Browse Source

array lookup with a dot-number token

master
Martin Dørum 3 years ago
parent
commit
fb5a02c602
8 changed files with 80 additions and 4 deletions
  1. 9
    1
      include/lang2/bytecode.h
  2. 1
    0
      include/lang2/gen/gen.h
  3. 2
    0
      include/lang2/parse/lex.h
  4. 6
    0
      lib/gen/gen.c
  5. 31
    2
      lib/parse/lex.c
  6. 14
    1
      lib/parse/parse.c
  7. 8
    0
      lib/vm/print.c
  8. 9
    0
      lib/vm/vm.c

+ 9
- 1
include/lang2/bytecode.h View File

@@ -153,13 +153,21 @@ enum l2_opcode {
L2_OP_NAMESPACE_SET,

/*
* Set a namespace's name to a value.
* Lookup a value from a namespace.
* Pop <key>
* Pop <ns>
* Push <ns[<key>]>
*/
L2_OP_NAMESPACE_LOOKUP,

/*
* Look up a value from an array.
* Pop <key>
* Pop <arr>
* Push <arr[<key>]>
*/
L2_OP_DIRECT_ARRAY_LOOKUP,

/*
* Halt execution.
*/

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

@@ -35,6 +35,7 @@ void l2_gen_function(struct l2_generator *gen, l2_word pos);
void l2_gen_namespace(struct l2_generator *gen);
void l2_gen_namespace_set(struct l2_generator *gen, char **ident);
void l2_gen_namespace_lookup(struct l2_generator *gen, char **ident);
void l2_gen_direct_array_lookup(struct l2_generator *gen, int number);
void l2_gen_stack_frame_lookup(struct l2_generator *gen, char **ident);
void l2_gen_func_call(struct l2_generator *gen);


+ 2
- 0
include/lang2/parse/lex.h View File

@@ -13,6 +13,7 @@ enum l2_token_kind {
L2_TOK_QUOT,
L2_TOK_COMMA,
L2_TOK_PERIOD,
L2_TOK_DOT_NUMBER,
L2_TOK_COLON,
L2_TOK_COLON_EQ,
L2_TOK_EOL,
@@ -33,6 +34,7 @@ struct l2_token {
union {
char *str;
double num;
int integer;
} v;
};


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

@@ -140,6 +140,12 @@ void l2_gen_namespace_lookup(struct l2_generator *gen, char **ident) {
put(gen, L2_OP_NAMESPACE_LOOKUP);
}

void l2_gen_direct_array_lookup(struct l2_generator *gen, int number) {
put(gen, L2_OP_PUSH);
put(gen, number);
put(gen, L2_OP_DIRECT_ARRAY_LOOKUP);
}

void l2_gen_stack_frame_lookup(struct l2_generator *gen, char **ident) {
size_t atom_id = l2_strset_put(&gen->atomset, ident);
put(gen, L2_OP_PUSH);

+ 31
- 2
lib/parse/lex.c View File

@@ -61,6 +61,8 @@ const char *l2_token_kind_name(enum l2_token_kind kind) {
return "comma";
case L2_TOK_PERIOD:
return "period";
case L2_TOK_DOT_NUMBER:
return "dot-number";
case L2_TOK_COLON:
return "colon";
case L2_TOK_COLON_EQ:
@@ -122,9 +124,13 @@ static int is_whitespace(int ch) {
return ch == ' ' || ch == '\r' || ch == '\n' || ch == '\t';
}

static int is_numeric(int ch) {
return ch >= '0' && ch <= '9';
}

static int skip_whitespace(struct l2_lexer *lexer) {
int nl = 0;
while (is_whitespace(l2_bufio_peek(&lexer->reader, 1))) {
while (is_whitespace(peek_ch(lexer))) {
int ch = read_ch(lexer);
if (ch == '\n') {
nl = 1;
@@ -134,6 +140,24 @@ static int skip_whitespace(struct l2_lexer *lexer) {
return nl;
}

static int read_integer(struct l2_lexer *lexer) {
char buffer[16]; // Should be enough
int len = 0;

while (len < sizeof(buffer) - 1 && is_numeric(peek_ch(lexer))) {
buffer[len++] = read_ch(lexer);
}

int num = 0;
int power = 1;
for (int i = len - 1; i >= 0; --i) {
num += (buffer[i] - '0') * power;
power *= 10;
}

return num;
}

static void read_string(struct l2_lexer *lexer, struct l2_token *tok) {
tok->kind = L2_TOK_STRING;
tok->v.str = malloc(16);
@@ -316,7 +340,12 @@ static void read_tok(struct l2_lexer *lexer, struct l2_token *tok) {

case '.':
read_ch(lexer);
tok->kind = L2_TOK_PERIOD;
if (is_numeric(peek_ch(lexer))) {
tok->kind = L2_TOK_DOT_NUMBER;
tok->v.integer = read_integer(lexer);
} else {
tok->kind = L2_TOK_PERIOD;
}
break;

case ':':

+ 14
- 1
lib/parse/parse.c View File

@@ -71,6 +71,11 @@ static int parse_function_literal_impl(
l2_trace_scope("function literal");
// '{' and EOL already skipped by parse_object_or_function_literal

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

int first = 1;
while (1) {
if (l2_lexer_peek(lexer, 1)->kind == L2_TOK_CLOSE_BRACE) {
@@ -184,6 +189,8 @@ static int parse_arg_level_expression_base(
l2_token_kind_name(tok->kind));
return -1;
}

l2_lexer_consume(lexer); // ')'
} else if (tok->kind == L2_TOK_IDENT) {
l2_trace_scope("ident");
l2_trace("ident '%s'", tok->v.str);
@@ -245,13 +252,19 @@ static int parse_arg_level_expression(
l2_gen_push(gen, 0);
l2_gen_func_call(gen);
} else if (tok->kind == L2_TOK_PERIOD && tok2->kind == L2_TOK_IDENT) {
l2_trace_scope("lookup");
l2_trace_scope("namespace lookup");
l2_trace("ident '%s'", tok2->v.str);
char *ident = l2_token_extract_str(tok2);
l2_lexer_consume(lexer); // '.'
l2_lexer_consume(lexer); // ident

l2_gen_namespace_lookup(gen, &ident);
} else if (tok->kind == L2_TOK_DOT_NUMBER) {
l2_trace_scope("direct array lookup");
int number = tok->v.integer;
l2_lexer_consume(lexer); // dot-number

l2_gen_direct_array_lookup(gen, number);
} else {
break;
}

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

@@ -197,6 +197,14 @@ void l2_vm_print_op(l2_word *ops, size_t opcount, size_t *ptr) {
printf("NAMESPACE_SET\n");
break;

case L2_OP_NAMESPACE_LOOKUP:
printf("NAMESPACE_LOOKUP\n");
break;

case L2_OP_DIRECT_ARRAY_LOOKUP:
printf("DIRECT_ARRAY_LOOKUP\n");
break;

case L2_OP_HALT:
printf("HALT\n");
break;

+ 9
- 0
lib/vm/vm.c View File

@@ -405,6 +405,15 @@ void l2_vm_step(struct l2_vm *vm) {
}
break;

case L2_OP_DIRECT_ARRAY_LOOKUP:
{
l2_word key = vm->stack[--vm->sptr];
l2_word arr = vm->stack[--vm->sptr];
// TODO: Error if out of bounds or incorrect type
vm->stack[vm->sptr++] = vm->values[arr].array->data[key];
break;
}

case L2_OP_HALT:
break;
}

Loading…
Cancel
Save