Browse Source

infix functions

master
Martin Dørum 3 years ago
parent
commit
8c10cec784
7 changed files with 109 additions and 5 deletions
  1. 10
    0
      include/lang2/bytecode.h
  2. 1
    0
      include/lang2/gen/gen.h
  3. 4
    0
      lib/gen/gen.c
  4. 8
    1
      lib/parse/lex.c
  5. 32
    3
      lib/parse/parse.c
  6. 4
    0
      lib/vm/print.c
  7. 50
    1
      lib/vm/vm.c

+ 10
- 0
include/lang2/bytecode.h View File

*/ */
L2_OP_FUNC_CALL, L2_OP_FUNC_CALL,


/*
* Call an infix function
* Pop <rhs>
* Pop <func>
* Pop <lhs>
* Call <func>
* (Before returning, the function will push a return value onto the stack)
*/
L2_OP_FUNC_CALL_INFIX,

/* /*
* Jump relative; rjmp <count> * Jump relative; rjmp <count>
* Jump <count> words forwards * Jump <count> words forwards

+ 1
- 0
include/lang2/gen/gen.h View File

void l2_gen_stack_frame_replace(struct l2_generator *gen, char **ident); void l2_gen_stack_frame_replace(struct l2_generator *gen, char **ident);
void l2_gen_stack_frame_replace_copy(struct l2_generator *gen, char *ident); void l2_gen_stack_frame_replace_copy(struct l2_generator *gen, char *ident);
void l2_gen_func_call(struct l2_generator *gen, l2_word argc); void l2_gen_func_call(struct l2_generator *gen, l2_word argc);
void l2_gen_func_call_infix(struct l2_generator *gen);


#endif #endif

+ 4
- 0
lib/gen/gen.c View File

put(gen, L2_OP_FUNC_CALL); put(gen, L2_OP_FUNC_CALL);
put(gen, argc); put(gen, argc);
} }

void l2_gen_func_call_infix(struct l2_generator *gen) {
put(gen, L2_OP_FUNC_CALL_INFIX);
}

+ 8
- 1
lib/parse/lex.c View File

return ch; return ch;
} }


static int peek_ch_n(struct l2_lexer *lexer, int n) {
int ch = l2_bufio_peek(&lexer->reader, n);
return ch;
}

static int read_ch(struct l2_lexer *lexer) { static int read_ch(struct l2_lexer *lexer) {
int ch = l2_bufio_get(&lexer->reader); int ch = l2_bufio_get(&lexer->reader);
lexer->ch += 1; lexer->ch += 1;
break; break;


default: default:
if (is_numeric(ch) || ch == '-') {
if (
is_numeric(ch) ||
(ch == '-' && is_numeric(peek_ch_n(lexer, 2)))) {
read_number(lexer, tok); read_number(lexer, tok);
break; break;
} }

+ 32
- 3
lib/parse/parse.c View File

kind == L2_TOK_EOL; kind == L2_TOK_EOL;
} }


static int tok_is_infix(struct l2_token *tok) {
if (l2_token_get_kind(tok) != L2_TOK_IDENT) return 0;
char *str;
if (l2_token_is_small(tok)) {
str = tok->v.strbuf;
} else {
str = tok->v.str;
}

return
(str[0] == '$' && str[1] != '\0') ||
strcmp(str, "+") == 0 ||
strcmp(str, "-") == 0 ||
strcmp(str, "*") == 0 ||
strcmp(str, "/") == 0;
}

static int parse_expression( static int parse_expression(
struct l2_lexer *lexer, struct l2_generator *gen, struct l2_parse_error *err); struct l2_lexer *lexer, struct l2_generator *gen, struct l2_parse_error *err);


// '{' and EOL already skipped by parse_object_or_function_literal // '{' and EOL already skipped by parse_object_or_function_literal


// The arguments array will be at the top of the stack // The arguments array will be at the top of the stack
char *ident = malloc(2);
ident[0] = '$'; ident[1] = '\0';
l2_gen_stack_frame_set(gen, &ident);
char *ident = "$";
l2_gen_stack_frame_set_copy(gen, ident);


int first = 1; int first = 1;
while (1) { while (1) {
return -1; return -1;
} }


if (tok_is_infix(l2_lexer_peek(lexer, 1))) {
if (parse_arg_level_expression(lexer, gen, err) < 0) {
return -1;
}

if (parse_arg_level_expression(lexer, gen, err) < 0) {
return -1;
}


l2_gen_func_call_infix(gen);
}

if (!tok_is_end(l2_lexer_peek(lexer, 1))) { if (!tok_is_end(l2_lexer_peek(lexer, 1))) {
if (parse_func_call_after_base(lexer, gen, err) < 0) { if (parse_func_call_after_base(lexer, gen, err) < 0) {
return -1; return -1;

+ 4
- 0
lib/vm/print.c View File

printf("FUNC_CALL %08x\n", ops[(*ptr)++]); printf("FUNC_CALL %08x\n", ops[(*ptr)++]);
return; return;


case L2_OP_FUNC_CALL_INFIX:
printf("FUNC_CALL_INFIX\n");
return;

case L2_OP_RJMP: case L2_OP_RJMP:
printf("RJMP %08x\n", ops[(*ptr)++]); printf("RJMP %08x\n", ops[(*ptr)++]);
return; return;

+ 50
- 1
lib/vm/vm.c View File

struct l2_vm_value *func = &vm->values[func_id]; struct l2_vm_value *func = &vm->values[func_id];


l2_word stack_base = vm->sptr; l2_word stack_base = vm->sptr;

enum l2_value_type typ = l2_vm_value_type(func); enum l2_value_type typ = l2_vm_value_type(func);


// C functions are called differently from language functions // C functions are called differently from language functions
} }
break; break;


case L2_OP_FUNC_CALL_INFIX:
{
l2_word rhs = vm->stack[--vm->sptr];
l2_word func_id = vm->stack[--vm->sptr];
l2_word lhs = vm->stack[--vm->sptr];

struct l2_vm_value *func = &vm->values[func_id];

l2_word stack_base = vm->sptr;
enum l2_value_type typ = l2_vm_value_type(func);

// C functions are called differently from language functions
if (typ == L2_VAL_TYPE_CFUNCTION) {
l2_word argv[] = { lhs, rhs };
vm->stack[vm->sptr++] = func->cfunc(vm, 2, argv);
break;
}

// Don't interpret a non-function as a function
if (typ != L2_VAL_TYPE_FUNCTION) {
vm->stack[vm->sptr++] = l2_vm_error(vm, "Attempt to call non-function");
break;
}

l2_word arr_id = alloc_val(vm);
vm->values[arr_id].flags = L2_VAL_TYPE_ARRAY;
vm->values[arr_id].array = malloc(
sizeof(struct l2_vm_array) + sizeof(l2_word) * 2);
struct l2_vm_array *arr = vm->values[arr_id].array;
arr->len = 2;
arr->size = 2;
arr->data[0] = lhs;
arr->data[1] = rhs;

vm->stack[vm->sptr++] = arr_id;

l2_word ns_id = alloc_val(vm);
func = &vm->values[func_id]; // func might be stale after alloc
vm->values[ns_id].extra.ns_parent = func->func.ns;
vm->values[ns_id].ns = NULL;
vm->values[ns_id].flags = L2_VAL_TYPE_NAMESPACE;
vm->fstack[vm->fsptr].ns = ns_id;
vm->fstack[vm->fsptr].retptr = vm->iptr;
vm->fstack[vm->fsptr].sptr = stack_base;
vm->fsptr += 1;

vm->iptr = func->func.pos;
}
break;

case L2_OP_HALT: case L2_OP_HALT:
vm->halted = 1; vm->halted = 1;
break; break;

Loading…
Cancel
Save