Browse Source

parse changes, and operators == and !=

master
Martin Dørum 7 months ago
parent
commit
6ebc5345b3
5 changed files with 89 additions and 33 deletions
  1. 2
    0
      include/lang2/builtins.x.h
  2. 27
    31
      lib/parse/lex.c
  3. 3
    1
      lib/parse/parse.c
  4. 54
    0
      lib/vm/builtins.c
  5. 3
    1
      lib/vm/vm.c

+ 2
- 0
include/lang2/builtins.x.h View File

@@ -11,6 +11,8 @@ X("+", l2_builtin_add)
X("-", l2_builtin_sub)
X("*", l2_builtin_mul)
X("/", l2_builtin_div)
X("==", l2_builtin_eq)
X("!=", l2_builtin_neq)
X("print", l2_builtin_print)
X("len", l2_builtin_len)
X("if", l2_builtin_if)

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

@@ -127,6 +127,16 @@ static int is_numeric(int ch) {
return ch >= '0' && ch <= '9';
}

static int is_ident(int ch) {
return !is_whitespace(ch) && ch != EOF &&
ch != '(' && ch != ')' &&
ch != '{' && ch != '}' &&
ch != '[' && ch != ']' &&
ch != '\'' &&
ch != ',' && ch != '.' &&
ch != ':' && ch != ';';
}

static int skip_whitespace(struct l2_lexer *lexer) {
int nl = 0;
while (1) {
@@ -413,25 +423,7 @@ static void read_ident(struct l2_lexer *lexer, struct l2_token *tok) {
while (1) {
int ch = peek_ch(lexer);

if (is_whitespace(ch)) {
dest[idx] = '\0';
return;
}

switch (ch) {
case '(':
case ')':
case '{':
case '}':
case '[':
case ']':
case '\'':
case ',':
case '.':
case ':':
case '=':
case ';':
case EOF:
if (!is_ident(ch)) {
dest[idx] = '\0';
return;
}
@@ -563,11 +555,6 @@ static void read_tok(struct l2_lexer *lexer, struct l2_token *tok) {
}
break;

case '=':
read_ch(lexer);
tok->v.flags = L2_TOK_EQUALS;
break;

case EOF:
tok->v.flags = L2_TOK_EOF;
break;
@@ -578,14 +565,23 @@ static void read_tok(struct l2_lexer *lexer, struct l2_token *tok) {
break;

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

read_ident(lexer, tok);
if (
is_numeric(ch) ||
(ch == '-' && is_numeric(ch2))) {
read_number(lexer, tok);
break;
}

tok->v.flags = L2_TOK_IDENT;
read_ident(lexer, tok);

if (l2_token_is_small(tok) && strcmp(tok->v.strbuf, "=") == 0) {
tok->v.flags = L2_TOK_EQUALS;
}
}
}
}


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

@@ -25,7 +25,9 @@ static int tok_is_infix(struct l2_token *tok) {
strcmp(str, "+") == 0 ||
strcmp(str, "-") == 0 ||
strcmp(str, "*") == 0 ||
strcmp(str, "/") == 0;
strcmp(str, "/") == 0 ||
strcmp(str, "==") == 0 ||
strcmp(str, "!=") == 0;
}

static int parse_expression(

+ 54
- 0
lib/vm/builtins.c View File

@@ -164,6 +164,60 @@ l2_word l2_builtin_div(struct l2_vm *vm, l2_word argc, l2_word *argv) {
return id;
}

l2_word l2_builtin_eq(struct l2_vm *vm, l2_word argc, l2_word *argv) {
if (argc < 2) {
return vm->ktrue;
}

for (l2_word i = 1; i < argc; ++i) {
if (argv[i - 1] == argv[i]) continue;
struct l2_vm_value *a = &vm->values[argv[i - 1]];
struct l2_vm_value *b = &vm->values[argv[i]];
if (a->flags != b->flags) {
return vm->kfalse;
}

enum l2_value_type typ = l2_vm_value_type(a);
if (typ == L2_VAL_TYPE_ATOM) {
if (a->atom != b->atom) {
return vm->kfalse;
}
} else if (typ == L2_VAL_TYPE_REAL) {
if (a->real != b->real) {
return vm->kfalse;
}
} else if (typ == L2_VAL_TYPE_BUFFER) {
if (a->buffer == NULL && b->buffer == NULL) continue;
if (a->buffer == NULL || b->buffer == NULL) {
return vm->kfalse;
}

if (a->buffer->len != b->buffer->len) {
return vm->kfalse;
}

if (memcmp(a->buffer->data, b->buffer->data, a->buffer->len) != 0) {
return vm->kfalse;
}
} else {
return vm->kfalse;
}
}

return vm->ktrue;
}

l2_word l2_builtin_neq(struct l2_vm *vm, l2_word argc, l2_word *argv) {
l2_word ret_id = l2_builtin_eq(vm, argc, argv);
if (ret_id == vm->ktrue) {
return vm->kfalse;
} else if (ret_id == vm->kfalse) {
return vm->ktrue;
} else {
return ret_id;
}
}

l2_word l2_builtin_print(struct l2_vm *vm, l2_word argc, l2_word *argv) {
for (size_t i = 0; i < argc; ++i) {
if (i != 0) {

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

@@ -196,19 +196,21 @@ void l2_vm_init(struct l2_vm *vm, l2_word *ops, size_t opcount) {
#define Y(name, k) \
if (strcmp(#k, "knone") == 0) { \
id = 0; \
l2_vm_namespace_set(&vm->values[builtins], key, id); \
} else { \
id = alloc_val(vm); \
vm->values[id].flags = L2_VAL_TYPE_ATOM | L2_VAL_CONST; \
vm->values[id].atom = key; \
} \
vm->k = id; \
l2_vm_namespace_set(&vm->values[builtins], key++, id);
key += 1;
#define X(name, f) \
id = alloc_val(vm); \
vm->values[id].flags = L2_VAL_TYPE_CFUNCTION | L2_VAL_CONST; \
vm->values[id].cfunc = f; \
l2_vm_namespace_set(&vm->values[builtins], key++, id);
#include "builtins.x.h"
#undef Y
#undef X
}


Loading…
Cancel
Save