implemented default arguments
This commit is contained in:
@@ -1,9 +0,0 @@
|
|||||||
|
|
||||||
fun add(a: int | float = 1, b = 8)
|
|
||||||
return a + b;
|
|
||||||
|
|
||||||
c = add(3, 4);
|
|
||||||
|
|
||||||
assert(c == 7);
|
|
||||||
|
|
||||||
print(c);
|
|
||||||
@@ -102,6 +102,7 @@ static const InstrInfo instr_table[] = {
|
|||||||
[OPCODE_PUSHMAP] = {"PUSHMAP", 1, (OperandType[]) {OPTP_INT}},
|
[OPCODE_PUSHMAP] = {"PUSHMAP", 1, (OperandType[]) {OPTP_INT}},
|
||||||
[OPCODE_PUSHTYP] = {"PUSHTYP", 0, NULL},
|
[OPCODE_PUSHTYP] = {"PUSHTYP", 0, NULL},
|
||||||
[OPCODE_PUSHTYPTYP] = {"PUSHTYPTYP", 0, NULL},
|
[OPCODE_PUSHTYPTYP] = {"PUSHTYPTYP", 0, NULL},
|
||||||
|
[OPCODE_PUSHNNETYP] = {"PUSHNNETYP", 0, NULL},
|
||||||
[OPCODE_RETURN] = {"RETURN", 1, (OperandType[]) {OPTP_INT}},
|
[OPCODE_RETURN] = {"RETURN", 1, (OperandType[]) {OPTP_INT}},
|
||||||
[OPCODE_ERROR] = {"ERROR", 1, (OperandType[]) {OPTP_STRING}},
|
[OPCODE_ERROR] = {"ERROR", 1, (OperandType[]) {OPTP_STRING}},
|
||||||
[OPCODE_JUMPIFNOTANDPOP] = {"JUMPIFNOTANDPOP", 1, (OperandType[]) {OPTP_IDX}},
|
[OPCODE_JUMPIFNOTANDPOP] = {"JUMPIFNOTANDPOP", 1, (OperandType[]) {OPTP_IDX}},
|
||||||
|
|||||||
@@ -87,6 +87,7 @@ typedef enum {
|
|||||||
OPCODE_PUSHMAP,
|
OPCODE_PUSHMAP,
|
||||||
OPCODE_PUSHTYP,
|
OPCODE_PUSHTYP,
|
||||||
OPCODE_PUSHTYPTYP,
|
OPCODE_PUSHTYPTYP,
|
||||||
|
OPCODE_PUSHNNETYP,
|
||||||
OPCODE_RETURN,
|
OPCODE_RETURN,
|
||||||
OPCODE_ERROR,
|
OPCODE_ERROR,
|
||||||
OPCODE_JUMPIFANDPOP,
|
OPCODE_JUMPIFANDPOP,
|
||||||
|
|||||||
@@ -194,5 +194,6 @@ typedef struct {
|
|||||||
char *name;
|
char *name;
|
||||||
int typec;
|
int typec;
|
||||||
Node *typev;
|
Node *typev;
|
||||||
|
Node *value;
|
||||||
} ArgumentNode;
|
} ArgumentNode;
|
||||||
#endif
|
#endif
|
||||||
@@ -157,6 +157,11 @@ static void emitInstr_PUSHTYPTYP(CodegenContext *ctx, int off, int len)
|
|||||||
CodegenContext_EmitInstr(ctx, OPCODE_PUSHTYPTYP, NULL, 0, off, len);
|
CodegenContext_EmitInstr(ctx, OPCODE_PUSHTYPTYP, NULL, 0, off, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void emitInstr_PUSHNNETYP(CodegenContext *ctx, int off, int len)
|
||||||
|
{
|
||||||
|
CodegenContext_EmitInstr(ctx, OPCODE_PUSHNNETYP, NULL, 0, off, len);
|
||||||
|
}
|
||||||
|
|
||||||
static void emitInstrForNode(CodegenContext *ctx, Node *node, Label *label_break);
|
static void emitInstrForNode(CodegenContext *ctx, Node *node, Label *label_break);
|
||||||
|
|
||||||
static Opcode exprkind_to_opcode(ExprKind kind)
|
static Opcode exprkind_to_opcode(ExprKind kind)
|
||||||
@@ -208,6 +213,14 @@ static void emitInstrForFuncCallNode(CodegenContext *ctx, CallExprNode *expr,
|
|||||||
static void emitInstrForArgumentNode(CodegenContext *ctx, ArgumentNode *arg, int argidx)
|
static void emitInstrForArgumentNode(CodegenContext *ctx, ArgumentNode *arg, int argidx)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
* // If a default value for the argument was specified
|
||||||
|
* PUSHTYP;
|
||||||
|
* PUSHNNETYP;
|
||||||
|
* EQL;
|
||||||
|
* JUMPIFNOTANDPOP default_handled;
|
||||||
|
* POP 1;
|
||||||
|
* <default-value>
|
||||||
|
* default_handled:
|
||||||
* // Push the type of the argument
|
* // Push the type of the argument
|
||||||
* PUSHTYP;
|
* PUSHTYP;
|
||||||
*
|
*
|
||||||
@@ -255,6 +268,19 @@ static void emitInstrForArgumentNode(CodegenContext *ctx, ArgumentNode *arg, int
|
|||||||
* POP 1;
|
* POP 1;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
if(arg->value != NULL) {
|
||||||
|
/* Emit bytecode for the default argument */
|
||||||
|
Label *label_default_handled = Label_New(ctx);
|
||||||
|
emitInstr_PUSHTYP(ctx, arg->value->offset, arg->value->length);
|
||||||
|
emitInstr_PUSHNNETYP(ctx, arg->value->offset, arg->value->length);
|
||||||
|
emitInstr_EQL(ctx, arg->value->offset, arg->value->length);
|
||||||
|
emitInstr_JUMPIFNOTANDPOP(ctx, label_default_handled, arg->value->offset, arg->value->length);
|
||||||
|
emitInstr_POP1(ctx, arg->value->offset, arg->value->length);
|
||||||
|
emitInstrForNode(ctx, arg->value, NULL);
|
||||||
|
Label_SetHere(label_default_handled, ctx);
|
||||||
|
Label_Free(label_default_handled);
|
||||||
|
}
|
||||||
|
|
||||||
if(arg->typev != NULL) {
|
if(arg->typev != NULL) {
|
||||||
|
|
||||||
/* Emit checks for the argument type */
|
/* Emit checks for the argument type */
|
||||||
|
|||||||
+43
-34
@@ -127,7 +127,7 @@ typedef struct {
|
|||||||
} Context;
|
} Context;
|
||||||
|
|
||||||
static Node *parse_statement(Context *ctx);
|
static Node *parse_statement(Context *ctx);
|
||||||
static Node *parse_expression(Context *ctx, _Bool allow_toplev_tuples);
|
static Node *parse_expression(Context *ctx, _Bool allow_toplev_tuples, _Bool allow_assignments);
|
||||||
static Node *parse_expression_statement(Context *ctx);
|
static Node *parse_expression_statement(Context *ctx);
|
||||||
static Node *parse_ifelse_statement(Context *ctx);
|
static Node *parse_ifelse_statement(Context *ctx);
|
||||||
static Node *parse_compound_statement(Context *ctx, TokenKind end);
|
static Node *parse_compound_statement(Context *ctx, TokenKind end);
|
||||||
@@ -616,7 +616,7 @@ static Node *parse_statement(Context *ctx)
|
|||||||
|
|
||||||
next(ctx); // Consume the "return" keyword.
|
next(ctx); // Consume the "return" keyword.
|
||||||
|
|
||||||
Node *val = parse_expression(ctx, 1);
|
Node *val = parse_expression(ctx, 1, 1);
|
||||||
|
|
||||||
if(val == NULL)
|
if(val == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -664,7 +664,7 @@ static Node *parse_expression_statement(Context *ctx)
|
|||||||
{
|
{
|
||||||
assert(ctx != NULL);
|
assert(ctx != NULL);
|
||||||
|
|
||||||
Node *expr = parse_expression(ctx, 1);
|
Node *expr = parse_expression(ctx, 1, 1);
|
||||||
|
|
||||||
if(expr == NULL)
|
if(expr == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -855,7 +855,7 @@ static Node *parse_list_primary_expression(Context *ctx)
|
|||||||
while(1)
|
while(1)
|
||||||
{
|
{
|
||||||
// Parse.
|
// Parse.
|
||||||
Node *item = parse_expression(ctx, 0);
|
Node *item = parse_expression(ctx, 0, 1);
|
||||||
|
|
||||||
if(item == NULL)
|
if(item == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -975,7 +975,7 @@ static Node *parse_map_primary_expression(Context *ctx)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
key = parse_expression(ctx, 0);
|
key = parse_expression(ctx, 0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(key == NULL)
|
if(key == NULL)
|
||||||
@@ -1002,7 +1002,7 @@ static Node *parse_map_primary_expression(Context *ctx)
|
|||||||
next(ctx);
|
next(ctx);
|
||||||
|
|
||||||
// Parse.
|
// Parse.
|
||||||
Node *item = parse_expression(ctx, 0);
|
Node *item = parse_expression(ctx, 0, 1);
|
||||||
|
|
||||||
if(item == NULL)
|
if(item == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -1144,7 +1144,7 @@ static Node *parse_primary_expresion(Context *ctx)
|
|||||||
{
|
{
|
||||||
next(ctx); // Consume the '('.
|
next(ctx); // Consume the '('.
|
||||||
|
|
||||||
Node *node = parse_expression(ctx, 1);
|
Node *node = parse_expression(ctx, 1, 1);
|
||||||
|
|
||||||
if(node == NULL)
|
if(node == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -1463,7 +1463,7 @@ static Node *parse_postfix_expression(Context *ctx)
|
|||||||
while(1)
|
while(1)
|
||||||
{
|
{
|
||||||
// Parse.
|
// Parse.
|
||||||
Node *arg = parse_expression(ctx, 0);
|
Node *arg = parse_expression(ctx, 0, 1);
|
||||||
|
|
||||||
if(arg == NULL)
|
if(arg == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -1648,13 +1648,13 @@ static inline int precedenceof(Token *tok)
|
|||||||
return -100000000;
|
return -100000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Node *parse_expression_2(Context *ctx, Node *left_expr, int min_prec, _Bool allow_toplev_tuples)
|
static Node *parse_expression_2(Context *ctx, Node *left_expr, int min_prec, _Bool allow_toplev_tuples, _Bool allow_assignments)
|
||||||
{
|
{
|
||||||
while(isbinop(ctx->token) && precedenceof(ctx->token) >= min_prec)
|
while(isbinop(ctx->token) && precedenceof(ctx->token) >= min_prec)
|
||||||
{
|
{
|
||||||
Token *op = ctx->token;
|
Token *op = ctx->token;
|
||||||
|
|
||||||
if(op->kind == ',' && allow_toplev_tuples == 0)
|
if((op->kind == ',' && allow_toplev_tuples == 0) || (op->kind == '=' && allow_assignments == 0))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
next(ctx);
|
next(ctx);
|
||||||
@@ -1666,7 +1666,7 @@ static Node *parse_expression_2(Context *ctx, Node *left_expr, int min_prec, _Bo
|
|||||||
|
|
||||||
while(isbinop(ctx->token) && (precedenceof(ctx->token) > precedenceof(op) || (precedenceof(ctx->token) == precedenceof(op) && isrightassoc(ctx->token))))
|
while(isbinop(ctx->token) && (precedenceof(ctx->token) > precedenceof(op) || (precedenceof(ctx->token) == precedenceof(op) && isrightassoc(ctx->token))))
|
||||||
{
|
{
|
||||||
right_expr = parse_expression_2(ctx, right_expr, precedenceof(op) + 1, allow_toplev_tuples);
|
right_expr = parse_expression_2(ctx, right_expr, precedenceof(op) + 1, allow_toplev_tuples, allow_assignments);
|
||||||
|
|
||||||
if(right_expr == NULL)
|
if(right_expr == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -1724,7 +1724,7 @@ static Node *parse_expression_2(Context *ctx, Node *left_expr, int min_prec, _Bo
|
|||||||
return left_expr;
|
return left_expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Node *parse_expression(Context *ctx, _Bool allow_toplev_tuples)
|
static Node *parse_expression(Context *ctx, _Bool allow_toplev_tuples, _Bool allow_assignments)
|
||||||
{
|
{
|
||||||
Node *left_expr = parse_prefix_expression(ctx);
|
Node *left_expr = parse_prefix_expression(ctx);
|
||||||
|
|
||||||
@@ -1734,7 +1734,7 @@ static Node *parse_expression(Context *ctx, _Bool allow_toplev_tuples)
|
|||||||
if(done(ctx))
|
if(done(ctx))
|
||||||
return left_expr;
|
return left_expr;
|
||||||
|
|
||||||
return parse_expression_2(ctx, left_expr, -1000000000, allow_toplev_tuples);
|
return parse_expression_2(ctx, left_expr, -1000000000, allow_toplev_tuples, allow_assignments);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Node *parse_ifelse_statement(Context *ctx)
|
static Node *parse_ifelse_statement(Context *ctx)
|
||||||
@@ -1758,7 +1758,7 @@ static Node *parse_ifelse_statement(Context *ctx)
|
|||||||
|
|
||||||
next(ctx); // Consume the "if" keyword.
|
next(ctx); // Consume the "if" keyword.
|
||||||
|
|
||||||
Node *condition = parse_expression(ctx, 1);
|
Node *condition = parse_expression(ctx, 1, 1);
|
||||||
|
|
||||||
if(condition == NULL)
|
if(condition == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -1865,7 +1865,7 @@ static Node *parse_compound_statement(Context *ctx, TokenKind end)
|
|||||||
return (Node*) node;
|
return (Node*) node;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Node *parse_function_arguments(Context *ctx, int *argc_)
|
static _Bool parse_function_arguments(Context *ctx, int *argc_, Node **argv_)
|
||||||
{
|
{
|
||||||
#warning "What if the source ends here?"
|
#warning "What if the source ends here?"
|
||||||
|
|
||||||
@@ -1875,7 +1875,7 @@ static Node *parse_function_arguments(Context *ctx, int *argc_)
|
|||||||
Error_Report(ctx->error, 0, "Source ended where a function argument list was expected");
|
Error_Report(ctx->error, 0, "Source ended where a function argument list was expected");
|
||||||
else
|
else
|
||||||
Error_Report(ctx->error, 0, "Got unexpected token \"%.*s\" where a function argument list was expected", ctx->token->length, ctx->src + ctx->token->offset);
|
Error_Report(ctx->error, 0, "Got unexpected token \"%.*s\" where a function argument list was expected", ctx->token->length, ctx->src + ctx->token->offset);
|
||||||
return NULL;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Node *argv = NULL;
|
Node *argv = NULL;
|
||||||
@@ -1890,13 +1890,13 @@ static Node *parse_function_arguments(Context *ctx, int *argc_)
|
|||||||
if(done(ctx))
|
if(done(ctx))
|
||||||
{
|
{
|
||||||
Error_Report(ctx->error, 0, "Source ended inside a function argument list");
|
Error_Report(ctx->error, 0, "Source ended inside a function argument list");
|
||||||
return NULL;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(current(ctx) != TIDENT)
|
if(current(ctx) != TIDENT)
|
||||||
{
|
{
|
||||||
Error_Report(ctx->error, 0, "Got unexpected token \"%.*s\" where a function argument name was expected", ctx->token->length, ctx->src + ctx->token->offset);
|
Error_Report(ctx->error, 0, "Got unexpected token \"%.*s\" where a function argument name was expected", ctx->token->length, ctx->src + ctx->token->offset);
|
||||||
return NULL;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *arg_name = copy_token_text(ctx);
|
char *arg_name = copy_token_text(ctx);
|
||||||
@@ -1904,7 +1904,7 @@ static Node *parse_function_arguments(Context *ctx, int *argc_)
|
|||||||
if(arg_name == NULL)
|
if(arg_name == NULL)
|
||||||
{
|
{
|
||||||
Error_Report(ctx->error, 1, "No memory");
|
Error_Report(ctx->error, 1, "No memory");
|
||||||
return NULL;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int typec;
|
int typec;
|
||||||
@@ -1913,17 +1913,17 @@ static Node *parse_function_arguments(Context *ctx, int *argc_)
|
|||||||
if(next(ctx) == ':') {
|
if(next(ctx) == ':') {
|
||||||
next(ctx); // Skip the ':'.
|
next(ctx); // Skip the ':'.
|
||||||
|
|
||||||
Node *type = parse_expression(ctx, 0);
|
Node *type = parse_expression(ctx, 0, 0);
|
||||||
if(type == NULL)
|
if(type == NULL)
|
||||||
return NULL;
|
return 0;
|
||||||
typev = type;
|
typev = type;
|
||||||
typec = 1;
|
typec = 1;
|
||||||
Node *tail = type;
|
Node *tail = type;
|
||||||
while(current(ctx) == '|') {
|
while(current(ctx) == '|') {
|
||||||
next(ctx);
|
next(ctx);
|
||||||
type = parse_expression(ctx, 0);
|
type = parse_expression(ctx, 0, 0);
|
||||||
if(type == NULL)
|
if(type == NULL)
|
||||||
return NULL;
|
return 0;
|
||||||
tail->next = type;
|
tail->next = type;
|
||||||
tail = type;
|
tail = type;
|
||||||
typec += 1;
|
typec += 1;
|
||||||
@@ -1931,6 +1931,15 @@ static Node *parse_function_arguments(Context *ctx, int *argc_)
|
|||||||
} else
|
} else
|
||||||
typec = 0;
|
typec = 0;
|
||||||
|
|
||||||
|
Node *defarg; // Default argument (or NULL if there isn't one)
|
||||||
|
if(current(ctx) == '=') {
|
||||||
|
next(ctx); // Skip the '='.
|
||||||
|
defarg = parse_expression(ctx, 0, 1);
|
||||||
|
if(defarg == NULL)
|
||||||
|
return 0;
|
||||||
|
} else
|
||||||
|
defarg = NULL;
|
||||||
|
|
||||||
ArgumentNode *arg;
|
ArgumentNode *arg;
|
||||||
{
|
{
|
||||||
// Make argument node.
|
// Make argument node.
|
||||||
@@ -1939,7 +1948,7 @@ static Node *parse_function_arguments(Context *ctx, int *argc_)
|
|||||||
if(arg == NULL)
|
if(arg == NULL)
|
||||||
{
|
{
|
||||||
Error_Report(ctx->error, 1, "No memory");
|
Error_Report(ctx->error, 1, "No memory");
|
||||||
return NULL;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
arg->base.kind = NODE_ARG;
|
arg->base.kind = NODE_ARG;
|
||||||
@@ -1949,6 +1958,7 @@ static Node *parse_function_arguments(Context *ctx, int *argc_)
|
|||||||
arg->name = arg_name;
|
arg->name = arg_name;
|
||||||
arg->typev = typev;
|
arg->typev = typev;
|
||||||
arg->typec = typec;
|
arg->typec = typec;
|
||||||
|
arg->value = defarg;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add it to the list.
|
// Add it to the list.
|
||||||
@@ -1961,7 +1971,7 @@ static Node *parse_function_arguments(Context *ctx, int *argc_)
|
|||||||
if(done(ctx))
|
if(done(ctx))
|
||||||
{
|
{
|
||||||
Error_Report(ctx->error, 0, "Source ended inside a function argument list");
|
Error_Report(ctx->error, 0, "Source ended inside a function argument list");
|
||||||
return NULL;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(current(ctx) == ')')
|
if(current(ctx) == ')')
|
||||||
@@ -1970,7 +1980,7 @@ static Node *parse_function_arguments(Context *ctx, int *argc_)
|
|||||||
if(current(ctx) != ',')
|
if(current(ctx) != ',')
|
||||||
{
|
{
|
||||||
Error_Report(ctx->error, 0, "Got unexpected token \"%.*s\" inside function argument list, where either ',' or ')' were expected", ctx->token->length, ctx->src + ctx->token->offset);
|
Error_Report(ctx->error, 0, "Got unexpected token \"%.*s\" inside function argument list, where either ',' or ')' were expected", ctx->token->length, ctx->src + ctx->token->offset);
|
||||||
return NULL;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now prepare for the next identifier.
|
// Now prepare for the next identifier.
|
||||||
@@ -1980,10 +1990,9 @@ static Node *parse_function_arguments(Context *ctx, int *argc_)
|
|||||||
|
|
||||||
next(ctx); // Consume the ')'.
|
next(ctx); // Consume the ')'.
|
||||||
|
|
||||||
if(argc_ != NULL)
|
if(argc_ != NULL) *argc_ = argc;
|
||||||
*argc_ = argc;
|
if(argv_ != NULL) *argv_ = argv;
|
||||||
|
return 1;
|
||||||
return argv;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static Node *parse_function_definition(Context *ctx)
|
static Node *parse_function_definition(Context *ctx)
|
||||||
@@ -2022,8 +2031,8 @@ static Node *parse_function_definition(Context *ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int argc = 0; // Initialization for the warning.
|
int argc = 0; // Initialization for the warning.
|
||||||
Node *argv = parse_function_arguments(ctx, &argc);
|
Node *argv;
|
||||||
if(argv == NULL)
|
if(!parse_function_arguments(ctx, &argc, &argv))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if(done(ctx))
|
if(done(ctx))
|
||||||
@@ -2082,7 +2091,7 @@ static Node *parse_while_statement(Context *ctx)
|
|||||||
|
|
||||||
next(ctx); // Consume the "while" keyword.
|
next(ctx); // Consume the "while" keyword.
|
||||||
|
|
||||||
Node *condition = parse_expression(ctx, 1);
|
Node *condition = parse_expression(ctx, 1, 1);
|
||||||
|
|
||||||
if(condition == NULL)
|
if(condition == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -2168,7 +2177,7 @@ static Node *parse_dowhile_statement(Context *ctx)
|
|||||||
|
|
||||||
next(ctx); // Consume the "while" keyword.
|
next(ctx); // Consume the "while" keyword.
|
||||||
|
|
||||||
Node *condition = parse_expression(ctx, 1);
|
Node *condition = parse_expression(ctx, 1, 1);
|
||||||
|
|
||||||
if(condition == NULL)
|
if(condition == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|||||||
@@ -1099,7 +1099,7 @@ static _Bool step(Runtime *runtime, Error *error)
|
|||||||
case OPCODE_PUSHFUN:
|
case OPCODE_PUSHFUN:
|
||||||
{
|
{
|
||||||
assert(opc == 2);
|
assert(opc == 2);
|
||||||
assert(ops[0].type == OPTP_INT);
|
assert(ops[0].type == OPTP_IDX);
|
||||||
assert(ops[1].type == OPTP_INT);
|
assert(ops[1].type == OPTP_INT);
|
||||||
|
|
||||||
Object *closure = Object_NewClosure(runtime->frame->closure, runtime->frame->locals, Runtime_GetHeap(runtime), error);
|
Object *closure = Object_NewClosure(runtime->frame->closure, runtime->frame->locals, Runtime_GetHeap(runtime), error);
|
||||||
@@ -1159,6 +1159,18 @@ static _Bool step(Runtime *runtime, Error *error)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case OPCODE_PUSHNNETYP:
|
||||||
|
{
|
||||||
|
assert(opc == 0);
|
||||||
|
|
||||||
|
Object *obj = (Object*) Object_GetNoneType();
|
||||||
|
assert(obj != NULL);
|
||||||
|
|
||||||
|
if(!Runtime_Push(runtime, error, obj))
|
||||||
|
return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
case OPCODE_PUSHTYP:
|
case OPCODE_PUSHTYP:
|
||||||
{
|
{
|
||||||
assert(opc == 0);
|
assert(opc == 0);
|
||||||
@@ -1201,14 +1213,14 @@ static _Bool step(Runtime *runtime, Error *error)
|
|||||||
|
|
||||||
case OPCODE_JUMP:
|
case OPCODE_JUMP:
|
||||||
assert(opc == 1);
|
assert(opc == 1);
|
||||||
assert(ops[0].type == OPTP_INT);
|
assert(ops[0].type == OPTP_IDX);
|
||||||
runtime->frame->index = ops[0].as_int;
|
runtime->frame->index = ops[0].as_int;
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
case OPCODE_JUMPIFANDPOP:
|
case OPCODE_JUMPIFANDPOP:
|
||||||
{
|
{
|
||||||
assert(opc == 1);
|
assert(opc == 1);
|
||||||
assert(ops[0].type == OPTP_INT);
|
assert(ops[0].type == OPTP_IDX);
|
||||||
|
|
||||||
long long int target = ops[0].as_int;
|
long long int target = ops[0].as_int;
|
||||||
|
|
||||||
@@ -1240,7 +1252,7 @@ static _Bool step(Runtime *runtime, Error *error)
|
|||||||
case OPCODE_JUMPIFNOTANDPOP:
|
case OPCODE_JUMPIFNOTANDPOP:
|
||||||
{
|
{
|
||||||
assert(opc == 1);
|
assert(opc == 1);
|
||||||
assert(ops[0].type == OPTP_INT);
|
assert(ops[0].type == OPTP_IDX);
|
||||||
|
|
||||||
long long int target = ops[0].as_int;
|
long long int target = ops[0].as_int;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
|
||||||
|
#source
|
||||||
|
|
||||||
|
fun nop(a = 1)
|
||||||
|
{}
|
||||||
|
|
||||||
|
#bytecode
|
||||||
|
|
||||||
|
PUSHFUN nop, 1;
|
||||||
|
ASS "nop";
|
||||||
|
POP 1;
|
||||||
|
JUMP nop_end;
|
||||||
|
nop:
|
||||||
|
PUSHTYP;
|
||||||
|
PUSHNNETYP;
|
||||||
|
EQL;
|
||||||
|
JUMPIFNOTANDPOP not_none;
|
||||||
|
POP 1;
|
||||||
|
PUSHINT 1;
|
||||||
|
not_none:
|
||||||
|
ASS "a";
|
||||||
|
POP 1;
|
||||||
|
RETURN 0;
|
||||||
|
nop_end:
|
||||||
|
RETURN 0;
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
|
||||||
|
#source
|
||||||
|
|
||||||
|
fun nop(a = 1, b)
|
||||||
|
{}
|
||||||
|
|
||||||
|
#bytecode
|
||||||
|
|
||||||
|
PUSHFUN nop, 2;
|
||||||
|
ASS "nop";
|
||||||
|
POP 1;
|
||||||
|
JUMP nop_end;
|
||||||
|
nop:
|
||||||
|
ASS "b";
|
||||||
|
POP 1;
|
||||||
|
PUSHTYP;
|
||||||
|
PUSHNNETYP;
|
||||||
|
EQL;
|
||||||
|
JUMPIFNOTANDPOP not_none;
|
||||||
|
POP 1;
|
||||||
|
PUSHINT 1;
|
||||||
|
not_none:
|
||||||
|
ASS "a";
|
||||||
|
POP 1;
|
||||||
|
RETURN 0;
|
||||||
|
nop_end:
|
||||||
|
RETURN 0;
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
|
||||||
|
#source
|
||||||
|
|
||||||
|
fun nop(a, b = true)
|
||||||
|
{}
|
||||||
|
|
||||||
|
#bytecode
|
||||||
|
|
||||||
|
PUSHFUN nop, 2;
|
||||||
|
ASS "nop";
|
||||||
|
POP 1;
|
||||||
|
JUMP nop_end;
|
||||||
|
nop:
|
||||||
|
PUSHTYP;
|
||||||
|
PUSHNNETYP;
|
||||||
|
EQL;
|
||||||
|
JUMPIFNOTANDPOP not_none;
|
||||||
|
POP 1;
|
||||||
|
PUSHTRU;
|
||||||
|
not_none:
|
||||||
|
ASS "b";
|
||||||
|
POP 1;
|
||||||
|
ASS "a";
|
||||||
|
POP 1;
|
||||||
|
RETURN 0;
|
||||||
|
nop_end:
|
||||||
|
RETURN 0;
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
|
||||||
|
#source
|
||||||
|
|
||||||
|
fun nop(a: int = 1)
|
||||||
|
{}
|
||||||
|
|
||||||
|
#bytecode
|
||||||
|
|
||||||
|
PUSHFUN nop, 1;
|
||||||
|
ASS "nop";
|
||||||
|
POP 1;
|
||||||
|
JUMP nop_end;
|
||||||
|
nop:
|
||||||
|
PUSHTYP;
|
||||||
|
PUSHNNETYP;
|
||||||
|
EQL;
|
||||||
|
JUMPIFNOTANDPOP not_none;
|
||||||
|
POP 1;
|
||||||
|
PUSHINT 1;
|
||||||
|
not_none:
|
||||||
|
|
||||||
|
PUSHTYP;
|
||||||
|
PUSHVAR "int";
|
||||||
|
PUSHTYP;
|
||||||
|
PUSHTYPTYP;
|
||||||
|
EQL;
|
||||||
|
JUMPIFNOTANDPOP annot_not_ok;
|
||||||
|
EQL;
|
||||||
|
JUMPIFANDPOP type_ok;
|
||||||
|
ERROR "Bad type for argument 0";
|
||||||
|
annot_not_ok:
|
||||||
|
ERROR "Argument 0 type annotation 0 is not a type";
|
||||||
|
type_ok:
|
||||||
|
ASS "a";
|
||||||
|
POP 1;
|
||||||
|
RETURN 0;
|
||||||
|
nop_end:
|
||||||
|
RETURN 0;
|
||||||
Reference in New Issue
Block a user