The reimagining of quest, much faster and more fun.
(all todos are now on the github)
reworking quest, but faster
Right now, the standard lib is quite barren. (eg Float
doesn't even have a single function defined). Let's fix that.
:0.x = 3;
``` doesn't work, as `:0` has to be mutably borrowed twice
There's no way to explicitly reference the entire stack right now.
One concern is what should happen if the array is modified? or should it be immutable. And what should happen if the stack updates. Maybe it should be a snapshot of the stack at that point?
My current impl of macros wont have nested parens, so stuff like $syntax { foo { } } = { } ;
wont work.
This should be pretty easy, but there may be some circular deps that have to be resolved
There's a bug in function parameter assignment which doesn't assign values properly. This is separate from named argument mismatch issues
The following could should print xbxb
, but instead it prints xbbxbb
:
f = { "x".concat("b") };
print(f() + f());
This is because constants (at least, Text
constants, possibly others but I haven't investigated) are the same between calls. If this is just a Text
bug, then maybe we can just add a flag to Text
?
AnyValue
is lacking a lot of debug representations for types, and simply returns Unknown
Trying to run ```
block = { :0 };
print(block);
Yields `Message("attributes` are already locked")'`
Currently, argument parsing is explicitly only positional arguments. Adding splat arguments (both when passing to a block and declaring parameters) as well as keyword arguments would be nice
Quest1 had regex literal support, which I'm a big fan of. Let's add that in
Currently, there's no way to reference these values. The question is if we want the _0
, ... to be actual local variables or special ones. __arguments__
should be a local variable regardless I think.
Currently, order of operaitons are ignored: everything has the same precedence, and are parsed left-to-right: 2 + 3 * 5 = 17
and 2 * 3 + 5 = 16
.
This could be nice to have, but isnt necessary right now.
Allow the ability to resume stackframes.
There's still some rough edges that have to be ironed about with what exactly it means to resume a stackframe. For example, how should this work?:
x = sf -> { sf.resume() };
foo = { x(:0) + 3 };
foo()
One idea I had was resuming a stackframe starts on the next statement, but that requires keeping track of statements.
Right now, List::@text
uses the Debug
implementation of AnyValue
to get the string representation it should be using. That's not great, as it doesnt work for custom types, and not all types have a suitable Debug
representation.
Add in the $syntax
macros.
Rough EBNF:
syntax-decl := '$syntax' [ident] [':' number-literal] '{' matches '}' = '{' replacement '}' ;
matches := {match | atom | $[...] | ${...} | $(...) };
match := macro-ident ':' match-kind ; (* macro-ident is just an ident with `$` before it *)
match-kind := ident | '(' ... ')' ; (* ident is a group kind eg `expr`, whereas `(`...`)` can contain a union *)
replacement := (? normal quest code, except it can have macro idents and `$[`/`${`/`$(` which are expanded ?) ;
example usages:
$syntax {
do $body:block while $cond:expr
} = {
$body;
while($cond, $body);
};
$syntax {
if $icond:expr $ibody:block
${ else if $eicond:expr $eibody:block }
$[ else $ebody:block ]
} = {
# pretend like `Kernel::ifelseifelse` exists
Kernel::ifelseifelse($cond, $ibody, [ ${$eicond, $ibody,} ], $[$ebody])
};
# Whenever you talk about an `expr` (eg `$icond:expr`), this will be included.
# it has a precedence of 10 (/100), which means it's one of the first ones to check.
$syntax expr : 10 { $body:atom '!' } = { $body.factorial() } ;
expr
)${...}
and friends)expr
and friendsThis doesn't work:
x = 1;
x.y = 2;
print(x.y); #=> undefined attribute
I presume this has something to do with how stackframes are doing attribute access
In quest1, identifiers could start with @
(eg @text
, which was used for conversions) and end in ?
(for functions that should return a boolean, eg empty?
)
Since we no longer have predeclared operators, it seems weird to staple these two things onto identifiers. We could just replace @
with to_
and ?
with is_
.
Make sure to replace all the Intern
representations
deep_clone
was added as part of the "make stackframes able to access outer stackframes," but I never ended up finishing it.
Which you try accessing an invalid attribute, the stackframe just panics with an unhelpful error currently.
x = 0;
{
print(x);
}();
``` this doesn't see `x` properly
In the following code, should f
return 3
or an exception?
f = { x + 1 };
f.x = 2;
f().print();
I'm tempted towards no. Originally, I was thinking it could be a good way to use statics, but to set them you'd need to do
f = { :0.__parents__[0].x = x + 1 };
f.x = 2;
f().print();
f().print();
Which isn't great. How about:
f = { f.x + 1 };
f.x = 2;
f().print();
f().print();
Or even, if I end up adding the __block__
attribute:
f = { __block__.x + 1 };
f.x = 2;
f().print();
f().print();
Due to how attribute lookup semantics work, looking tryign to call dbg
on Integer
tries downcasting it to an Integer
instance. Since Integer
itself isn't an instance of Integer
, an error is raised.
I'm not sure if there's a good solution to this problem
For example, for statics:,
f = { __block__.x = __block__.x + 1 };
f.x = 2;
f().print();
f().print();
Previously, I thought it'd be a nice optimization to be able to have threads able to access the attributes and parents of an object at separate times. But I ended up implementing it with a mutex, which means that multiple threads cant access the attributes of any one object at a time, even if it's read access. So, multiple threads cant add integers at the same time.
The problem is it's somewhat deeply engrained, and so removing it's not a simple feat, and requires makign sure the surrounding code is sound.
To prepare for the $syntax
macros, I want to move the arguments of a block within the {...}
s. For a motivating example, let's say we use the optional () ->
for blocks:
$syntax {
if $cond:expr $body:block else $ebody:block
} = {
if($cond, $body, $ebody)
};
if foo == 'yup' () -> {
print('yup!');
} else () -> {
print('yup?');
};
Doesn't look great. Here's some alternatives i've been thiking about:
add = { |a, b| a + b }
->
: add = { a, b -> a + b }
in
: add = { a, b in a + b }
::
: add = { a, b :: a + b }
Ideally, the there'd be a token before and after them, as it'd make parsing it much easier (ie no backtracking), but i'm not sure if any syntax would look good like that. I like the ::
, and it is already a builtin token, so that might work
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.