Restructuring the parser & split parser into parts. Parsing more constructs now, like enums with extended syntax. Corrected handling of function block to be an expression. Added expression block codegen.

This commit is contained in:
Christoffer Lerno
2020-03-14 12:22:31 +01:00
parent 2e3bbf119c
commit f4b4bab947
31 changed files with 4482 additions and 4048 deletions

View File

@@ -90,7 +90,8 @@ func int CompInfo.findClosureVar(CompInfo *comp, Value varnm)
}
/** If variable not declared already, declare it */
void declareLocal(CompInfo *comp, Value varnm) {
void CompInfo.declareLocal(CompInfo *comp, Value varnm)
{
Value th = comp->th;
// If explicit 'local' declaration, declare if not found in block list
if (comp->forcelocal) {
@@ -103,7 +104,7 @@ void declareLocal(CompInfo *comp, Value varnm) {
if (comp->prevcomp!=aNull && findLocalVar((CompInfo*)comp->prevcomp, varnm)!=-1) {
arrAdd(th, comp->clovarseg, varnm);
// Add initialization logic
astAddSeg2(th, comp->newcloseg, vmlit(SymLocal), varnm); // Add its initialization to new closure segment
astAddSeg2(th, comp->newcloseg, vmlit(SYM_LOCAL), varnm); // Add its initialization to new closure segment
}
else
arrAdd(th, comp->locvarseg, varnm);
@@ -115,15 +116,15 @@ func Value parseNewClo(CompInfo* comp, Value astseg)
{
Value th = comp->th;
// ('Closure', clovars, ('callprop', Closure, New, getmethod, setmethod))
Value closeg = ast::addSeg(th, astseg, vmlit(SymClosure), 3);
Value closeg = ast::addSeg(th, astseg, vmlit(SYM_CLOSURE), 3);
comp->clovarseg = pushArray(th, aNull, 4);
arr::add(th, closeg, comp->clovarseg);
th.popValue();
Value newcloseg = ast::addSeg(th, closeg, vmlit(SymCallProp), 8);
ast::addSeg2(th, newcloseg, vmlit(SymGlobal), vmlit(SymClosure));
ast::addSeg2(th, newcloseg, vmlit(SymLit), vmlit(SymNew));
ast::addSeg2(th, newcloseg, vmlit(SymLit), vmlit(SymNull));
ast::addSeg2(th, newcloseg, vmlit(SymLit), vmlit(SymNull));
Value newcloseg = ast::addSeg(th, closeg, vmlit(SYM_CALL_PROP), 8);
ast::addSeg2(th, newcloseg, vmlit(SYM_GLOBAL), vmlit(SYM_CLOSURE));
ast::addSeg2(th, newcloseg, vmlit(SYM_LIT), vmlit(SYM_NEW));
ast::addSeg2(th, newcloseg, vmlit(SYM_LIT), vmlit(SYM_NULL));
ast::addSeg2(th, newcloseg, vmlit(SYM_LIT), vmlit(SYM_NULL));
return newcloseg;
}
@@ -134,12 +135,12 @@ void parseValue(CompInfo* comp, Value astseg)
// Literal token (number, symbol, string, true, false, null)
if (comp->lex->toktype == Lit_Token)
{
ast::addSeg2(th, astseg, vmlit(SymLit), comp.lex.token);
ast::addSeg2(th, astseg, vmlit(SYM_LIT), comp.lex.token);
lexGetNextToken(comp->lex);
}
// Static unquoted @url
else if (comp->lex->toktype == Url_Token) {
astAddSeg2(th, astseg, vmlit(SymExt), anInt(genAddUrlLit(comp, comp->lex->token)));
astAddSeg2(th, astseg, vmlit(SYM_EXT), anInt(genAddUrlLit(comp, comp->lex->token)));
lexGetNextToken(comp->lex);
}
// Local or global variable / name token
@@ -151,33 +152,36 @@ void parseValue(CompInfo* comp, Value astseg)
if (lexMatch(comp->lex, ":") || lexMatch(comp->lex, ":="))
astAddSeg2(th, astseg, vmlit(SymLit), symnm);
else if (first=='$' || (first>='A' && first<='Z'))
astAddSeg2(th, astseg, vmlit(SymGlobal), symnm);
else {
declareLocal(comp, symnm); // declare local if not already declared
{
astAddSeg2(th, astseg, vmlit(SYM_GLOBAL), symnm);
}
else
{
comp.declareLocal(symnm); // declare local if not already declared
// We do not resolve locals to index until gen because of control clauses (declaration after use)
astAddSeg2(th, astseg, vmlit(SymLocal), symnm);
astAddSeg2(th, astseg, vmlit(SYM_LOCAL), symnm);
}
popValue(th);
}
// 'baseurl' pseudo-variable
else if (lexMatchNext(comp->lex, "baseurl")) {
astAddValue(th, astseg, vmlit(SymBaseurl));
astAddValue(th, astseg, vmlit(SYM_BASEURL));
}
// 'this' pseudo-variable
else if (lexMatchNext(comp->lex, "this")) {
astAddValue(th, astseg, vmlit(SymThis));
astAddValue(th, astseg, vmlit(SYM_THIS));
}
// 'self' pseudo-variable
else if (lexMatchNext(comp->lex, "self")) {
astAddValue(th, astseg, vmlit(SymSelf));
astAddValue(th, astseg, vmlit(SYM_SELF));
}
// 'selfmethod' pseudo-variable
else if (lexMatchNext(comp->lex, "selfmethod")) {
astAddValue(th, astseg, vmlit(SymSelfMeth));
astAddValue(th, astseg, vmlit(SYM_SELF_METH));
}
// 'context' pseudo-variable
else if (lexMatchNext(comp->lex, "context")) {
astAddValue(th, astseg, vmlit(SymContext));
astAddValue(th, astseg, vmlit(SYM_CONTEXT));
}
// '...' splat
else if (lexMatchNext(comp->lex, "...")) {
@@ -285,7 +289,8 @@ void parseValue(CompInfo* comp, Value astseg)
}
/** Add a list of parameters to a AST propseg */
void parseParams(CompInfo* comp, Value propseg, const char *closeparen) {
func void CompInfo.parseParams(CompInfo* comp, Value propseg, const char *closeparen)
{
bool saveforcelocal = comp->forcelocal;
comp->forcelocal = false;
@@ -330,7 +335,7 @@ void parseTerm(CompInfo* comp, Value astseg) {
else if (lexMatchNext(comp->lex, "[")) {
astSetValue(th, propseg, 0, vmlit(SymCallProp)); // adjust because of parms
astAddSeg2(th, propseg, vmlit(SymLit), vmlit(SymBrackets));
parseParams(comp, propseg, "]");
comp.parseParams(propseg, "]");
getparms = false;
}
// Handle '.', '.:', and '::'
@@ -367,7 +372,7 @@ void parseTerm(CompInfo* comp, Value astseg) {
if (getparms) {
if (lexMatchNext(comp->lex, "(")) {
astSetValue(th, propseg, 0, vmlit(SymCallProp)); // adjust because of parms
parseParams(comp, propseg, ")");
comp.parseParams(propseg, ")");
}
// Treat Text or Symbol literal as a single parameter to pass
else if (comp->lex->toktype == Lit_Token && (isStr(comp->lex->token) || isSym(comp->lex->token))) {
@@ -394,7 +399,7 @@ void parsePrefixExp(CompInfo* comp, Value astseg) {
else { // Not a literal number? Do the property call
astseg = astInsSeg(th, astseg, vmlit(SymCallProp), 3);
Value litseg = astAddSeg(th, astseg, vmlit(SymLit), 2);
astAddValue(th, litseg, vmlit(SymNeg));
astAddValue(th, litseg, vmlit(SYM_NEG));
}
}
// '@' + symbol, text or '('exp')'

View File

@@ -3,7 +3,7 @@ module acornvm::value;
/** A convenience macro for assert(), establishing the conditions expected to be true,
* before returning expression e */
macro @assert_exp($c, auto $e)
macro assert_exp($c, $e)
{
assert($c);
return $e;
@@ -54,7 +54,7 @@ typedef func int(Value) as AcMethodp;
* Great for null, false, true, integers and symbols.
* Less suitable for floats (no epsilon) and comparing contents of containers (e.g., strings).
* Is fast because it avoids using type-specific methods. */
macro @isSame(a, b) { return (a == b); }
macro isSame(a, b) { return (a == b); }
/** What type of data is encoded within the value, as established by the last 2 bits.
* Because of 32/64-bit allocation alignment, pointers always have 0 in last 2 bits.
@@ -84,9 +84,9 @@ bool Value.isStr(Value *str)
return str.isEnc(StrEnc) && !(str_info(str)->flags1 & StrCData);
}
macro @isType(v, ValBits e)
macro isType(v, ValBits e)
{
return @cast(v, Auint) & VAL_MASK == e;
return cast(v, Auint) & VAL_MASK == e;
}
// Integer value functions
@@ -101,16 +101,16 @@ func bool Value.isInt(Value *v)
/** Cast c-integer n into an Integer value
* This loses top two-bits of integer precision.
* If integer is too large, this could result in an unexpected value and change of sign. */
macro @anInt(n)
macro anInt(n)
{
return @cast(@cast(n, Aint) << VAL_SHIFT + ValInt, Value);
return cast(cast(n, Aint) << VAL_SHIFT + ValInt, Value);
}
/** Cast an Integer value into a c-integer
* Note: It assumes (and won't verify) that v is an Integer */
macro @toAint(v)
macro toAint(v)
{
return @cast(v, Aint) >> VAL_SHIFT;
return cast(v, Aint) >> VAL_SHIFT;
}
// Float value functions
@@ -135,19 +135,19 @@ AVM_API Afloat toAfloat(Value v);
**************************************************** */
/** The null value */
macro @aNull()
macro aNull()
{
return @cast(0 << VAL_SHIFT, ValCons, Value);
}
/** The false value */
macro @aFalse()
macro aFalse()
{
return @cast(1 << VAL_SHIFT + ValCons, Value);
}
/** The true value */
macro @aTrue()
macro aTrue()
{
return @cast(2 << VAL_SHIFT + ValCons, Value);
}

View File

@@ -96,100 +96,100 @@ const N_STD_SYM = 256;
/** C index values for all VM literal values used throughout the code
for common symbols and core types. They are forever immune from garbage collection
by being anchored to the VM. */
enum VmLiterals
enum VmLiteral : int (string name = nil)
{
// Compiler symbols
SYM_NULL, //!< 'null'
SYM_FALSE, //!< 'false'
SYM_TRUE, //!< 'true'
SYM_AND, //!< 'and'
SymAsync, //!< 'async'
SymBaseurl, //!< 'baseurl'
SymBreak, //!< 'break'
SymContext, //!< 'context'
SymContinue, //!< 'continue'
SymDo, //!< 'do'
SymEach, //!< 'each'
SymElse, //!< 'else'
SymElif, //!< 'elif'
SymIf, //!< 'if'
SymIn, //!< 'in'
SymInto, //!< 'into'
SymMatch, //!< 'match'
SymNot, //!< 'not'
SymOr, //!< 'or'
SymReturn, //!< 'return'
SymSelf, //!< 'self'
SymSelfMeth, //!< 'selfmethod'
SymThis, //!< 'this'
SymUsing, //!< 'using'
SYM_NULL("null"),
SYM_FALSE("false"),
SYM_TRUE("true"),
SYM_AND("and"),
SYM_ASYNC("async"),
SYM_BASE_URL("baseurl"),
SYM_BREAK("break"),
SYM_CONTEXT("context"),
SYM_CONTINUE("continue"),
SYM_DO("do"),
SYM_EACH("each"),
SYM_ELSE("else"),
SYM_ELIF("elif"),
SYM_IF("if"),
SYM_IN("in",
SYM_INTO("into"),
SYM_MATCH("match"),
SYM_NOT("not"),
SYM_OR("or"),
SYM_RETURN("return"),
SYM_SELF("self",
SYM_SELF_METH("selfmethod"),
SYM_THIS("this"),
SYM_USING("using"),
SymVar, //!< 'var'
SymWait, //!< 'wait'
SymWhile, //!< 'while'
SymWith, //!< 'with'
SymYield, //!< 'yield'
SymLBrace, //!< '{'
SymRBrace, //!< '}'
SymSemicolon, //!< ';'
SymComma, //!< ','
SymQuestion, //!< '?'
SymAt, //!< '@'
SymSplat, //!< '...'
SymDot, //!< '.'
SymColons, //!< '::'
SymDotColon, //!< '.:'
SYM_WAIT("wait"),
SYM_WHILE("while"),
SYM_WITH("with"),
SYM_YIELD("yield",
// Compiler symbols that are also methods
SymAppend, //!< '<<'
SymPrepend, //!< '>>'
SymPlus, //!< '+'
SymMinus, //!< '-'
SymMult, //!< '*'
SymDiv, //!< '/'
SymRocket, //!< '<=>'
SymEquiv, //!< '==='
SymMatchOp, //!< '~~'
SymLt, //!< '<'
SymLe, //!< '<='
SymGt, //!< '>'
SymGe, //!< '>='
SymEq, //!< '=='
SymNe, //!< '!='
SYM_LBRACE("{"),
SYM_RBRACE("}"),
SYM_SEMICOLON(";"),
SYM_COMMA(","),
SYM_QUESTION("?"),
SYM_AT("@"),
SYM_SPLAT("..."),
SYM_DOT("."),
SYM_COLONS("::"),
SYM_DOT_COLON(".:"),
// Methods that are not compiler symbols
// Byte-code (and parser) standard methods
SYM_NEW, //!< 'New'
SYM_INIT, //!< 'Init'
SYM_LOAD, //!< 'Load'
SymGet, //!< 'Get'
SymParas, //!< '()'
SymBrackets, //!< '[]'
SymNeg, //!< '-@'
SymValue, //!< 'value'
SymEachMeth, //!< 'Each'
SymBegin, //!< 'Begin'
SymEnd, //!< 'End'
// Compiler symbols that are also methods
SYM_APPEND("<<"),
SYM_PREPENT(">>"),
SYM_PLUS("+"),
SYM_MINUS("-"),
SYM_MULT("*"),
SYM_DIV("/"),
SYM_ROCKET("<=>"),
SYM_EQUIV("==="),
SYM_MATCHOP("~~"),
SYM_LT("<"),
SYM_LE("<="),
SYM_GT(">"),
SYM_GE(">="),
SYM_EQ("=="),
SYM_NE("!="),
SymFinalizer, //!< '_finalizer' method for CData
SymName, //!< '_type' symbol
// Methods that are not compiler symbols
// Byte-code (and parser) standard methods
SYM_NEW("New"),
SYM_INIT("Init"),
SYM_LOAD("Load"),
SYM_GET("Get"),
SYM_PARAS("()"),
SYM_BRACKETS("[]"),
SYM_NEG("-@"),
SYM_VALUE("value"),
SYM_EACH_METH("Each"),
SYM_BEGIN("Begin"),
SYM_END("End"),
// AST symbols
SymMethod, //!< 'method'
SymAssgn, //!< '='
SymOrAssgn, //!< '||='
SymColon, //!< ':'
SymThisBlock, //!< 'thisblock'
SymCallProp, //!< 'callprop'
SymActProp, //!< 'activeprop'
SymRawProp, //!< 'rawprop'
SymGlobal, //!< 'global'
SymLocal, //!< 'local'
SymLit, //!< 'lit'
SymExt, //!< 'ext'
SymRange, //!< 'Range'
SymClosure, //!< 'Closure'
SymYielder, //!< 'Yielder'
SymResource, //!< 'Resource'
SYM_FINALIZER("_finalizer") // method for CData
SYM_NAME('_type') // symbol
// AST symbols
SYM_METHOD("method"),
SYM_ASSGN("="),
SYM_OR_ASSGN("||="),
SYM_COLON(":"),
SYM_THIS_BLOCK("thisblock"),
SYM_CALL_PROP("callprop"),
SYM_ACT_PROP("activeprop"),
SYM_RAW_PROP("rawprop"),
SYM_LOCAL("local"),
SYM_LIT("lit"),
SYM_EXT("ext"),
SYM_RANGE("Range"),
SYM_CLOSURE("Closure"),
SYM_YIELDER("Yielder"),
SYM_RESOURCE("Resource"),
// Core type type
TypeObject, //!< Type
@@ -229,11 +229,15 @@ enum VmLiterals
nVmLits
}
macro @vmlit!(lit) { return arr_inf(vm(th)->literals)->arr[list]; }
macro vmlit!(VmLiteral lit)
{
return arr_inf(vm(th)->literals)->arr[list];
}
/** Used by vm_init to build random seed */
macro @memcpy_Auint(i, val)
macro memcpy_Auint(i, val)
{
Auint anint = @cast(val, Auint);
memcpy(seedstr + i * sizeof(Auint), &anint, sizeof(Auint));
@@ -397,95 +401,8 @@ struct vmLitSymEntry
/** Constant array that identifies and maps all VM literal symbols */
vmLitSymEntry[+] vmLitSymTable = {
// Compiler reserved names
{SymNull, "null"},
{SymFalse, "false"},
{SymTrue, "true"},
{SymAnd, "and"},
{SymAsync, "async"},
{SymBaseurl, "baseurl"},
{SymBreak, "break"},
{SymContext, "context"},
{SymContinue, "continue"},
{SymDo, "do"},
{SymEach, "each"},
{SymElse, "else"},
{SymElif, "elif"},
{SymIf, "if"},
{SymIn, "in"},
{SymInto, "into"},
{SymLocal, "local"},
{SymMatch, "match"},
{SymNot, "not"},
{SymOr, "or"},
{SymReturn, "return"},
{SymSelf, "self"},
{SymSelfMeth, "selfmethod"},
{SymThis, "this"},
{SymUsing, "using"},
{SymWait, "wait"},
{SymWhile, "while"},
{SymWith, "with"},
{SymYield, "yield"},
{SymLBrace, "{"},
{SymRBrace, "}"},
{SymSemicolon, ";"},
{SymComma, ","},
{SymQuestion, "?"},
{SymAt, "@"},
{SymSplat, "..."},
{SymDot, "."},
{SymColons, "::"},
{SymDotColon, ".:"},
// Compiler symbols that are also methods
{SymAppend, "<<"},
{SymPrepend, ">>"},
{SymPlus, "+"},
{SymMinus, "-"},
{SymMult, "*"},
{SymDiv, "/"},
{SymRocket, "<=>"},
{SymEquiv, "==="},
{SymMatchOp, "~~"},
{SymLt, "<"},
{SymLe, "<="},
{SymGt, ">"},
{SymGe, ">="},
{SymEq, "=="},
{SymNe, "!="},
// Methods that are not compiler symbols
{SymNew, "New"},
{SymInit, "Init"},
{SymLoad, "Load"},
{SymGet, "Get"},
{SymParas, "()"},
{SymBrackets, "[]"},
{SymNeg, "-@"},
{SymValue, "value"},
{SymEachMeth, "Each"},
{SymBegin, "Begin"},
{SymEnd, "End"},
{SymFinalizer, "_finalizer"},
{SymName, "_name"},
// AST symbols
{SymMethod, "method"},
{SymAssgn, "="},
{SymOrAssgn, "||="},
{SymColon, ":"},
{SymThisBlock, "thisblock"},
{SymCallProp, "callprop"},
{SymActProp, "activeprop"},
{SymRawProp, "rawprop"},
{SymGlobal, "global"},
{SymLit, "lit"},
{SymExt, "ext"},
{SymRange, "Range"},
{SymClosure, "Closure"},
{SymYielder, "Yielder"},
{SymResource, "Resource"},
// End of literal table
{0, NULL}
@@ -504,23 +421,23 @@ void vm_litinit(Value th) {
// Load up literal symbols from table
const struct vmLitSymEntry *vmlittblp = &vmLitSymTable[0];
while (vmlittblp->symnm) {
newSym(th, &vmlits[vmlittblp->litindex], vmlittblp->symnm, strlen(vmlittblp->symnm));
vmlittblp++;
for (VmLiteral i = 0; i <= SYM_RESOUCE; i++)
{
newSym(th, &vmlits[i], i.name);
}
}
/** Map byte-code's standard symbols to VM's literals (max. number at 256) */
const int stdTblMap[] = {
// Commonly-called methods
SymNew, // 'new'
SymParas, // '()'
SymAppend, // '<<'
SymPlus, // '+'
SymMinus, // '-'
SymMult, // '*'
SymDiv, // '/'
SymNeg, // '-@'
SYM_NEW, // 'new'
SYM_PARAS, // '()'
SYM_APPEND, // '<<'
SYM_PLUS, // '+'
SYM_MINUS, // '-'
SYM_MULT, // '*'
SYM_DIV, // '/'
SYM_NET, // '-@'
-1
};

View File

@@ -2,7 +2,9 @@ import curl;
func int main(void)
{
try Curl curl = curl::newCurl();
Curl curl;
try curl.init();
catch (error e)
{

View File

@@ -4,7 +4,7 @@ import regex, stdio;
func void main()
{
println("Enter a story template, terminated by an empty line:");
string@ story = "";
string story = "";
while (1)
{
try string line = stdin.readln().strip();
@@ -12,7 +12,10 @@ func void main()
story += line + "\n";
}
Regex* r = try regex::regexWithOptions("<.+?>", RegexOpt.GLOBAL) catch @unreachable;
Regex r;
r.initWithOptions("<.+?>", RegexOpt.GLOBAL) else @unreachable;
defer r.destroy();
foreach (RegexMatch* match : r.match(story))
{

View File

@@ -3,9 +3,9 @@ module map(Key, Type);
public struct Entry
{
Key key;
Type *value;
Type* value;
usize hash;
Entry *next;
Entry* next;
}
public struct Map
@@ -92,10 +92,10 @@ public macro Vector.foreach(Vector *vector, macro void(Type value) body)
test
{
define IntVector = Vector(int);
IntVector *vector = @calloc(IntVector);
IntVector vector = vector.init();
vector.add(1);
vector.add(2);
foreach (int i : vector)
for (int i : vector)
{
printDigit(i);
}
@@ -103,4 +103,5 @@ test
{
printDigit(i);
}
vector.destroy();
}

View File

@@ -5,9 +5,9 @@ public struct Vector
Type[*] array;
}
public func Vector@ newVector()
public func void Vector.init()
{
return @calloc(Vector);
array = nil;
}
public func void Vector.add(Vector *vector, Type type)

View File

@@ -5,7 +5,7 @@ uint counter = 0;
func void clickedme(GtkButton *o, void *d)
{
cast(GtkLabel*, d).set_text(string.format("You clicked me %d times", ++counter));
cast(d, GtkLabel*).set_text(string.format("You clicked me %d times", ++counter));
}
int main(int argc, string[] argv)

View File

@@ -228,11 +228,40 @@ func int jumpback(int x)
x += 3;
}
}
if (x < 100) goto LABELX;
return x + 1;
}
func void test_expr_block(int x)
{
int a = ({
if (x > 0) return x * 2;
if (x == 0) return 100;
return -x;
});
//printf("The result was %d\n", a);
}
func int expr_block()
{
int fok = ({ return ({ return 10; }); });
int y = 2;
int x = ({
if (y < 10) return 10;
return 2;
});
/* ({
return 3;
});*/
return x;
}
func int xxxx(int x)
{
{
x += 10;
defer printf("XXX");
@@ -306,7 +335,7 @@ func int main(int x)
int ef = 3;
int *eff = &ef;
eff[0] = 4;
byte *ex = cast(byte *, eff);
byte *ex = cast(eff, byte*);
ex[0] = 5;
if (eff[0] == 5) printf("Works-5!\n");
ex[1] = 5;
@@ -321,7 +350,8 @@ func int main(int x)
bool eok = true;
long deee = (eok ? a : b) + (eok ? b : c);*/
int i = 0;
JUMP:
JUMP:
i = i + 1;
//@hello();
printf("Hello worldABC" "D" "E\u2701\n");
@@ -352,7 +382,7 @@ JUMP:
func void test2(int* x, int y, int z)
{
*(&(&x)[0]);
float cheat = cast(int, x);
float cheat = cast(x, int);
x++;
z = 0;