Add in '#' operator for length

This commit is contained in:
Bruce Hill 2024-02-18 01:27:25 -05:00
parent 733ebfd234
commit eabff011ea
5 changed files with 34 additions and 2 deletions

1
ast.c
View File

@ -94,6 +94,7 @@ CORD ast_to_cord(ast_t *ast)
T(Assign, "(targets=%r, values=%r)", ast_list_to_cord(data.targets), ast_list_to_cord(data.values))
T(BinaryOp, "(%r, %s, %r)", ast_to_cord(data.lhs), OP_NAMES[data.op], ast_to_cord(data.rhs))
T(UpdateAssign, "(%r, %s, %r)", ast_to_cord(data.lhs), OP_NAMES[data.op], ast_to_cord(data.rhs))
T(Length, "(%r)", ast_to_cord(data.value))
T(Negative, "(%r)", ast_to_cord(data.value))
T(Not, "(%r)", ast_to_cord(data.value))
T(HeapAllocate, "(%r)", ast_to_cord(data.value))

4
ast.h
View File

@ -88,7 +88,7 @@ typedef enum {
StringLiteral, StringJoin,
Declare, Assign,
BinaryOp, UpdateAssign,
Not, Negative, HeapAllocate, StackReference,
Length, Not, Negative, HeapAllocate, StackReference,
Min, Max,
Array, Table, TableEntry,
FunctionDef, Lambda,
@ -150,7 +150,7 @@ struct ast_s {
} BinaryOp, UpdateAssign;
struct {
ast_t *value;
} Not, Negative, HeapAllocate, StackReference;
} Length, Not, Negative, HeapAllocate, StackReference;
struct {
ast_t *lhs, *rhs, *key;
} Min, Max;

View File

@ -75,6 +75,27 @@ CORD compile(env_t *env, ast_t *ast)
char *buf = asprintfa(Match(ast, Num)->bits == 64 ? "%a" : "%af", Match(ast, Num)->n);
return CORD_from_char_star(buf);
}
case Length: {
ast_t *expr = Match(ast, Length)->value;
CORD code = compile(env, expr);
type_t *t = get_type(env, expr);
next_value:;
switch (t->tag) {
case PointerType: {
auto ptr = Match(t, PointerType);
if (ptr->is_optional)
code_err(ast, "You can't dereference this value, since it's not guaranteed to be non-null");
code = CORD_all("*(", code, ")");
t = ptr->pointed;
goto next_value;
}
case StringType: return CORD_all("CORD_len(", code, ")");
case ArrayType: return CORD_all("I64((", code, ").length)");
case TableType: return CORD_all("I64((", code, ").entries.length)");
default: code_err(ast, "Length is only supported for strings, arrays, and tables, not: %T", t);
}
break;
}
case Not: return CORD_asprintf("not(%r)", compile(env, Match(ast, Not)->value));
case Negative: return CORD_asprintf("-(%r)", compile(env, Match(ast, Negative)->value));
case HeapAllocate: return CORD_asprintf("$heap(%r)", compile(env, Match(ast, HeapAllocate)->value));

View File

@ -839,6 +839,14 @@ PARSER(parse_while) {
return NewAST(ctx->file, start, pos, While, .condition=condition, .body=body);
}
PARSER(parse_length) {
const char *start = pos;
if (!match(&pos, "#")) return NULL;
spaces(&pos);
ast_t *val = expect(ctx, start, &pos, parse_expr, "I expected an expression for this '#'");
return NewAST(ctx->file, start, pos, Length, .value=val);
}
PARSER(parse_heap_alloc) {
const char *start = pos;
if (!match(&pos, "@")) return NULL;
@ -1070,6 +1078,7 @@ PARSER(parse_term_no_suffix) {
|| (term=parse_nil(ctx, pos))
|| (term=parse_num(ctx, pos))
|| (term=parse_int(ctx, pos))
|| (term=parse_length(ctx, pos))
|| (term=parse_negative(ctx, pos))
|| (term=parse_heap_alloc(ctx, pos))
|| (term=parse_stack_reference(ctx, pos))

View File

@ -368,6 +368,7 @@ type_t *get_type(env_t *env, ast_t *ast)
return Type(AbortType);
}
case Pass: return Type(VoidType);
case Length: return Type(IntType, .bits=64);
case Negative: {
type_t *t = get_type(env, Match(ast, Negative)->value);
if (t->tag == IntType || t->tag == NumType)