changed dot operator to access global functions

This commit is contained in:
2022-09-08 01:18:20 +01:00
parent 8550f3141c
commit 5861602f23
11 changed files with 81 additions and 378 deletions

View File

@@ -34,17 +34,17 @@ DONE: Import/export keywords
DONE: A way to check the type of a variable (typeOf keyword) DONE: A way to check the type of a variable (typeOf keyword)
DONE: slice and dot notation around the builtin _index and _dot functions DONE: slice and dot notation around the builtin _index and _dot functions
DONE: maximum recursion/function depth DONE: maximum recursion/function depth
DONE: better sugar for _push, _pop, _length
TODO: nested compound assignment TODO: nested compound assignment
TODO: better sugar for _push, _pop, _length
TODO: ternary operator? TODO: ternary operator?
TODO: Nullish types? TODO: Nullish types?
TODO: hooks on the external libraries, triggered on import TODO: hooks on the external libraries, triggered on import
TODO: standard library TODO: standard library
TODO: external script runner library TODO: external script runner library
TODO: document how it all works - book? TODO: document how it all works - book?
TODO: better API TODO: better API?
TODO: packaging for release? TODO: packaging for release?
NOPE: a = b = c = 1; NOPE: a = b = c = 1;

View File

@@ -433,15 +433,14 @@ var dict: [string const, int const] const = [
]; ];
``` ```
Dictionaries can be indexed using traditional bracket notation, or the dot operator when the keys are strings. Existing elements can be accessed or overwritten, or new ones inserted if they don't already exist this way by using the standard library functions. Dictionaries can be indexed using traditional bracket notation. Existing elements can be accessed or overwritten, or new ones inserted if they don't already exist this way by using the standard library functions.
``` ```
dict["foo"] = "bar"; dict["foo"] = "bar";
print dict["foo"]; print dict["foo"];
print dict.foo; //syntactic sugar, only works if the key is not a built-in function
``` ```
## Indexing, Slice and Dot Notation ## Slice Notation
Strings, arrays and dictionaries can be indexed in several ways, via the globally available functions (see below). Elements can be accessed using traditional bracket notation: Strings, arrays and dictionaries can be indexed in several ways, via the globally available functions (see below). Elements can be accessed using traditional bracket notation:
@@ -485,11 +484,22 @@ print str[::-2]; //drwolH
0 cannot be used as the third argument. 0 cannot be used as the third argument.
### Globally available functions ### Globally Available Functions
The slice and dot notations (the latter of which only works on dictionaries) are simply syntactic sugar for the globally available functions. The dot notation can be used to acces the globally available functions, like so:
``` ```
obj.function(); //passes in obj as the first argument
```
A list of globally available functions is:
```
//usable with arrays, dictionaries and strings - probably a good idea not to use this one, just use index notation
fn _index(self, first, second, third, assign, op) {
//native code
}
//usable with arrays and dictionaries //usable with arrays and dictionaries
fn _set(self, key, value) { fn _set(self, key, value) {
//native code //native code

View File

@@ -62,6 +62,16 @@ fn extra(one, two, ...rest) {
extra("one", "two", "three", "four", "five", "six", "seven"); extra("one", "two", "three", "four", "five", "six", "seven");
//test underscore functions
fn _example(self, a, b, c) {
assert a == "a", "underscore failed (a)";
assert b == "b", "underscore failed (b)";
assert c == "c", "underscore failed (c)";
return self;
}
assert "hello world".example("a", "b", "c") == "hello world", "underscore call failed";
print "All good"; print "All good";

View File

@@ -8,16 +8,6 @@
} }
//test dot insertion
{
var d = [:];
d.foo = "bar";
assert d == ["foo":"bar"], "dot insertion failed";
}
//test index arithmetic //test index arithmetic
{ {
var d = ["one":1, "two":2, "three":3]; var d = ["one":1, "two":2, "three":3];
@@ -28,28 +18,6 @@
} }
//test dot arithmetic
{
var d = ["one":1, "two":2, "three":3];
d.three *= 3;
assert d == ["one":1, "two":2, "three":9], "index arithmetic failed";
}
//test dot calls
{
fn f() {
return 42;
}
var d = ["foo":f];
assert d.foo() == 42, "dot calls failed";
}
//test indexing with variables //test indexing with variables
{ {
var d = ["one":1, "two":2, "three":3]; var d = ["one":1, "two":2, "three":3];

View File

@@ -309,7 +309,7 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
//special case for when indexing and assigning //special case for when indexing and assigning
if (override != OP_EOF && node->binary.opcode >= OP_VAR_ASSIGN && node->binary.opcode <= OP_VAR_MODULO_ASSIGN) { if (override != OP_EOF && node->binary.opcode >= OP_VAR_ASSIGN && node->binary.opcode <= OP_VAR_MODULO_ASSIGN) {
writeCompilerWithJumps(compiler, node->binary.right, breakAddressesPtr, continueAddressesPtr, jumpOffsets); writeCompilerWithJumps(compiler, node->binary.right, breakAddressesPtr, continueAddressesPtr, jumpOffsets);
compiler->bytecode[compiler->count++] = (unsigned char)override + 2; //1 byte WARNING: enum arithmetic compiler->bytecode[compiler->count++] = (unsigned char)override + 1; //1 byte WARNING: enum arithmetic
compiler->bytecode[compiler->count++] = (unsigned char)node->binary.opcode; //1 byte compiler->bytecode[compiler->count++] = (unsigned char)node->binary.opcode; //1 byte
return OP_EOF; return OP_EOF;
} }
@@ -319,7 +319,7 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte
} }
//return from the index-binary //return this if...
Opcode ret = writeCompilerWithJumps(compiler, node->binary.right, breakAddressesPtr, continueAddressesPtr, jumpOffsets); Opcode ret = writeCompilerWithJumps(compiler, node->binary.right, breakAddressesPtr, continueAddressesPtr, jumpOffsets);
//loopy logic - if opcode == index or dot //loopy logic - if opcode == index or dot
@@ -504,7 +504,7 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
} }
//push the argument COUNT to the top of the stack //push the argument COUNT to the top of the stack
Literal argumentsCountLiteral = TO_INTEGER_LITERAL(node->fnCall.arguments->fnCollection.count); Literal argumentsCountLiteral = TO_INTEGER_LITERAL(node->fnCall.argumentCount); //argumentCount is set elsewhere to support dot operator
int argumentsCountIndex = findLiteralIndex(&compiler->literalCache, argumentsCountLiteral); int argumentsCountIndex = findLiteralIndex(&compiler->literalCache, argumentsCountLiteral);
if (argumentsCountIndex < 0) { if (argumentsCountIndex < 0) {
argumentsCountIndex = pushLiteralArray(&compiler->literalCache, argumentsCountLiteral); argumentsCountIndex = pushLiteralArray(&compiler->literalCache, argumentsCountLiteral);
@@ -859,20 +859,8 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
break; break;
case NODE_DOT: { case NODE_DOT: {
//pass to the child nodes, then embed the opcode fprintf(stderr, ERROR "[internal] NODE_DOT encountered in writeCompilerWithJumps()\n" RESET);
if (!node->index.first) { compiler->bytecode[compiler->count++] = OP_EOF; //1 byte
writeLiteralToCompiler(compiler, TO_NULL_LITERAL);
}
else {
Opcode override = writeCompilerWithJumps(compiler, node->index.first, breakAddressesPtr, continueAddressesPtr, jumpOffsets);
if (override != OP_EOF) {//compensate for indexing & dot notation being screwy
compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte
}
}
// compiler->bytecode[compiler->count++] = (unsigned char)OP_DOT; //1 byte
return OP_DOT_ASSIGN;
} }
break; break;
} }

