* VM creates arrays using the BeginArray and EndArray instructions
* ArrayObj is implemented with a __str__ function (annoying)
* Simple example of array creation is added
Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
pest::Span and pest::Position both carry a ref to the input text, while
we carry an Rc<String> so we don't have to supply the lifetime
everywhere we use Spans (which is everywhere). They also calculate line
information on-the-fly, while we cache it.
Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
Compile::discover_locals now takes a Vec<SpExpr> instead of a single
SpExpr. It is also called before the compiler starts building the list
of instructions so that all names in the scope are available at
compile-time.
Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
There's some API design that I'm happy with so far but gives us some
unused code. I don't want to get rid of it so we'll just allow it for
now.
Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
PEG parser using pest is implemented. It was able to run the three
examples that we currently have so hopefully there aren't any huge
issues. There's a few warnings remaining that I will squash soon. Token,
parser, and token modules have been removed.
Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
* T and F were builtins that were created as functions. They have been
changed to just be global values instead, so you don't need to suffix
them with ! to get the creamy value inside.
Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
* `if` function stack ordering is changed to use condition, if-false,
if-true (bottom to top). This is so we can pass a value on top of the
stack directly to a new `if` in a condition, so we don't have to store
a new value in a new variable.
* Add __splat__ and __minus__ functions to Int
* Add * and - builtins, which call the __splat__ and __minus__ functions
of the top stack item, respectively.
* Add factorial example because now factorials are possible with this
skeleton implementation, albeit a little hacky with the recursion.
Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
* `if` builtin is the big one here - branching! Yay!
* The `if` builtin requires __bool__ to be implemented for things. This
is added for all builtin objects.
* Vtables have slightly better ergonomics.
Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
Since we're nightly and using coerce_unsized, we can just coerce a
Gc<T: Obj> into a Gc<dyn Obj> for free.
Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
Since we're able to coerce objects easily, we're changing bools to be
interned behind the scenes.
T and F builtin functions are added because that's probably the easiest
way to implement true and false constants without making new
lexer/parsing rules.
Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
Also, object.rs got moved to a new directory in preparation for
splitting members out into their own files
Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
I'm trying to remember why this was added in the first place - I think
to simplifly cloning? It's not important now though.
Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
* Obj is now a trait instead of a struct
* Value enum is gone, replaced with individual structs that implement
Obj
* All instances where a Value was used, a Gc<(dyn Obj + 'static)> takes
its place. ObjPtr is shorthand for this.
* A __str__ method for objects is implemented for a couple builtin types
as a proof-of-concept
* println and print builtin functions are implemented using this
interface
There's still a lot to do, mostly with interned values. For example,
whenever a new string object is created, a new __str__ function object
is created each time, rather than reusing the first one that was
created. Stuff like that.
Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
I just learned about thread local storage, so we really don't
lazy_static for anything anymore - it was only being used for the lexer
regex.
Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
I'm not writing my own GC, it's a huge pain in Rust. I'm using the gc
library instead.
Base object stuff implementation is here too. Hopefully going to start
using ObjPtr instead of Value next.
Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
Span was using the auto-implemented PartialCmp during testing, which was
interfering with the new "source" member, causing test failures.
PartialCmp of a Span during testing is now always true.
Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
Positions were being calculated by looking at the *first* character,
which would cause the same character to be visited twice. Now, if the
character is a null byte (\0), it won't advance the position at all.
The null byte should be a safe sentinel value to use because it
(hypothetically) shouldn't be showing up in a source file. This will
probably cause a hang if a file that starts with null bytes, but that's
a problem for future me.
Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
* RuntimeSpanError was an extraneous solution to adding spans to the
errors; so instead this behavior has been delegated to the
RuntimeError itself.
* Usage of Inst has mostly been replaced with SpInst so if an error is
encountered, we can spit out where it happened in the source code
(hopefully with a stack trace).
Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This allows us to write out errors that follow the call stack and give
locations to where errors originated.
Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This is the path to the location that this span is pointing to. This is
usually going to be a file path, but it can really be anything you want.
Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This helps split up expressions, meta calls (like includes) that can be
expanded into more expressions.
Signed-off-by: Alek Ratzloff <alekratz@gmail.com>