map can have function members by placing function declaration between the curly braces
This commit is contained in:
+13
-9
@@ -352,13 +352,17 @@ fun parse(src: String) {
|
|||||||
return newRequest(method, url, version, headers);
|
return newRequest(method, url, version, headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
sample = cat(
|
fun test() {
|
||||||
"GET /search?client=firefox-b-d&q=http+request+dataset HTTP/2\r\n",
|
sample = cat(
|
||||||
"Host: www.google.com\r\n",
|
"GET /search?client=firefox-b-d&q=http+request+dataset HTTP/2\r\n",
|
||||||
"user-agent: curl/7.84.0\r\n",
|
"Host: www.google.com\r\n",
|
||||||
"accept: */*\r\n",
|
"user-agent: curl/7.84.0\r\n",
|
||||||
"\r\n");
|
"accept: */*\r\n",
|
||||||
|
"\r\n");
|
||||||
|
|
||||||
request, error = parse(sample);
|
request, error = parse(sample);
|
||||||
print("request=", request, "\n");
|
print("request=", request, "\n");
|
||||||
print("error=", error, "\n");
|
print("error=", error, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return {parse: parse, test: test};
|
||||||
|
|||||||
+3
-1
@@ -328,4 +328,6 @@ fun test() {
|
|||||||
print("passed: ", passed, "\n");
|
print("passed: ", passed, "\n");
|
||||||
print("failed: ", failed, "\n");
|
print("failed: ", failed, "\n");
|
||||||
print(" total: ", total, "\n");
|
print(" total: ", total, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return {parse: parse, test: test};
|
||||||
+33
-35
@@ -8,38 +8,40 @@ Scanner = {
|
|||||||
consumeSpaces: Callable
|
consumeSpaces: Callable
|
||||||
};
|
};
|
||||||
|
|
||||||
fun hint(scan: Scanner, n: int = 1) {
|
|
||||||
k = scan.i + n;
|
|
||||||
if k < count(scan.src):
|
|
||||||
return scan.src[k];
|
|
||||||
return none;
|
|
||||||
}
|
|
||||||
|
|
||||||
fun current(scan: Scanner)
|
|
||||||
return hint(scan, 0);
|
|
||||||
|
|
||||||
fun consume(scan: Scanner, n: int = 1) {
|
|
||||||
assert(n > 0);
|
|
||||||
limit = count(scan.src);
|
|
||||||
scan.i = min(scan.i + n, limit);
|
|
||||||
return current(scan);
|
|
||||||
}
|
|
||||||
|
|
||||||
fun consumeSpaces(scan: Scanner) {
|
|
||||||
char = current(scan);
|
|
||||||
while isSpace(char):
|
|
||||||
char = consume(scan);
|
|
||||||
return char;
|
|
||||||
}
|
|
||||||
|
|
||||||
fun newScanner(src: String) {
|
fun newScanner(src: String) {
|
||||||
|
|
||||||
|
fun isSpace(c: String)
|
||||||
|
return c == ' '
|
||||||
|
or c == '\t'
|
||||||
|
or c == '\n';
|
||||||
|
|
||||||
scan = {
|
scan = {
|
||||||
src: src,
|
src: src,
|
||||||
i: 0,
|
i: 0,
|
||||||
hint: hint,
|
|
||||||
consume: consume,
|
fun hint(scan: Scanner, n: int = 1) {
|
||||||
current: current,
|
k = scan.i + n;
|
||||||
consumeSpaces: consumeSpaces
|
if k < count(scan.src):
|
||||||
|
return scan.src[k];
|
||||||
|
return none;
|
||||||
|
}
|
||||||
|
|
||||||
|
fun current(scan: Scanner)
|
||||||
|
return scan->hint(0);
|
||||||
|
|
||||||
|
fun consume(scan: Scanner, n: int = 1) {
|
||||||
|
assert(n > 0);
|
||||||
|
limit = count(scan.src);
|
||||||
|
scan.i = min(scan.i + n, limit);
|
||||||
|
return scan->current();
|
||||||
|
}
|
||||||
|
|
||||||
|
fun consumeSpaces(scan: Scanner) {
|
||||||
|
char = scan->current();
|
||||||
|
while isSpace(char):
|
||||||
|
char = scan->consume();
|
||||||
|
return char;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
assert(istypeof(Scanner, scan));
|
assert(istypeof(Scanner, scan));
|
||||||
return scan;
|
return scan;
|
||||||
@@ -48,11 +50,7 @@ fun newScanner(src: String) {
|
|||||||
fun isDigit(char: ?String) {
|
fun isDigit(char: ?String) {
|
||||||
if char == none:
|
if char == none:
|
||||||
return false;
|
return false;
|
||||||
return string.ord(char) >= string.ord('0')
|
ord = string.ord;
|
||||||
and string.ord(char) <= string.ord('9');
|
return ord(char) >= ord('0')
|
||||||
|
and ord(char) <= ord('9');
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isSpace(c: String)
|
|
||||||
return c == ' '
|
|
||||||
or c == '\t'
|
|
||||||
or c == '\n';
|
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
|
||||||
|
Person = {name: String, age: int, sayHello: Callable};
|
||||||
|
|
||||||
|
fun newPerson(name: String, age: int)
|
||||||
|
return {
|
||||||
|
name: name,
|
||||||
|
age: age,
|
||||||
|
fun sayHello(self)
|
||||||
|
print("Hello from ", self.name, "!\n");
|
||||||
|
};
|
||||||
|
|
||||||
|
me = newPerson("Francesco", 24);
|
||||||
|
me->sayHello();
|
||||||
|
|
||||||
|
assert(istypeof(Person, me));
|
||||||
@@ -56,7 +56,7 @@ fun stringFromInteger(n: int) {
|
|||||||
|
|
||||||
temp = abs(n); # Temporary copy of the input
|
temp = abs(n); # Temporary copy of the input
|
||||||
text = ""; # The output we're about to compute
|
text = ""; # The output we're about to compute
|
||||||
|
|
||||||
while power >= 1: {
|
while power >= 1: {
|
||||||
# Pop the leftmost digit from [temp].
|
# Pop the leftmost digit from [temp].
|
||||||
digit = temp / power; # Get the leftmost digit
|
digit = temp / power; # Get the leftmost digit
|
||||||
@@ -78,6 +78,7 @@ fun floatFromInteger(n: int)
|
|||||||
return 1.0 * n;
|
return 1.0 * n;
|
||||||
|
|
||||||
fun integerFromDigit(char: String) {
|
fun integerFromDigit(char: String) {
|
||||||
|
ord = string.ord;
|
||||||
res = ord(char) - ord('0');
|
res = ord(char) - ord('0');
|
||||||
if res < 0 or res > 9:
|
if res < 0 or res > 9:
|
||||||
error("String isn't a digit");
|
error("String isn't a digit");
|
||||||
|
|||||||
+13
-6
@@ -70,6 +70,7 @@ typedef enum {
|
|||||||
EXPR_INT,
|
EXPR_INT,
|
||||||
EXPR_MAP,
|
EXPR_MAP,
|
||||||
EXPR_CALL,
|
EXPR_CALL,
|
||||||
|
EXPR_FUNC,
|
||||||
EXPR_PAIR,
|
EXPR_PAIR,
|
||||||
EXPR_LIST,
|
EXPR_LIST,
|
||||||
EXPR_NONE,
|
EXPR_NONE,
|
||||||
@@ -157,6 +158,14 @@ typedef struct {
|
|||||||
Node *set;
|
Node *set;
|
||||||
} IndexSelectionExprNode;
|
} IndexSelectionExprNode;
|
||||||
|
|
||||||
|
#warning "temp"
|
||||||
|
typedef struct {
|
||||||
|
ExprNode base;
|
||||||
|
Node *argv;
|
||||||
|
int argc;
|
||||||
|
Node *body;
|
||||||
|
} FuncExprNode;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
Node base;
|
Node base;
|
||||||
Node *condition;
|
Node *condition;
|
||||||
@@ -187,12 +196,10 @@ typedef struct {
|
|||||||
} ReturnNode;
|
} ReturnNode;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
Node base;
|
Node base;
|
||||||
char *name;
|
StringExprNode *name;
|
||||||
Node *argv;
|
FuncExprNode *expr;
|
||||||
int argc;
|
} FuncDeclNode;
|
||||||
Node *body;
|
|
||||||
} FunctionNode;
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
Node base;
|
Node base;
|
||||||
|
|||||||
@@ -255,7 +255,7 @@ static void emitInstrForArgumentNode(CodegenContext *ctx, ArgumentNode *arg, int
|
|||||||
emitInstr_POP1(ctx, arg->base.offset, arg->base.length);
|
emitInstr_POP1(ctx, arg->base.offset, arg->base.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void emitInstrForFuncNode(CodegenContext *ctx, FunctionNode *func)
|
static void emitInstrForFuncExprNode(CodegenContext *ctx, FuncExprNode *func)
|
||||||
{
|
{
|
||||||
Label *label_func = Label_New(ctx);
|
Label *label_func = Label_New(ctx);
|
||||||
Label *label_jump = Label_New(ctx);
|
Label *label_jump = Label_New(ctx);
|
||||||
@@ -266,11 +266,9 @@ static void emitInstrForFuncNode(CodegenContext *ctx, FunctionNode *func)
|
|||||||
{ .type = OPTP_PROMISE, .as_promise = Label_ToPromise(label_func) },
|
{ .type = OPTP_PROMISE, .as_promise = Label_ToPromise(label_func) },
|
||||||
{ .type = OPTP_INT, .as_int = func->argc },
|
{ .type = OPTP_INT, .as_int = func->argc },
|
||||||
};
|
};
|
||||||
CodegenContext_EmitInstr(ctx, OPCODE_PUSHFUN, ops, 2, func->base.offset, func->base.length);
|
CodegenContext_EmitInstr(ctx, OPCODE_PUSHFUN, ops, 2, func->base.base.offset, func->base.base.length);
|
||||||
}
|
}
|
||||||
emitInstr_ASS(ctx, func->name, func->base.offset, func->base.length); // Assign variable
|
emitInstr_JUMP(ctx, label_jump, func->base.base.offset, func->base.base.length); // Jump after the function code
|
||||||
emitInstr_POP1(ctx, func->base.offset, func->base.length); // Pop function object
|
|
||||||
emitInstr_JUMP(ctx, label_jump, func->base.offset, func->base.length); // Jump after the function code
|
|
||||||
Label_SetHere(label_func, ctx); // This is the function code index.
|
Label_SetHere(label_func, ctx); // This is the function code index.
|
||||||
|
|
||||||
// Compile the function body.
|
// Compile the function body.
|
||||||
@@ -302,6 +300,12 @@ static void emitInstrForFuncNode(CodegenContext *ctx, FunctionNode *func)
|
|||||||
Label_Free(label_jump);
|
Label_Free(label_jump);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void emitInstrForFuncDeclNode(CodegenContext *ctx, FuncDeclNode *func)
|
||||||
|
{
|
||||||
|
emitInstrForFuncExprNode(ctx, func->expr);
|
||||||
|
emitInstr_ASS(ctx, func->name->val, func->base.offset, func->base.length); // Assign variable
|
||||||
|
emitInstr_POP1(ctx, func->base.offset, func->base.length); // Pop function object
|
||||||
|
}
|
||||||
|
|
||||||
static void flattenTupleTree(CodegenContext *ctx, ExprNode *root, ExprNode *tuple[], int max, int *count)
|
static void flattenTupleTree(CodegenContext *ctx, ExprNode *root, ExprNode *tuple[], int max, int *count)
|
||||||
{
|
{
|
||||||
@@ -569,6 +573,10 @@ static void emitInstrForExprNode(CodegenContext *ctx, ExprNode *expr,
|
|||||||
emitInstrForFuncCallNode(ctx, (CallExprNode*) expr, label_break, 1);
|
emitInstrForFuncCallNode(ctx, (CallExprNode*) expr, label_break, 1);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
case EXPR_FUNC:
|
||||||
|
emitInstrForFuncExprNode(ctx, (FuncExprNode*) expr);
|
||||||
|
return;
|
||||||
|
|
||||||
case EXPR_SELECT:
|
case EXPR_SELECT:
|
||||||
{
|
{
|
||||||
IndexSelectionExprNode *sel = (IndexSelectionExprNode*) expr;
|
IndexSelectionExprNode *sel = (IndexSelectionExprNode*) expr;
|
||||||
@@ -723,7 +731,7 @@ static void emitInstrForNode(CodegenContext *ctx, Node *node, Label *label_break
|
|||||||
}
|
}
|
||||||
|
|
||||||
case NODE_FUNC:
|
case NODE_FUNC:
|
||||||
emitInstrForFuncNode(ctx, (FunctionNode*) node);
|
emitInstrForFuncDeclNode(ctx, (FuncDeclNode*) node);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|||||||
+115
-73
@@ -136,7 +136,7 @@ static Node *parse_expression(Context *ctx, _Bool allow_toplev_tuples, _Bool all
|
|||||||
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);
|
||||||
static Node *parse_function_definition(Context *ctx);
|
static FuncDeclNode *parse_function_definition(Context *ctx);
|
||||||
static Node *parse_postfix_expression(Context *ctx);
|
static Node *parse_postfix_expression(Context *ctx);
|
||||||
static Node *parse_prefix_expression(Context *ctx);
|
static Node *parse_prefix_expression(Context *ctx);
|
||||||
static Node *parse_while_statement(Context *ctx);
|
static Node *parse_while_statement(Context *ctx);
|
||||||
@@ -656,7 +656,7 @@ static Node *parse_statement(Context *ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
case TKWFUN:
|
case TKWFUN:
|
||||||
return parse_function_definition(ctx);
|
return (Node*) parse_function_definition(ctx);
|
||||||
|
|
||||||
case TKWWHILE:
|
case TKWWHILE:
|
||||||
return parse_while_statement(ctx);
|
return parse_while_statement(ctx);
|
||||||
@@ -965,58 +965,69 @@ static Node *parse_map_primary_expression(Context *ctx)
|
|||||||
while(1)
|
while(1)
|
||||||
{
|
{
|
||||||
Node *key;
|
Node *key;
|
||||||
_Bool key_is_a_single_ident;
|
Node *item;
|
||||||
|
|
||||||
|
bool item_is_func_decl = false;
|
||||||
|
|
||||||
|
if (current(ctx) == TKWFUN)
|
||||||
{
|
{
|
||||||
_Bool key_starts_with_an_ident = current(ctx) == TIDENT;
|
FuncDeclNode *func = parse_function_definition(ctx);
|
||||||
|
if (func == NULL) return NULL;
|
||||||
next(ctx);
|
key = (Node*) func->name;
|
||||||
|
item = (Node*) func->expr;
|
||||||
key_is_a_single_ident = key_starts_with_an_ident && (current(ctx) == TDONE || current(ctx) == ':');
|
item_is_func_decl = true;
|
||||||
|
|
||||||
prev(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(key_is_a_single_ident)
|
|
||||||
{
|
|
||||||
assert(current(ctx) == TIDENT);
|
|
||||||
key = makeStringExprNode(ctx, ctx->src + ctx->token->offset, ctx->token->length);
|
|
||||||
|
|
||||||
next(ctx);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
key = parse_expression(ctx, 0, 1);
|
_Bool key_is_a_single_ident;
|
||||||
|
{
|
||||||
|
_Bool key_starts_with_an_ident = current(ctx) == TIDENT;
|
||||||
|
|
||||||
|
next(ctx);
|
||||||
|
|
||||||
|
key_is_a_single_ident = key_starts_with_an_ident && (current(ctx) == TDONE || current(ctx) == ':');
|
||||||
|
|
||||||
|
prev(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(key_is_a_single_ident)
|
||||||
|
{
|
||||||
|
assert(current(ctx) == TIDENT);
|
||||||
|
key = makeStringExprNode(ctx, ctx->src + ctx->token->offset, ctx->token->length);
|
||||||
|
|
||||||
|
next(ctx);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
key = parse_expression(ctx, 0, 1);
|
||||||
|
|
||||||
|
if(key == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if(done(ctx))
|
||||||
|
{
|
||||||
|
Error_Report(ctx->error, 0,
|
||||||
|
"Source ended where a map key-value "
|
||||||
|
"separator ':' was expected");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(current(ctx) != ':')
|
||||||
|
{
|
||||||
|
Error_Report(ctx->error, 0,
|
||||||
|
"Got token \"%.*s\" where a map key-value "
|
||||||
|
"separator ':' was expected",
|
||||||
|
ctx->token->length,
|
||||||
|
ctx->src + ctx->token->offset);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
next(ctx);
|
||||||
|
|
||||||
|
// Parse.
|
||||||
|
item = parse_expression(ctx, 0, 1);
|
||||||
|
if(item == NULL) return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(key == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if(done(ctx))
|
|
||||||
{
|
|
||||||
Error_Report(ctx->error, 0,
|
|
||||||
"Source ended where a map key-value "
|
|
||||||
"separator ':' was expected");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(current(ctx) != ':')
|
|
||||||
{
|
|
||||||
Error_Report(ctx->error, 0,
|
|
||||||
"Got token \"%.*s\" where a map key-value "
|
|
||||||
"separator ':' was expected",
|
|
||||||
ctx->token->length,
|
|
||||||
ctx->src + ctx->token->offset);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
next(ctx);
|
|
||||||
|
|
||||||
// Parse.
|
|
||||||
Node *item = parse_expression(ctx, 0, 1);
|
|
||||||
|
|
||||||
if(item == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
// Append.
|
// Append.
|
||||||
if(tail)
|
if(tail)
|
||||||
{
|
{
|
||||||
@@ -1038,19 +1049,20 @@ static Node *parse_map_primary_expression(Context *ctx)
|
|||||||
if(current(ctx) == '}')
|
if(current(ctx) == '}')
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if(current(ctx) != ',')
|
if (!item_is_func_decl) {
|
||||||
{
|
if(current(ctx) != ',')
|
||||||
if(current(ctx) == TDONE)
|
{
|
||||||
Error_Report(ctx->error, 0, "Source ended inside a map literal");
|
if(current(ctx) == TDONE)
|
||||||
else
|
Error_Report(ctx->error, 0, "Source ended inside a map literal");
|
||||||
Error_Report(ctx->error, 0,
|
else
|
||||||
"Got unexpected token \"%.*s\" inside "
|
Error_Report(ctx->error, 0,
|
||||||
"map literal, where ',' or '}' were expected",
|
"Got unexpected token \"%.*s\" inside "
|
||||||
ctx->token->length, ctx->src + ctx->token->offset);
|
"map literal, where ',' or '}' were expected",
|
||||||
return NULL;
|
ctx->token->length, ctx->src + ctx->token->offset);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
next(ctx); // Skip the ','.
|
||||||
}
|
}
|
||||||
|
|
||||||
next(ctx); // Skip the ','.
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2001,7 +2013,7 @@ static _Bool parse_function_arguments(Context *ctx, int *argc_, Node **argv_)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Node *parse_function_definition(Context *ctx)
|
static FuncDeclNode *parse_function_definition(Context *ctx)
|
||||||
{
|
{
|
||||||
assert(ctx != NULL);
|
assert(ctx != NULL);
|
||||||
|
|
||||||
@@ -2028,13 +2040,15 @@ static Node *parse_function_definition(Context *ctx)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *name = copy_token_text(ctx);
|
char *name_val = copy_token_text(ctx);
|
||||||
|
if(name_val == NULL)
|
||||||
if(name == NULL)
|
|
||||||
{
|
{
|
||||||
Error_Report(ctx->error, 1, "No memory");
|
Error_Report(ctx->error, 1, "No memory");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
int name_len = strlen(name_val);
|
||||||
|
int name_offset = current_token(ctx)->offset;
|
||||||
|
int name_length = current_token(ctx)->length;
|
||||||
|
|
||||||
int argc = 0; // Initialization for the warning.
|
int argc = 0; // Initialization for the warning.
|
||||||
Node *argv;
|
Node *argv;
|
||||||
@@ -2052,28 +2066,56 @@ static Node *parse_function_definition(Context *ctx)
|
|||||||
if(body == NULL)
|
if(body == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
FunctionNode *func;
|
FuncDeclNode *func;
|
||||||
{
|
{
|
||||||
// Make argument node.
|
int length = body->offset
|
||||||
func = BPAlloc_Malloc(ctx->alloc, sizeof(FunctionNode));
|
+ body->length
|
||||||
|
- offset;
|
||||||
|
|
||||||
|
FuncExprNode *expr = BPAlloc_Malloc(ctx->alloc, sizeof(FuncExprNode));
|
||||||
|
if (expr == NULL)
|
||||||
|
{
|
||||||
|
Error_Report(ctx->error, 1, "No memory");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
expr->base.base.kind = NODE_EXPR;
|
||||||
|
expr->base.base.next = NULL;
|
||||||
|
expr->base.base.offset = offset;
|
||||||
|
expr->base.base.length = length;
|
||||||
|
expr->base.kind = EXPR_FUNC;
|
||||||
|
expr->argv = argv;
|
||||||
|
expr->argc = argc;
|
||||||
|
expr->body = body;
|
||||||
|
|
||||||
|
StringExprNode *name = BPAlloc_Malloc(ctx->alloc, sizeof(StringExprNode));
|
||||||
|
if (name == NULL)
|
||||||
|
{
|
||||||
|
Error_Report(ctx->error, 1, "No memory");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
name->base.base.kind = NODE_EXPR;
|
||||||
|
name->base.base.next = NULL;
|
||||||
|
name->base.base.offset = name_offset;
|
||||||
|
name->base.base.length = name_length;
|
||||||
|
name->base.kind = EXPR_STRING;
|
||||||
|
name->val = name_val;
|
||||||
|
name->len = name_len;
|
||||||
|
|
||||||
|
func = BPAlloc_Malloc(ctx->alloc, sizeof(FuncDeclNode));
|
||||||
if(func == NULL)
|
if(func == NULL)
|
||||||
{
|
{
|
||||||
Error_Report(ctx->error, 1, "No memory");
|
Error_Report(ctx->error, 1, "No memory");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
func->base.kind = NODE_FUNC;
|
func->base.kind = NODE_FUNC;
|
||||||
func->base.next = NULL;
|
func->base.next = NULL;
|
||||||
func->base.offset = offset;
|
func->base.offset = offset;
|
||||||
func->base.length = body->offset + body->length - offset;
|
func->base.length = length;
|
||||||
func->name = name;
|
func->name = name;
|
||||||
func->argv = argv;
|
func->expr = expr;
|
||||||
func->argc = argc;
|
|
||||||
func->body = body;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (Node*) func;
|
return func;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Node *parse_while_statement(Context *ctx)
|
static Node *parse_while_statement(Context *ctx)
|
||||||
|
|||||||
Reference in New Issue
Block a user