egranata / krakatau Goto Github PK
View Code? Open in Web Editor NEWKrakatau: a stack based virtual machine
License: Apache License 2.0
Krakatau: a stack based virtual machine
License: Apache License 2.0
It would be good to have iftrue <...> else <...> even if it is just a convenience operation
Define an operation bind
that creates a partial bind at runtime
The only tricky part about this is that "bind" is the name of a value type already, so it can't automagically just be the name of an operation for parsing purposes
One might consider having a table that contains a set of (name, value) pairs, some of which are data and other are operations (would it make sense to bind an operation to the value itself and put it into the table?)
Some kind of syntax sugar could be provided for "call one such operation", essentially making it a method call on an immutable object
Construction could happen via prototypes
There probably should be a 'character' value type and a string should just be a tuple of those values
More of a long-term idea, but consider a JSON format where one can describe, e.g. the types of inputs to an operation, or the keywords that can generate a value type, if any, and have C++ code be automatically generated at build time from this description
string
should have support for Unicode
Write - and push - interesting sample programs using Krakatau
This has at least two separate purposes:
The current class model for Operation has a few nice properties:
OTOH, it is fragile, hard to extend and relies extensively on macros.
It would be nice to keep these properties, but rework the model to allow new behaviors to be added in a more streamlined fashion.
A stack machine with two stacks is automagically Turing-complete
Numbers are currently uint64_t
It might be interesting to provide big numbers. This would likely come at a performance cost, but it should be possible to offer a variant<> so that one only pays (most of) the cost if needed
Split libcore
into a few smaller library targets, e.g. libvalue
, liboperation
, ...
This is largely about the "tetris test".
Provide a way to invoke "native" operations, e.g. file or network access.
Given a block with N slots, allow defining a partial bind of that block. For example, given
value foo block slots $a,$b,$c,$d
...
one could do something like
load foo
push number 1
push empty
bind
to obtain a block in two slots $c,$d, such that calling bound_foo(3,4)
would be equivalent to calling foo(1,empty,3,4)
(except the order would be inverted, because slots are popped last-to-first)
The object model around callable entities is more convoluted than it should be, having all separate objects for a bind vs. an operation vs. a block
In practice, operations are all that really exist and a bind/block should just be subclasses thereof
This would allow removing Value_Block and Value_Bind
At parse time, one would still check for bind
and block
and pick an appropriate subclass, but this should be no different than push
vs. dup
.
Allow filter
map
and reduce
to work on sets, and generally on all Iterable things
This would involve being able to - given a value of some iterable type - make a new value of that same type, and append things to it at runtime
This could be as simple as a convenience over table, so basically a table of values to boolean true for all elements in the set
Tuples, strings, tables and sets are "iterable", aka they contain other values that can be enumerated
Each operation that wants to act on this now needs to be extended to deal with different value types
There should be a common language of "iterable value" and looping over the elements of one
Add support for enumerations, i.e. types whose value can be one of a closed set of symbolic constants
bind
, the operation, is actually redundant.
What should actually happen is that, having a Value and a Value_Operation, one should pack them into a tuple, and then typecast the tuple to a Value_Bind
A lot of operation implementations have boilerplate of the form
if (!s.stack().hasAtLeast(2)) {
s.stack().push(Value::error(ErrorCode::INSUFFICIENT_ARGUMENTS));
return Operation::Result::ERROR;
}
This should somehow be automated such that one can just declare the argument count for an operation. There should be a provision for "unknown at compile time" and a provision for "completely unknown, will accept anything"
In the same vein as IterableValue, there should be additional "value traits" that allow defining operations on classes of values.
Examples include: AppendableValue for values that one can append new values to (e.g. tables and tuples); FindableValue for values that one can search by key out of (e.g. sets and tables)
Add support for floating point math
Consider an operation that given (tuple, value) and (table, tuple (value, value)) would create a new tuple or table that contains everything in the previous container AND also the new element
Consider allowing slots to have type hints on them, e.g.
slots number $a, string $b
which would introduce automated type checking and return a type error if the actual type does not match the declared type. This would have to be made optional, both in the sense that it need not exist, and in the sense that "any type is valid" should be allowed (coincidentally, the two would end up having the same semantics, but one might want an explicit any
marker for documentation purposes)
Define - immutable - named slots associated with a block's execution.
This would allow, for example, one to name the "arguments" to a block and then push them back onto the stack at any convenient time.
A program such as
value main block {
load main
exec
}
will eventually cause a segfault
It would be nice to catch this somehow (probably via signals), and do something intelligent
There should be a way for a native operation to return an "opaque handle" value, such that its type could be checked for "valid" and "associated to this operation" or at least "associated to this native library"
This could for example be used for a native library that provides file access to return a file descriptor object
CALL would be a convenience operation, e.g.
call foo (number 1, number 2, boolean false)
Would be equivalent to
push number 1
push number 2
push boolean false
load foo
exec
This is not, in general, possible, but - if "foo" is already available at the "call" site, the assembler could check that the list of arguments if of the same size as the slots, and emit a warning if not.
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.