Age | Commit message (Collapse) | Author |
|
|
|
|
|
|
|
It picks up the wrong test util library right now.
|
|
|
|
Now the comparison is done in assembly, using quads for
checking the larger loop, and words for the smaller.
|
|
|
|
Maybe we can make it do something useful later.
|
|
|
|
|
|
We don't necessarily know the type of the array index until
after substituting, so things like sizeof() or constant
folding may not work.
|
|
The size parameter *may* be null.
|
|
Because of low resolution clocks, we need to be conservative
and assume that if a timestamp is equal, we may be up to a
second out of date.
|
|
Before, code like:
const f = {
var buf: byte[sizeof(int)]
}
would crash us, because `sizeof` would not get folded.
A slightly subtle point: muse doens't install a hook here,
but since it's already handling processed usefiles, the
array sizes should already be prefolded for its viewing
pleasure.
|
|
Soon enough, it's going to use a strict equality comparison,
so that params from different scopes will be considered
different.
It's a step towards deduping.
|
|
tydedup does the job.
|
|
This should clear the way for better deduplication.
|
|
Hello,
I wrote this patch to start a conversation about resource
management in Myrddin.
~ Introduction
~~~~~~~~~~~~~~
The patch attached provides a hopefully life-improving and
surely non-invasive mechanism to handle resources that have
block-limited lifetimes: automatic variables.
This resource-management scheme can be found in multiple
languages today. For example, C++ calls destructors
automatically at the end of the scope of a variable;
similarly, Rust automatically calls user-defined code
when a variable's scope ends; finally, also related is
Go's defer statement which ensures that resource-releasing
code is called at the end of a function.
~ Description
~~~~~~~~~~~~~
The idea is that every "binder" of the language (var/const/
fn args/match) offers the possibility to mark the variables
it binds as "automatic" using the 'auto' keyword.
An automatic variable must be of a type that implements
the new builtin 'disposable' trait below. When the scope
of a variable 'v' marked as automatic ends, '__dispose__(v)'
is called.
That's it.
trait disposable @a =
__dispose__ : (val : @a -> void)
;;
~ Example Programs
~~~~~~~~~~~~~~~~~~
The language modification is shown in action in the program
below.
use std
impl disposable int =
__dispose__ = {x
std.put("__dispose__({})\n", x)
}
;;
const g = {auto x
-> x++ - 1
}
const main = {
var auto i, auto j = 42
for i = 1; i < 6; i=i+1
var auto z : int = 2*i
if i == 3
std.put("z = {} -- cont\n", z)
continue
;;
std.put("z = {}\n", z)
if i/2 == 2
var auto inner : int = 1234
break
;;
;;
i = g(321)
}
The output of the previous test program is:
1: z = 2
2: __dispose__(2)
3: z = 4
4: __dispose__(4)
5: z = 6 -- cont
6: __dispose__(6)
7: z = 8
8: __dispose__(1234)
9: __dispose__(8)
10: __dispose__(322)
11: __dispose__(42)
12: __dispose__(320)
Some important remarks:
* Unlike Go, __dispose__ is called as soon as the scope
of a variable ends, not at the end of the function.
In particular, the variable 'z' in the example is
always disposed of before starting the next iteration.
(An iteration ends the loop body block.)
* __dispose__ is called in reverse order of declaration
This allows variables to depend on resources of
variables already in scope.
* Regardless of how a block is exited (fallthrough,
break, continue, return), variables of the blocks left
are disposed of in reverse order and exactly once.
* As line 10 of the output shows, the __dispose__ calls
happen "after" the return statement of the function.
(It happens after the post-increment, so x's value
when it is disposed of is 322.)
The following example shows that, using an ad hoc type,
it is possible to execute arbitrary code at the end of
a scope.
type defer = (-> void)
impl disposable defer =
__dispose__ = {f: defer; f()}
;;
const foobar = {...
const auto _dummy = ({
std.put("Bye!\n")
}: defer)
...
}
~ Discussion
~~~~~~~~~~~~
Multiple alternatives exist for resource management, and
hopefully this mail starts an interesting debate.
According to me, here are the pros and cons of the current
proposal:
- PROS -
* Opt-in
* Backward compatible
* Simple
* The spirit of C's original auto
* It has an implementation
- CONS -
* No safety guarantees/compiler checks whatsoever
* Syntactic pollution: 'auto' keyword, 'disposable' trait
Finally, note that the current patch does not implement
auto support for variables bound in match statements.
This will come in a followup patch if there is sufficient
interest. Also, the patch does not provide proper support
(or proper errors) for gotos and labels.
|
|
|
|
std.no std.on std.every std.name std.you std.use.
The rules for an un-namespaced name now are as follows:
1) Attempt to look up a name in the current file.
2) Check all namespaces for a unique name. If the
name is not globally unique, give an error.
|
|
A const works perfectly fine.
|
|
stupid shit like:
const foo : (bar : baz, blah, here -> void)
should not miscompile any more.
|
|
|
|
That's what the new muse generates.
|
|
|
|
|
|
- FreeBSD
- Linux
- Plan 9
- OSX
- OpenBSD
- NetBSD
|
|
Grab mbld from the right place.
|
|
|
|
We were using the wrong name.
|
|
|
|
Wait for all launched processes to exit before quitting.
|
|
Currently, it's unconditional.
|
|
|
|
When developing this out of tree, this was not needed.
Now it is.
|
|
It just returns a hard-coded value, but that should be good
enough for correctness.
|
|
Match patterns can't be null. They haven't been nullable
for ages. And even if they could be nullable, $2 isn't the
match statement any more.
|
|
|
|
|
|
|
|
It's a tad stricter about a couple of things.
|
|
|
|
Also, it's going to go away in the new mbld.
|
|
|
|
This sucks, but it's *extremely* unlikely that a file
will share a namespace, filename, and __init__.
This makes builds directory-independent, so that linking
the same file compiled with a different compiler cwd will
work.
|
|
|
|
Although the data structure works no matter the initial contents of
livedense and livesparse, malloc returns a pointer to indeterminate
values, and accessing an indeterminate value is undefined behavior.
This also avoids spurious valgrind errors when debugging.
|
|
The first h *= m after the loop should only happen for len % 4 != 0.
|
|
|
|
The winds of change are a-blowin.
|