summaryrefslogtreecommitdiff
path: root/parse
AgeCommit message (Collapse)Author
2017-07-31Move array size checking to verification.Ori Bernstein
We don't necessarily know the type of the array index until after substituting, so things like sizeof() or constant folding may not work.
2017-07-31Handle empty array sizes correctly.Ori Bernstein
The size parameter *may* be null.
2017-07-30Add hook into frontend for sizeof() folding.Ori Bernstein
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.
2017-07-29Don't use tyhash for scoping.Ori Bernstein
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.
2017-07-29Eliminate the deduptab.Ori Bernstein
tydedup does the job.
2017-07-29Finally do a by-scope comparison of generic types.Ori Bernstein
This should clear the way for better deduplication.
2017-07-29Automatic variablesOri Bernstein
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.
2017-07-28Fix error message for generics in non-generic decls.Ori Bernstein
2017-07-27std.change std.name std.lookup std.rules.Ori Bernstein
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.
2017-07-26Be stricter about declarations in function types.Ori Bernstein
stupid shit like: const foo : (bar : baz, blah, here -> void) should not miscompile any more.
2017-07-26Whitespace fixes.Quentin Carbonneaux
2017-07-25Remove spandrels.Ori Bernstein
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.
2017-07-21This function is long dead.Ori Bernstein
2017-07-19Only use the filename itself for __init__Ori Bernstein
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.
2017-07-17Start migrating code to use `for x : iterable`.Ori Bernstein
`in` is too good of a variable name to waste on a loop iterator specifier.
2017-07-15Wrap overlong line.Ori Bernstein
2017-07-15Remove unused extern var.Ori Bernstein
2017-07-15Inline remapping function.Ori Bernstein
Easier to read, clearer what's going on.
2017-07-15Use type hashing instead of string hasing in tyenv.Ori Bernstein
Set the stage for stricter env lookups.
2017-07-15Type binding refactoring now compiles.Ori Bernstein
Still a bit sloppy on a few things, needs some dedup work, but it's working.
2017-07-12Add support for -O in 6m.Ori Bernstein
First step to not polluting source dirs.
2017-07-10Remove unused enum.Ori Bernstein
2017-07-10Clean up conditions in trait satisfaction.Ori Bernstein
2017-07-09Remove stupid comments.Ori Bernstein
2017-07-09Mark things as static.Ori Bernstein
2017-07-09Clean up some indentation.Ori Bernstein
2017-07-09Inferstate is global.Ori Bernstein
Fuck it, might as well treat it that way.
2017-07-09Style(9)-ify.Ori Bernstein
2017-07-09Don't allow hidden decls to clobber each other.Ori Bernstein
Hidden decls are still global, which means that if two modules define them, they are going to alias to the same symbol. This can lead to really painful to debug errors, since writes to one variable that seems to be file-local will cause some other variable in some other unrelated file to get clobbered. This turns the situation into a compile-time error.
2017-07-08Remap type params according to bound scope.Ori Bernstein
Getting closer to scoping type params properly. Still not fully there.
2017-07-08Factor out genericness checks.Ori Bernstein
It's the same on every use, might as well put it into the function.
2017-07-06Cleaner/correcter version of the termination condition.Ori Bernstein
It isn't entirely equivalent, but the cases where it returns true should be the same. And it shouldn't return false early.
2017-07-06Fix up the type equality checking.Ori Bernstein
2017-07-06Fix unused name in error message.Ori Bernstein
2017-07-06Remove double recursion.Ori Bernstein
2017-07-05Add some discipline to type bindings.Ori Bernstein
We actually now do it in terms of scopes. It's still hacky, but...
2017-07-03Function args should go into the block stab.Ori Bernstein
Now we get errors if a function body shadows its args.
2017-07-03Actually mark void arg lists as void.Ori Bernstein
2017-07-03Errors are conventionally lowercase.Ori Bernstein
2017-07-03Clean up formatting of error reporting.Ori Bernstein
2017-07-03Clean up indentation of comments.Ori Bernstein
2017-07-03Specialize impl declarations on impl type in addition to decl typeMichael Forney
This allows multiple specializations of a declarations with a concrete type, which can be selected with the new impl expression if it can't be deduced by its type alone. For example trait hasname @t = Name: byte[:] ;; impl hasname void = Name = "somename" ;; impl hasname bool = Name = "othername" ;; const boolname = impl(Name, void) To do this, pass the param type through to genericname and specializedcl. Since we now need the type parameter to look up trait decls, make sure n->expr.param gets the necessary treatment in typesub, specializenode, pickle, and unpickle. We also need to tag the param types for export.
2017-07-03Add impl(type, name) to retrieve a particular implementation of a trait declMichael Forney
This avoids having to create a temporary variable when you know what implementation your want for a generic constant or function with generic return value. Re-use the impl keyword for this expression to avoid invalidating existing programs.
2017-07-03Resolve trait decl types before fixing themMichael Forney
Otherwise, if the decl has a named type with parameters, it remains unresolved until tyfix. tyfix looks up the tid in tytab, finding the original definition of the named type, which may have different type parameter names than than used in the trait decl. Upon importing this trait from a use file and writing a new impl, we end up trying to resolve type parameters of the *definition* of the named type, rather than what is specified in the trait decl type. If both type parameters are the same, we don't notice a problem, but if they differ, we end up trying to serialize a Tyvar in genericname. tyvar has no idstr
2017-07-03Write trait IDs instead of indices in typickleMichael Forney
If trait prototypes are used and merged with the actual trait, there may be entries in the trait table which have an ID corresponding to some other entry. When pickling types, write the trait ID instead of the index since the trait definitions are written with their IDs. Otherwise, we may end up reading types referring to non-existent traits, resulting in an error like Unable to find trait for id 7 Also, only pickle traits whose index matches its ID to avoid duplicates.
2017-07-03Fix indentationMichael Forney
2017-06-30TyposMichael Forney
2017-06-30Use switch statement in postcheckpassMichael Forney
We don't need to check for Nexpr since exprop asserts e->type == Nexpr.
2017-06-30Remove unused traitlist from Type structMichael Forney
2017-06-28Update ABI version.Ori Bernstein