Added 'local' support for 'proto', fixed DOS bug in proto parser

This commit is contained in:
CPunch 2021-01-31 12:06:20 -06:00
parent 300ffb89e9
commit 3a28de6b2a
2 changed files with 27 additions and 6 deletions

View File

@ -1036,13 +1036,12 @@ static void defineVariable(CParseState *pstate, uint16_t global, bool forceLocal
} }
static void _proto(CParseState *pstate) { static void _proto(CParseState *pstate) {
uint16_t var = parseVariable(pstate, "Expected identifer!", false);
int entries = 0; int entries = 0;
while (!match(pstate, TOKEN_END) && !match(pstate, TOKEN_EOF) && !pstate->hadError) { while (!match(pstate, TOKEN_END) && !match(pstate, TOKEN_EOF) && !pstate->hadError) {
if (match(pstate, TOKEN_FUNCTION)) { if (match(pstate, TOKEN_FUNCTION)) {
// define method // define method
consume(pstate, TOKEN_IDENTIFIER, "Expected identifier!"); consume(pstate, TOKEN_IDENTIFIER, "Expected identifier for method!");
uint16_t fieldIdent = identifierConstant(pstate, &pstate->previous); uint16_t fieldIdent = identifierConstant(pstate, &pstate->previous);
// OP_NEWOBJECT expects the key on the stack before the value // OP_NEWOBJECT expects the key on the stack before the value
@ -1051,6 +1050,8 @@ static void _proto(CParseState *pstate) {
function(pstate, FTYPE_METHOD); function(pstate, FTYPE_METHOD);
valuePopped(pstate, 1); valuePopped(pstate, 1);
} else {
errorAtCurrent(pstate, "Illegal syntax!");
} }
entries++; entries++;
@ -1059,9 +1060,27 @@ static void _proto(CParseState *pstate) {
writeu8(pstate, OP_NEWOBJECT); writeu8(pstate, OP_NEWOBJECT);
writeu16(pstate, entries); writeu16(pstate, entries);
valuePushed(pstate, 1); valuePushed(pstate, 1);
}
static void protoDeclaration(CParseState *pstate) {
uint16_t var = parseVariable(pstate, "Expected identifer for proto!", false);
// parse proto definiton
_proto(pstate);
defineVariable(pstate, var, false); defineVariable(pstate, var, false);
} }
static void localProto(CParseState *pstate) {
// parses the variable, forcefully marking it as a local
uint16_t var = parseVariable(pstate, "Expected identifer for proto!", true);
// parse proto definiton
_proto(pstate);
defineVariable(pstate, var, true);
}
static void popLocals(CParseState *pstate, int toScope) { static void popLocals(CParseState *pstate, int toScope) {
if (pstate->hadError) if (pstate->hadError)
return; return;
@ -1541,7 +1560,9 @@ static void expressionStatement(CParseState *pstate) {
} else if (match(pstate, TOKEN_LOCAL)) { } else if (match(pstate, TOKEN_LOCAL)) {
// force declare a local // force declare a local
if (match(pstate, TOKEN_FUNCTION)) if (match(pstate, TOKEN_FUNCTION))
localFunction(pstate); // force local a function localFunction(pstate); // force a local function declaration
else if (match(pstate, TOKEN_PROTO))
localProto(pstate); // force a local proto declaration
else else
varDeclaration(pstate, true, 0); // force local a variable varDeclaration(pstate, true, 0); // force local a variable
} else if (match(pstate, TOKEN_IF)) { } else if (match(pstate, TOKEN_IF)) {
@ -1557,7 +1578,7 @@ static void expressionStatement(CParseState *pstate) {
} else if (match(pstate, TOKEN_FUNCTION)) { } else if (match(pstate, TOKEN_FUNCTION)) {
functionDeclaration(pstate); functionDeclaration(pstate);
} else if (match(pstate, TOKEN_PROTO)) { } else if (match(pstate, TOKEN_PROTO)) {
_proto(pstate); protoDeclaration(pstate);
} else if (match(pstate, TOKEN_BREAK)) { } else if (match(pstate, TOKEN_BREAK)) {
breakStatement(pstate); breakStatement(pstate);
} else if (match(pstate, TOKEN_CONTINUE)) { } else if (match(pstate, TOKEN_CONTINUE)) {

View File

@ -307,7 +307,7 @@ bool callCValue(CState *state, CValue func, int args, int nresults, int offset)
#endif #endif
if (!IS_OBJ(func)) { if (!IS_OBJ(func)) {
cosmoV_error(state, "Cannot call non-function type %s!", cosmoV_typeStr(func)); cosmoV_error(state, "Cannot call non-callable type %s!", cosmoV_typeStr(func));
return false; return false;
} }
@ -350,7 +350,7 @@ bool callCValue(CState *state, CValue func, int args, int nresults, int offset)
break; break;
} }
default: default:
cosmoV_error(state, "Cannot call non-function type %s!", cosmoV_typeStr(func)); cosmoV_error(state, "Cannot call non-callable type %s!", cosmoV_typeStr(func));
return false; return false;
} }