fixed multiple assignments from function calls()

This commit is contained in:
CPunch 2021-01-06 01:26:42 -06:00
parent 860f30f201
commit ea4654cb6e

View File

@ -75,7 +75,7 @@ typedef enum {
PREC_PRIMARY // everything else PREC_PRIMARY // everything else
} Precedence; } Precedence;
typedef void (*ParseFunc)(CParseState* pstate, bool canAssign); typedef void (*ParseFunc)(CParseState* pstate, bool canAssign, Precedence curPrec);
typedef struct { typedef struct {
ParseFunc prefix; ParseFunc prefix;
@ -84,7 +84,6 @@ typedef struct {
} ParseRule; } ParseRule;
static void parsePrecedence(CParseState*, Precedence); static void parsePrecedence(CParseState*, Precedence);
static void variable(CParseState *pstate, bool canAssign);
static int expressionPrecedence(CParseState *pstate, int needed, Precedence prec, bool forceNeeded); static int expressionPrecedence(CParseState *pstate, int needed, Precedence prec, bool forceNeeded);
static int expression(CParseState *pstate, int needed, bool forceNeeded); static int expression(CParseState *pstate, int needed, bool forceNeeded);
static void statement(CParseState *pstate); static void statement(CParseState *pstate);
@ -144,11 +143,12 @@ static void errorAt(CParseState *pstate, CToken *token, const char *format, va_l
if (pstate->hadError) if (pstate->hadError)
return; return;
if (token->type == TOKEN_EOF) { if (token->type == TOKEN_EOF) {
cosmoV_pushString(pstate->state, "At end: "); cosmoV_pushString(pstate->state, "At end: ");
} else if (!(token->type == TOKEN_ERROR)) { } else if (!(token->type == TOKEN_ERROR)) {
cosmoV_pushFString(pstate->state, "At '%t'", token); // this is why the '%t' exist in cosmoO_pushFString lol cosmoV_pushFString(pstate->state, "At '%t': ", token); // this is why the '%t' exist in cosmoO_pushFString lol
} else {
cosmoV_pushString(pstate->state, "Lexer error: ");
} }
cosmoO_pushVFString(pstate->state, format, args); cosmoO_pushVFString(pstate->state, format, args);
@ -395,19 +395,24 @@ static void alignStack(CParseState *pstate, int alignment) {
pstate->compiler->pushedValues = alignment; pstate->compiler->pushedValues = alignment;
} }
// last in precedence expression?
static bool isLast(CParseState *pstate, Precedence pType) {
return pType > getRule(pstate->current.type)->level;
}
// ================================================================ [PARSER] ================================================================ // ================================================================ [PARSER] ================================================================
static void number(CParseState *pstate, bool canAssign) { static void number(CParseState *pstate, bool canAssign, Precedence prec) {
cosmo_Number num = strtod(pstate->previous.start, NULL); cosmo_Number num = strtod(pstate->previous.start, NULL);
writeConstant(pstate, cosmoV_newNumber(num)); writeConstant(pstate, cosmoV_newNumber(num));
} }
static void string(CParseState *pstate, bool canAssign) { static void string(CParseState *pstate, bool canAssign, Precedence prec) {
CObjString *strObj = cosmoO_takeString(pstate->state, pstate->previous.start, pstate->previous.length); CObjString *strObj = cosmoO_takeString(pstate->state, pstate->previous.start, pstate->previous.length);
writeConstant(pstate, cosmoV_newObj((CObj*)strObj)); writeConstant(pstate, cosmoV_newObj((CObj*)strObj));
} }
static void literal(CParseState *pstate, bool canAssign) { static void literal(CParseState *pstate, bool canAssign, Precedence prec) {
switch (pstate->previous.type) { switch (pstate->previous.type) {
case TOKEN_TRUE: writeu8(pstate, OP_TRUE); break; case TOKEN_TRUE: writeu8(pstate, OP_TRUE); break;
case TOKEN_FALSE: writeu8(pstate, OP_FALSE); break; case TOKEN_FALSE: writeu8(pstate, OP_FALSE); break;
@ -420,7 +425,7 @@ static void literal(CParseState *pstate, bool canAssign) {
} }
// parses prefix operators // parses prefix operators
static void unary(CParseState *pstate, bool canAssign) { static void unary(CParseState *pstate, bool canAssign, Precedence prec) {
CTokenType type = pstate->previous.type; CTokenType type = pstate->previous.type;
int cachedLine = pstate->previous.line; // eval'ing the next expression might change the line number int cachedLine = pstate->previous.line; // eval'ing the next expression might change the line number
@ -437,7 +442,7 @@ static void unary(CParseState *pstate, bool canAssign) {
} }
// parses infix operators // parses infix operators
static void binary(CParseState *pstate, bool canAssign) { static void binary(CParseState *pstate, bool canAssign, Precedence prec) {
CTokenType type = pstate->previous.type; // already consumed CTokenType type = pstate->previous.type; // already consumed
int cachedLine = pstate->previous.line; // eval'ing the next expression might change the line number int cachedLine = pstate->previous.line; // eval'ing the next expression might change the line number
@ -464,7 +469,7 @@ static void binary(CParseState *pstate, bool canAssign) {
valuePopped(pstate, 1); // we pop 2 values off the stack and push 1 for a net pop of 1 value valuePopped(pstate, 1); // we pop 2 values off the stack and push 1 for a net pop of 1 value
} }
static void group(CParseState *pstate, bool canAssign) { static void group(CParseState *pstate, bool canAssign, Precedence prec) {
expression(pstate, 1, true); expression(pstate, 1, true);
consume(pstate, TOKEN_RIGHT_PAREN, "Expected ')'"); consume(pstate, TOKEN_RIGHT_PAREN, "Expected ')'");
} }
@ -554,7 +559,7 @@ static void namedVariable(CParseState *pstate, CToken name, bool canAssign, bool
} }
} }
static void and_(CParseState *pstate, bool canAssign) { static void and_(CParseState *pstate, bool canAssign, Precedence prec) {
int jump = writeJmp(pstate, OP_EJMP); // conditional jump without popping int jump = writeJmp(pstate, OP_EJMP); // conditional jump without popping
writePop(pstate, 1); writePop(pstate, 1);
@ -563,7 +568,7 @@ static void and_(CParseState *pstate, bool canAssign) {
patchJmp(pstate, jump); patchJmp(pstate, jump);
} }
static void or_(CParseState *pstate, bool canAssign) { static void or_(CParseState *pstate, bool canAssign, Precedence prec) {
int elseJump = writeJmp(pstate, OP_EJMP); int elseJump = writeJmp(pstate, OP_EJMP);
int endJump = writeJmp(pstate, OP_JMP); int endJump = writeJmp(pstate, OP_JMP);
@ -575,15 +580,15 @@ static void or_(CParseState *pstate, bool canAssign) {
patchJmp(pstate, endJump); patchJmp(pstate, endJump);
} }
static void anonFunction(CParseState *pstate, bool canAssign) { static void anonFunction(CParseState *pstate, bool canAssign, Precedence prec) {
function(pstate, FTYPE_FUNCTION); function(pstate, FTYPE_FUNCTION);
} }
static void variable(CParseState *pstate, bool canAssign) { static void variable(CParseState *pstate, bool canAssign, Precedence prec) {
namedVariable(pstate, pstate->previous, canAssign, true, 0); namedVariable(pstate, pstate->previous, canAssign, true, 0);
} }
static void concat(CParseState *pstate, bool canAssign) { static void concat(CParseState *pstate, bool canAssign, Precedence prec) {
CTokenType type = pstate->previous.type; CTokenType type = pstate->previous.type;
int vars = 1; // we already have something on the stack int vars = 1; // we already have something on the stack
@ -598,19 +603,25 @@ static void concat(CParseState *pstate, bool canAssign) {
valuePopped(pstate, vars - 1); // - 1 because we're pushing the concat result valuePopped(pstate, vars - 1); // - 1 because we're pushing the concat result
} }
static void call_(CParseState *pstate, bool canAssign) { static void call_(CParseState *pstate, bool canAssign, Precedence prec) {
// we enter having already consumed the '(' // we enter having already consumed the '('
int returnNum = pstate->compiler->expectedValues;
// grab our arguments // grab our arguments
uint8_t argCount = parseArguments(pstate); uint8_t argCount = parseArguments(pstate);
valuePopped(pstate, argCount + 1); // all of these values will be popped off the stack when returned (+1 for the function) valuePopped(pstate, argCount + 1); // all of these values will be popped off the stack when returned (+1 for the function)
writeu8(pstate, OP_CALL); writeu8(pstate, OP_CALL);
writeu8(pstate, argCount); writeu8(pstate, argCount);
writeu8(pstate, pstate->compiler->expectedValues);
valuePushed(pstate, pstate->compiler->expectedValues); // if we're not the last token in this expression or we're expecting multiple values, we should return only 1 value!!
if (!isLast(pstate, prec) || (returnNum > 1 && check(pstate, TOKEN_COMMA)))
returnNum = 1;
writeu8(pstate, returnNum);
valuePushed(pstate, returnNum);
} }
static void object(CParseState *pstate, bool canAssign) { static void object(CParseState *pstate, bool canAssign, Precedence prec) {
// already consumed the beginning '{' // already consumed the beginning '{'
int entries = 0; int entries = 0;
@ -637,7 +648,7 @@ static void object(CParseState *pstate, bool canAssign) {
valuePushed(pstate, 1); valuePushed(pstate, 1);
} }
static void dot(CParseState *pstate, bool canAssign) { static void dot(CParseState *pstate, bool canAssign, Precedence prec) {
consume(pstate, TOKEN_IDENTIFIER, "Expected property name after '.'."); consume(pstate, TOKEN_IDENTIFIER, "Expected property name after '.'.");
uint16_t name = identifierConstant(pstate, &pstate->previous); uint16_t name = identifierConstant(pstate, &pstate->previous);
@ -672,7 +683,7 @@ static void dot(CParseState *pstate, bool canAssign) {
} }
} }
static void _index(CParseState *pstate, bool canAssign) { static void _index(CParseState *pstate, bool canAssign, Precedence prec) {
expression(pstate, 1, true); expression(pstate, 1, true);
consume(pstate, TOKEN_RIGHT_BRACKET, "Expected ']' to end index."); consume(pstate, TOKEN_RIGHT_BRACKET, "Expected ']' to end index.");
@ -795,7 +806,7 @@ static void increment(CParseState *pstate, int val) {
} }
// ++i // ++i
static void preincrement(CParseState *pstate, bool canAssign) { static void preincrement(CParseState *pstate, bool canAssign, Precedence prec) {
// expect identifier // expect identifier
consume(pstate, TOKEN_IDENTIFIER, "Expected identifier after '++'"); consume(pstate, TOKEN_IDENTIFIER, "Expected identifier after '++'");
@ -803,7 +814,7 @@ static void preincrement(CParseState *pstate, bool canAssign) {
} }
// --i // --i
static void predecrement(CParseState *pstate, bool canAssign) { static void predecrement(CParseState *pstate, bool canAssign, Precedence prec) {
// expect identifier // expect identifier
consume(pstate, TOKEN_IDENTIFIER, "Expected identifier after '--'"); consume(pstate, TOKEN_IDENTIFIER, "Expected identifier after '--'");
@ -881,12 +892,12 @@ static void parsePrecedence(CParseState *pstate, Precedence prec) {
return; return;
bool canAssign = prec <= PREC_ASSIGNMENT; bool canAssign = prec <= PREC_ASSIGNMENT;
prefix(pstate, canAssign); prefix(pstate, canAssign, prec);
while (prec <= getRule(pstate->current.type)->level) { while (prec <= getRule(pstate->current.type)->level) {
ParseFunc infix = getRule(pstate->current.type)->infix; ParseFunc infix = getRule(pstate->current.type)->infix;
advance(pstate); advance(pstate);
infix(pstate, canAssign); infix(pstate, canAssign, prec);
} }
if (canAssign && match(pstate, TOKEN_EQUAL)) { if (canAssign && match(pstate, TOKEN_EQUAL)) {