View File

@@ -990,7 +990,7 @@ static bool execFalseJump(Interpreter* interpreter) {
static void execInterpreter(Interpreter*); static void execInterpreter(Interpreter*);
static void readInterpreterSections(Interpreter* interpreter); static void readInterpreterSections(Interpreter* interpreter);
static bool execFnCall(Interpreter* interpreter) { static bool execFnCall(Interpreter* interpreter, bool looseFirstArgument) {
//BUGFIX: depth check - don't drown! //BUGFIX: depth check - don't drown!
if (interpreter->depth >= 1000) { if (interpreter->depth >= 1000) {
interpreter->errorOutput("Depth check failed\n"); interpreter->errorOutput("Depth check failed\n");
@@ -1004,7 +1004,14 @@ static bool execFnCall(Interpreter* interpreter) {
Literal stackSize = popLiteralArray(&interpreter->stack); Literal stackSize = popLiteralArray(&interpreter->stack);
//unpack the stack of arguments //unpack the stack of arguments
for (int i = 0; i < AS_INTEGER(stackSize); i++) { for (int i = 0; i < AS_INTEGER(stackSize) - 1; i++) {
Literal lit = popLiteralArray(&interpreter->stack);
pushLiteralArray(&arguments, lit); //NOTE: also reverses the order
freeLiteral(lit);
}
//collect one more argument
if (!looseFirstArgument && AS_INTEGER(stackSize) > 0) {
Literal lit = popLiteralArray(&interpreter->stack); Literal lit = popLiteralArray(&interpreter->stack);
pushLiteralArray(&arguments, lit); //NOTE: also reverses the order pushLiteralArray(&arguments, lit); //NOTE: also reverses the order
freeLiteral(lit); freeLiteral(lit);
@@ -1012,6 +1019,23 @@ static bool execFnCall(Interpreter* interpreter) {
Literal identifier = popLiteralArray(&interpreter->stack); Literal identifier = popLiteralArray(&interpreter->stack);
//collect one more argument
if (looseFirstArgument) {
Literal lit = popLiteralArray(&interpreter->stack);
pushLiteralArray(&arguments, lit); //NOTE: also reverses the order
freeLiteral(lit);
}
//let's screw with the fn name, too
if (looseFirstArgument) {
int length = strlen(AS_IDENTIFIER(identifier)) + 1;
char buffer[MAX_STRING_LENGTH];
snprintf(buffer, MAX_STRING_LENGTH, "_%s", AS_IDENTIFIER(identifier)); //prepend an underscore
freeLiteral(identifier);
identifier = TO_IDENTIFIER_LITERAL(copyString(buffer, length), length);
}
Literal func = identifier; Literal func = identifier;
if (!parseIdentifierToValue(interpreter, &func)) { if (!parseIdentifierToValue(interpreter, &func)) {
@@ -1453,81 +1477,6 @@ static bool execIndex(Interpreter* interpreter) {
return true; return true;
} }
static bool execDot(Interpreter* interpreter) {
//assume -> compound, first are all on the stack
Literal first = popLiteralArray(&interpreter->stack);
Literal compound = popLiteralArray(&interpreter->stack);
Literal tmp = first;
first = TO_STRING_LITERAL(copyString(AS_IDENTIFIER(tmp), strlen(AS_IDENTIFIER(tmp))) , strlen(AS_IDENTIFIER(tmp)) );
freeLiteral(tmp);
if (!IS_IDENTIFIER(compound)) {
interpreter->errorOutput("Unknown literal found in dot notation\n");
printLiteralCustom(compound, interpreter->errorOutput);
interpreter->errorOutput("\n");
freeLiteral(first);
freeLiteral(compound);
return false;
}
Literal idn = compound;
if (!parseIdentifierToValue(interpreter, &compound)) {
freeLiteral(first);
freeLiteral(compound);
freeLiteral(idn);
return false;
}
if (!IS_DICTIONARY(compound)) {
interpreter->errorOutput("Unknown compound found in dot notation\n");
freeLiteral(first);
freeLiteral(compound);
freeLiteral(idn);
return false;
}
//get the index function
Literal func = TO_NULL_LITERAL;
char* keyStr = "_dot";
Literal key = TO_IDENTIFIER_LITERAL(copyString(keyStr, strlen(keyStr)), strlen(keyStr));
if (!getScopeVariable(interpreter->scope, key, &func) || !IS_FUNCTION_NATIVE(func)) {
interpreter->errorOutput("couldn't get the _dot function\n");
freeLiteral(first);
freeLiteral(compound);
freeLiteral(idn);
freeLiteral(func);
freeLiteral(key);
return false;
}
//build the argument list
LiteralArray arguments;
initLiteralArray(&arguments);
pushLiteralArray(&arguments, compound);
pushLiteralArray(&arguments, first);
pushLiteralArray(&arguments, TO_NULL_LITERAL); //it expects an assignment command
pushLiteralArray(&arguments, TO_NULL_LITERAL); //it expects an assignment "opcode"
//call the function
NativeFn fn = (NativeFn)AS_FUNCTION(func).bytecode;
fn(interpreter, &arguments);
//clean up
freeLiteral(first);
freeLiteral(compound);
freeLiteral(idn);
freeLiteral(func);
freeLiteral(key);
freeLiteralArray(&arguments);
return true;
}
static bool execIndexAssign(Interpreter* interpreter) { static bool execIndexAssign(Interpreter* interpreter) {
//assume -> compound, first, second, third, assign are all on the stack //assume -> compound, first, second, third, assign are all on the stack
@@ -1699,161 +1648,6 @@ static bool execIndexAssign(Interpreter* interpreter) {
return true; return true;
} }
static bool execDotAssign(Interpreter* interpreter) {
//assume -> compound, first, assign are all on the stack
Literal assign = popLiteralArray(&interpreter->stack);
Literal first = popLiteralArray(&interpreter->stack);
Literal compound = popLiteralArray(&interpreter->stack);
Literal tmp = first;
first = TO_STRING_LITERAL(copyString(AS_IDENTIFIER(tmp), strlen(AS_IDENTIFIER(tmp))) , strlen(AS_IDENTIFIER(tmp)) );
freeLiteral(tmp);
if (!IS_IDENTIFIER(compound)) {
interpreter->errorOutput("Unknown literal found in dot assigning notation\n");
printLiteralCustom(compound, interpreter->errorOutput);
interpreter->errorOutput("\n");
freeLiteral(assign);
freeLiteral(first);
freeLiteral(compound);
return false;
}
Literal idn = compound;
if (!parseIdentifierToValue(interpreter, &compound)) {
freeLiteral(assign);
freeLiteral(first);
freeLiteral(compound);
freeLiteral(idn);
return false;
}
if (!IS_DICTIONARY(compound)) {
interpreter->errorOutput("Unknown compound found in dot assigning notation\n");
freeLiteral(assign);
freeLiteral(first);
freeLiteral(compound);
freeLiteral(idn);
return false;
}
//check const-ness of "first" within "compound"
Literal type = getScopeType(interpreter->scope, idn);
if (AS_TYPE(type).typeOf == LITERAL_DICTIONARY && AS_TYPE(((Literal*)(AS_TYPE(type).subtypes))[1]).constant) {
interpreter->errorOutput("couldn't assign to constant within compound within dot assigning notation\n");
freeLiteral(assign);
freeLiteral(first);
freeLiteral(compound);
freeLiteral(idn);
freeLiteral(type);
return false;
}
//get the index function
Literal func = TO_NULL_LITERAL;
char* keyStr = "_dot";
Literal key = TO_IDENTIFIER_LITERAL(copyString(keyStr, strlen(keyStr)), strlen(keyStr));
if (!getScopeVariable(interpreter->scope, key, &func) || !IS_FUNCTION_NATIVE(func)) {
interpreter->errorOutput("couldn't get the _dot function\n");
freeLiteral(assign);
freeLiteral(first);
freeLiteral(compound);
freeLiteral(idn);
freeLiteral(func);
freeLiteral(key);
freeLiteral(type);
return false;
}
//build the opcode
unsigned char opcode = readByte(interpreter->bytecode, &interpreter->count);
char* opStr = "";
switch(opcode) {
case OP_VAR_ASSIGN:
opStr = "=";
break;
case OP_VAR_ADDITION_ASSIGN:
opStr = "+=";
break;
case OP_VAR_SUBTRACTION_ASSIGN:
opStr = "-=";
break;
case OP_VAR_MULTIPLICATION_ASSIGN:
opStr = "*=";
break;
case OP_VAR_DIVISION_ASSIGN:
opStr = "/=";
break;
case OP_VAR_MODULO_ASSIGN:
opStr = "%=";
break;
default:
interpreter->errorOutput("bad opcode in dot assigning notation\n");
freeLiteral(assign);
freeLiteral(first);
freeLiteral(compound);
freeLiteral(idn);
freeLiteral(func);
freeLiteral(key);
freeLiteral(type);
return false;
}
Literal op = TO_STRING_LITERAL(copyString(opStr, strlen(opStr)), strlen(opStr));
//build the argument list
LiteralArray arguments;
initLiteralArray(&arguments);
pushLiteralArray(&arguments, compound);
pushLiteralArray(&arguments, first);
pushLiteralArray(&arguments, assign); //it expects an assignment command
pushLiteralArray(&arguments, op); //it expects an assignment "opcode"
//call the function
NativeFn fn = (NativeFn)AS_FUNCTION(func).bytecode;
fn(interpreter, &arguments);
//save the result (assume top of the interpreter stack is the new compound value)
Literal result = popLiteralArray(&interpreter->stack);
if (!setScopeVariable(interpreter->scope, idn, result, true)) {
interpreter->errorOutput("Incorrect type assigned to compound member: ");
printLiteralCustom(result, interpreter->errorOutput);
interpreter->errorOutput("\n");
//clean up
freeLiteral(assign);
freeLiteral(first);
freeLiteral(compound);
freeLiteral(idn);
freeLiteral(func);
freeLiteral(key);
freeLiteral(type);
freeLiteral(result);
freeLiteralArray(&arguments);
freeLiteral(op);
return false;
}
//clean up
freeLiteral(op);
freeLiteral(assign);
freeLiteral(first);
freeLiteral(compound);
freeLiteral(idn);
freeLiteral(func);
freeLiteralArray(&arguments);
freeLiteral(key);
freeLiteral(type);
freeLiteral(result);
return true;
}
//the heart of toy //the heart of toy
static void execInterpreter(Interpreter* interpreter) { static void execInterpreter(Interpreter* interpreter) {
//set the starting point for the interpreter //set the starting point for the interpreter
@@ -2038,11 +1832,18 @@ static void execInterpreter(Interpreter* interpreter) {
break; break;
case OP_FN_CALL: case OP_FN_CALL:
if (!execFnCall(interpreter)) { if (!execFnCall(interpreter, false)) {
return; return;
} }
break; break;
case OP_DOT:
if (!execFnCall(interpreter, true)) { //compensate for the out-of-order arguments
return;
}
break;
case OP_FN_RETURN: case OP_FN_RETURN:
if (!execFnReturn(interpreter)) { if (!execFnReturn(interpreter)) {
return; return;
@@ -2067,24 +1868,12 @@ static void execInterpreter(Interpreter* interpreter) {
} }
break; break;
case OP_DOT:
if (!execDot(interpreter)) {
return;
}
break;
case OP_INDEX_ASSIGN: case OP_INDEX_ASSIGN:
if (!execIndexAssign(interpreter)) { if (!execIndexAssign(interpreter)) {
return; return;
} }
break; break;
case OP_DOT_ASSIGN:
if (!execDotAssign(interpreter)) {
return;
}
break;
case OP_POP_STACK: case OP_POP_STACK:
while (interpreter->stack.count > 0) { while (interpreter->stack.count > 0) {
freeLiteral(popLiteralArray(&interpreter->stack)); freeLiteral(popLiteralArray(&interpreter->stack));
@@ -2450,7 +2239,6 @@ void resetInterpreter(Interpreter* interpreter) {
//globally available functions //globally available functions
injectNativeFn(interpreter, "_index", _index); injectNativeFn(interpreter, "_index", _index);
injectNativeFn(interpreter, "_dot", _dot);
injectNativeFn(interpreter, "_set", _set); injectNativeFn(interpreter, "_set", _set);
injectNativeFn(interpreter, "_get", _get); injectNativeFn(interpreter, "_get", _get);
injectNativeFn(interpreter, "_push", _push); injectNativeFn(interpreter, "_push", _push);

View File

@@ -913,70 +913,6 @@ int _index(Interpreter* interpreter, LiteralArray* arguments) {
return 1; return 1;
} }
int _dot(Interpreter* interpreter, LiteralArray* arguments) {
//_dot(compound, first, assignValue, opcode)
Literal op = popLiteralArray(arguments);
Literal assign = popLiteralArray(arguments);
Literal first = popLiteralArray(arguments);
Literal compound = popLiteralArray(arguments);
Literal value = getLiteralDictionary(AS_DICTIONARY(compound), first);
//dictionary
if (IS_NULL(op)) {
pushLiteralArray(&interpreter->stack, value);
}
else if (!strcmp( AS_STRING(op), "=")) {
setLiteralDictionary(AS_DICTIONARY(compound), first, assign);
pushLiteralArray(&interpreter->stack, compound);
}
else if (!strcmp( AS_STRING(op), "+=")) {
Literal lit = addition(interpreter, value, assign);
setLiteralDictionary(AS_DICTIONARY(compound), first, lit);
freeLiteral(lit);
pushLiteralArray(&interpreter->stack, compound);
}
else if (!strcmp( AS_STRING(op), "-=")) {
Literal lit = subtraction(interpreter, value, assign);
setLiteralDictionary(AS_DICTIONARY(compound), first, lit);
freeLiteral(lit);
pushLiteralArray(&interpreter->stack, compound);
}
else if (!strcmp( AS_STRING(op), "*=")) {
Literal lit = multiplication(interpreter, value, assign);
setLiteralDictionary(AS_DICTIONARY(compound), first, lit);
freeLiteral(lit);
pushLiteralArray(&interpreter->stack, compound);
}
else if (!strcmp( AS_STRING(op), "/=")) {
Literal lit = division(interpreter, value, assign);
setLiteralDictionary(AS_DICTIONARY(compound), first, lit);
freeLiteral(lit);
pushLiteralArray(&interpreter->stack, compound);
}
else if (!strcmp( AS_STRING(op), "%=")) {
Literal lit = modulo(interpreter, value, assign);
setLiteralDictionary(AS_DICTIONARY(compound), first, lit);
freeLiteral(lit);
pushLiteralArray(&interpreter->stack, compound);
}
//cleanup
freeLiteral(op);
freeLiteral(assign);
freeLiteral(first);
freeLiteral(compound);
freeLiteral(value);
return 1;
}
int _set(Interpreter* interpreter, LiteralArray* arguments) { int _set(Interpreter* interpreter, LiteralArray* arguments) {
//if wrong number of arguments, fail //if wrong number of arguments, fail
if (arguments->count != 3) { if (arguments->count != 3) {

View File

@@ -207,11 +207,12 @@ void emitNodeFnDecl(Node** nodeHandle, Literal identifier, Node* arguments, Node
*nodeHandle = tmp; *nodeHandle = tmp;
} }
void emitFnCall(Node** nodeHandle, Node* arguments) { void emitFnCall(Node** nodeHandle, Node* arguments, int argumentCount) {
Node* tmp = ALLOCATE(Node, 1); Node* tmp = ALLOCATE(Node, 1);
tmp->type = NODE_FN_CALL; tmp->type = NODE_FN_CALL;
tmp->fnCall.arguments = arguments; tmp->fnCall.arguments = arguments;
tmp->fnCall.argumentCount = argumentCount;
*nodeHandle = tmp; *nodeHandle = tmp;
} }

View File

@@ -103,6 +103,7 @@ typedef struct NodeFnCollection {
typedef struct NodeFnCall { typedef struct NodeFnCall {
NodeType type; NodeType type;
Node* arguments; Node* arguments;
int argumentCount;
} NodeFnCall; } NodeFnCall;
typedef struct NodePath { typedef struct NodePath {
@@ -162,7 +163,7 @@ void emitNodeCompound(Node** nodeHandle, LiteralType literalType);
void setNodePair(Node* node, Node* left, Node* right); void setNodePair(Node* node, Node* left, Node* right);
void emitNodeVarDecl(Node** nodeHandle, Literal identifier, Literal type, Node* expression); void emitNodeVarDecl(Node** nodeHandle, Literal identifier, Literal type, Node* expression);
void emitNodeFnDecl(Node** nodeHandle, Literal identifier, Node* arguments, Node* returns, Node* block); void emitNodeFnDecl(Node** nodeHandle, Literal identifier, Node* arguments, Node* returns, Node* block);
void emitFnCall(Node** nodeHandle, Node* arguments); void emitFnCall(Node** nodeHandle, Node* arguments, int argumentCount);
void emitNodeFnCollection(Node** nodeHandle); void emitNodeFnCollection(Node** nodeHandle);
void emitNodePath(Node** nodeHandle, NodeType type, Node* preClause, Node* postClause, Node* condition, Node* thenPath, Node* elsePath); void emitNodePath(Node** nodeHandle, NodeType type, Node* preClause, Node* postClause, Node* condition, Node* thenPath, Node* elsePath);
void emitNodePrefixIncrement(Node** nodeHandle, Literal identifier, int increment); void emitNodePrefixIncrement(Node** nodeHandle, Literal identifier, int increment);

View File

@@ -50,10 +50,8 @@ typedef enum Opcode {
//for indexing //for indexing
OP_INDEX, OP_INDEX,
OP_DOT,
OP_INDEX_ASSIGN, OP_INDEX_ASSIGN,
OP_DOT_ASSIGN, OP_DOT,
//comparison of values //comparison of values
OP_COMPARE_EQUAL, OP_COMPARE_EQUAL,

View File

@@ -677,7 +677,7 @@ static Opcode decrementInfix(Parser* parser, Node** nodeHandle) {
} }
static Opcode fnCall(Parser* parser, Node** nodeHandle) { static Opcode fnCall(Parser* parser, Node** nodeHandle) {
advance(parser); advance(parser); //skip the left paren
//binary() is an infix rule - so only get the RHS of the operator //binary() is an infix rule - so only get the RHS of the operator
switch(parser->previous.type) { switch(parser->previous.type) {
@@ -708,7 +708,7 @@ static Opcode fnCall(Parser* parser, Node** nodeHandle) {
} }
//emit the call //emit the call
emitFnCall(nodeHandle, arguments); emitFnCall(nodeHandle, arguments, arguments->fnCollection.count);
return OP_FN_CALL; return OP_FN_CALL;
} }
@@ -786,14 +786,17 @@ static Opcode indexAccess(Parser* parser, Node** nodeHandle) {
static Opcode dot(Parser* parser, Node** nodeHandle) { static Opcode dot(Parser* parser, Node** nodeHandle) {
advance(parser); //for the dot advance(parser); //for the dot
advance(parser); //for the identifier
Node* first = NULL; Node* node = NULL;
identifier(parser, &first); //specific case parsePrecedence(parser, &node, PREC_CALL);
emitNodeDot(nodeHandle, first);
return OP_DOT; //hijack the function call, and hack in an extra parameter
node->binary.right->fnCall.argumentCount++;
node->binary.opcode = OP_DOT;
(*nodeHandle) = node;
return OP_DOT; //signal that the function name and arguments are in the wrong order
} }
ParseRule parseRules[] = { //must match the token types ParseRule parseRules[] = { //must match the token types