tomo/ast.h

354 lines
8.9 KiB
C
Raw Normal View History

2024-02-04 12:23:59 -08:00
#pragma once
2024-03-18 09:49:38 -07:00
// Logic defining ASTs (abstract syntax trees) to represent code
2024-09-17 22:11:50 -07:00
#include <err.h>
#include <gc/cord.h>
2024-09-17 22:11:50 -07:00
#include <printf.h>
2024-02-04 12:23:59 -08:00
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include "stdlib/datatypes.h"
2024-09-13 17:18:08 -07:00
#include "stdlib/files.h"
#include "stdlib/util.h"
2024-02-04 12:23:59 -08:00
#define NewAST(_file, _start, _end, ast_tag, ...) (new(ast_t, .file=_file, .start=_start, .end=_end,\
.tag=ast_tag, .__data.ast_tag={__VA_ARGS__}))
#define NewTypeAST(_file, _start, _end, ast_tag, ...) (new(type_ast_t, .file=_file, .start=_start, .end=_end,\
.tag=ast_tag, .__data.ast_tag={__VA_ARGS__}))
#define FakeAST(ast_tag, ...) (new(ast_t, .tag=ast_tag, .__data.ast_tag={__VA_ARGS__}))
#define WrapAST(ast, ast_tag, ...) (new(ast_t, .file=(ast)->file, .start=(ast)->start, .end=(ast)->end, .tag=ast_tag, .__data.ast_tag={__VA_ARGS__}))
2024-07-26 10:30:24 -07:00
#define TextAST(ast, _str) WrapAST(ast, TextLiteral, .str=GC_strdup(_str))
2024-09-17 22:11:50 -07:00
#define Match(x, _tag) ((x)->tag == _tag ? &(x)->__data._tag : (errx(1, __FILE__ ":%d This was supposed to be a " # _tag "\n", __LINE__), &(x)->__data._tag))
2024-02-04 12:23:59 -08:00
2024-09-17 22:10:34 -07:00
#define REVERSE_LIST(list) do { \
__typeof(list) _prev = NULL; \
__typeof(list) _next = NULL; \
auto _current = list; \
while (_current != NULL) { \
_next = _current->next; \
_current->next = _prev; \
_prev = _current; \
_current = _next; \
} \
list = _prev; \
} while(0)
2024-02-04 12:23:59 -08:00
struct binding_s;
typedef struct type_ast_s type_ast_t;
typedef struct ast_s ast_t;
typedef struct ast_list_s {
ast_t *ast;
struct ast_list_s *next;
} ast_list_t;
2024-02-07 21:52:18 -08:00
typedef struct arg_ast_s {
const char *name;
2024-02-04 12:23:59 -08:00
type_ast_t *type;
2024-02-23 09:50:01 -08:00
ast_t *value;
2024-02-07 21:52:18 -08:00
struct arg_ast_s *next;
} arg_ast_t;
2024-02-04 12:23:59 -08:00
2024-05-01 10:53:51 -07:00
typedef struct when_clause_s {
ast_t *pattern, *body;
2024-05-01 10:53:51 -07:00
struct when_clause_s *next;
} when_clause_t;
2024-02-04 12:23:59 -08:00
typedef enum {
BINOP_UNKNOWN,
BINOP_POWER=100, BINOP_MULT, BINOP_DIVIDE, BINOP_MOD, BINOP_MOD1, BINOP_PLUS,
2024-11-03 12:48:13 -08:00
BINOP_MINUS, BINOP_CONCAT, BINOP_LSHIFT, BINOP_ULSHIFT, BINOP_RSHIFT, BINOP_URSHIFT, BINOP_MIN,
2024-02-04 12:23:59 -08:00
BINOP_MAX, BINOP_EQ, BINOP_NE, BINOP_LT, BINOP_LE, BINOP_GT, BINOP_GE,
BINOP_CMP,
2024-02-04 12:23:59 -08:00
BINOP_AND, BINOP_OR, BINOP_XOR,
} binop_e;
extern const char *binop_method_names[BINOP_XOR+1];
2024-02-04 12:23:59 -08:00
typedef enum {
2024-02-05 10:22:30 -08:00
UnknownTypeAST,
VarTypeAST,
PointerTypeAST,
ArrayTypeAST,
2024-08-10 12:15:38 -07:00
SetTypeAST,
2024-02-05 10:22:30 -08:00
TableTypeAST,
FunctionTypeAST,
2024-09-10 22:31:31 -07:00
OptionalTypeAST,
MutexedTypeAST,
2024-02-04 12:23:59 -08:00
} type_ast_e;
2024-02-07 21:52:18 -08:00
typedef struct tag_ast_s {
2024-02-04 12:23:59 -08:00
const char *name;
2024-02-07 21:52:18 -08:00
arg_ast_t *fields;
2024-02-24 12:24:44 -08:00
bool secret:1;
2024-02-07 21:52:18 -08:00
struct tag_ast_s *next;
} tag_ast_t;
2024-02-04 12:23:59 -08:00
struct type_ast_s {
type_ast_e tag;
2024-02-11 16:06:42 -08:00
file_t *file;
2024-02-04 12:23:59 -08:00
const char *start, *end;
union {
2024-02-05 10:22:30 -08:00
struct {} UnknownTypeAST;
2024-02-04 12:23:59 -08:00
struct {
2024-02-07 21:52:18 -08:00
const char *name;
2024-02-05 10:22:30 -08:00
} VarTypeAST;
2024-02-04 12:23:59 -08:00
struct {
type_ast_t *pointed;
bool is_stack:1;
2024-02-05 10:22:30 -08:00
} PointerTypeAST;
2024-02-04 12:23:59 -08:00
struct {
type_ast_t *item;
} ArrayTypeAST;
2024-02-04 12:23:59 -08:00
struct {
type_ast_t *key, *value;
ast_t *default_value;
2024-02-05 10:22:30 -08:00
} TableTypeAST;
2024-08-10 12:15:38 -07:00
struct {
type_ast_t *item;
} SetTypeAST;
2024-02-04 12:23:59 -08:00
struct {
2024-02-07 21:52:18 -08:00
arg_ast_t *args;
2024-02-04 12:23:59 -08:00
type_ast_t *ret;
2024-02-05 10:22:30 -08:00
} FunctionTypeAST;
2024-09-10 22:31:31 -07:00
struct {
type_ast_t *type;
} OptionalTypeAST, MutexedTypeAST;
2024-02-04 12:23:59 -08:00
} __data;
};
typedef enum {
Unknown = 0,
None, Bool, Var,
2024-02-11 21:41:49 -08:00
Int, Num,
2024-07-04 13:23:05 -07:00
TextLiteral, TextJoin, PrintStatement,
Path,
2024-02-04 12:23:59 -08:00
Declare, Assign,
2024-02-17 13:56:19 -08:00
BinaryOp, UpdateAssign,
Not, Negative, HeapAllocate, StackReference, Mutexed, Holding,
2024-02-04 12:23:59 -08:00
Min, Max,
Array, Set, Table, TableEntry, Comprehension,
FunctionDef, Lambda, ConvertDef,
2024-02-29 10:49:24 -08:00
FunctionCall, MethodCall,
2024-02-04 12:23:59 -08:00
Block,
2024-11-03 09:20:53 -08:00
For, While, If, When, Repeat,
2024-02-04 12:23:59 -08:00
Reduction,
Skip, Stop, Pass,
2024-07-04 15:00:01 -07:00
Defer,
2024-02-04 12:23:59 -08:00
Return,
Extern,
2024-05-12 17:13:19 -07:00
StructDef, EnumDef, LangDef,
2024-09-11 21:13:53 -07:00
Index, FieldAccess, Optional, NonOptional,
2024-11-17 11:49:03 -08:00
Moment,
2024-02-04 12:23:59 -08:00
DocTest,
Use,
2024-02-25 13:02:36 -08:00
InlineCCode,
2025-02-07 17:25:48 -08:00
Deserialize,
2024-02-04 12:23:59 -08:00
} ast_e;
struct ast_s {
ast_e tag;
2024-02-11 16:06:42 -08:00
file_t *file;
2024-02-04 12:23:59 -08:00
const char *start, *end;
union {
struct {} Unknown;
struct {
type_ast_t *type;
} None;
2024-02-04 12:23:59 -08:00
struct {
bool b;
} Bool;
struct {
2024-02-07 21:52:18 -08:00
const char *name;
2024-02-04 12:23:59 -08:00
} Var;
struct {
const char *str;
2024-02-04 12:23:59 -08:00
} Int;
struct {
double n;
} Num;
struct {
2024-02-11 12:31:30 -08:00
CORD cord;
2024-03-03 15:15:45 -08:00
} TextLiteral;
2024-02-04 12:23:59 -08:00
struct {
2024-03-09 15:22:12 -08:00
const char *lang;
2024-02-04 12:23:59 -08:00
ast_list_t *children;
2024-03-03 15:15:45 -08:00
} TextJoin;
struct {
const char *path;
} Path;
2024-07-04 13:23:05 -07:00
struct {
ast_list_t *to_print;
} PrintStatement;
2024-02-04 12:23:59 -08:00
struct {
ast_t *var;
ast_t *value;
} Declare;
struct {
ast_list_t *targets, *values;
} Assign;
struct {
ast_t *lhs;
binop_e op;
ast_t *rhs;
} BinaryOp, UpdateAssign;
struct {
ast_t *value;
} Not, Negative, HeapAllocate, StackReference, Mutexed;
struct {
ast_t *mutexed, *body;
} Holding;
2024-02-04 12:23:59 -08:00
struct {
ast_t *lhs, *rhs, *key;
} Min, Max;
struct {
2024-08-11 11:47:34 -07:00
type_ast_t *item_type;
2024-02-04 12:23:59 -08:00
ast_list_t *items;
} Array;
struct {
2024-08-10 12:15:38 -07:00
type_ast_t *item_type;
ast_list_t *items;
} Set;
struct {
2024-02-04 12:23:59 -08:00
type_ast_t *key_type, *value_type;
ast_t *default_value;
ast_t *fallback;
2024-02-04 12:23:59 -08:00
ast_list_t *entries;
} Table;
struct {
ast_t *key, *value;
} TableEntry;
struct {
2024-07-13 14:17:58 -07:00
ast_list_t *vars;
ast_t *expr, *iter, *filter;
} Comprehension;
2024-02-04 12:23:59 -08:00
struct {
ast_t *name;
2024-02-07 21:52:18 -08:00
arg_ast_t *args;
2024-02-04 12:23:59 -08:00
type_ast_t *ret_type;
ast_t *body;
ast_t *cache;
bool is_inline;
2024-02-04 12:23:59 -08:00
} FunctionDef;
struct {
arg_ast_t *args;
type_ast_t *ret_type;
ast_t *body;
ast_t *cache;
bool is_inline;
} ConvertDef;
2024-02-04 12:23:59 -08:00
struct {
2024-02-07 21:52:18 -08:00
arg_ast_t *args;
type_ast_t *ret_type;
2024-02-04 12:23:59 -08:00
ast_t *body;
int64_t id;
2024-02-04 12:23:59 -08:00
} Lambda;
struct {
ast_t *fn;
2024-02-23 09:50:01 -08:00
arg_ast_t *args;
2024-02-04 12:23:59 -08:00
} FunctionCall;
2024-02-29 10:49:24 -08:00
struct {
const char *name;
ast_t *self;
arg_ast_t *args;
} MethodCall;
2024-02-04 12:23:59 -08:00
struct {
ast_list_t *statements;
} Block;
struct {
2024-07-13 14:17:58 -07:00
ast_list_t *vars;
ast_t *iter, *body, *empty;
2024-02-04 12:23:59 -08:00
} For;
struct {
ast_t *condition, *body;
} While;
2024-11-03 09:20:53 -08:00
struct {
ast_t *body;
} Repeat;
2024-02-04 12:23:59 -08:00
struct {
ast_t *condition, *body, *else_body;
} If;
struct {
ast_t *subject;
when_clause_t *clauses;
ast_t *else_body;
} When;
2024-02-04 12:23:59 -08:00
struct {
ast_t *iter, *key;
binop_e op;
2024-02-04 12:23:59 -08:00
} Reduction;
struct {
const char *target;
} Skip, Stop;
struct {} Pass;
2024-07-04 15:00:01 -07:00
struct {
ast_t *body;
} Defer;
2024-02-04 12:23:59 -08:00
struct {
ast_t *value;
} Return;
struct {
const char *name;
type_ast_t *type;
} Extern;
struct {
2024-02-07 21:52:18 -08:00
const char *name;
arg_ast_t *fields;
ast_t *namespace;
2025-03-16 10:35:58 -07:00
bool secret:1, external:1, opaque:1;
2024-02-07 21:52:18 -08:00
} StructDef;
struct {
const char *name;
tag_ast_t *tags;
2024-02-04 12:23:59 -08:00
ast_t *namespace;
2024-02-07 21:52:18 -08:00
} EnumDef;
2024-03-09 15:22:12 -08:00
struct {
const char *name;
ast_t *namespace;
} LangDef;
2024-02-04 12:23:59 -08:00
struct {
ast_t *indexed, *index;
bool unchecked;
} Index;
struct {
ast_t *fielded;
const char *field;
} FieldAccess;
2024-04-30 10:18:47 -07:00
struct {
ast_t *value;
2024-09-11 21:13:53 -07:00
} Optional, NonOptional;
2024-09-30 10:55:55 -07:00
struct {
2024-11-17 11:49:03 -08:00
Moment_t moment;
} Moment;
2024-02-04 12:23:59 -08:00
struct {
ast_t *expr;
const char *output;
bool skip_source:1;
} DocTest;
struct {
ast_t *var;
const char *path;
enum { USE_LOCAL, USE_MODULE, USE_SHARED_OBJECT, USE_HEADER, USE_C_CODE, USE_ASM } what;
2024-02-04 12:23:59 -08:00
} Use;
2024-02-25 13:02:36 -08:00
struct {
CORD code;
struct type_s *type;
type_ast_t *type_ast;
2024-02-25 13:02:36 -08:00
} InlineCCode;
2024-11-29 15:09:12 -08:00
struct {
ast_t *value;
type_ast_t *type;
} Deserialize;
2024-02-04 12:23:59 -08:00
} __data;
};
CORD ast_to_xml(ast_t *ast);
CORD type_ast_to_xml(type_ast_t *ast);
2024-02-04 12:23:59 -08:00
int printf_ast(FILE *stream, const struct printf_info *info, const void *const args[]);
PUREFUNC bool is_idempotent(ast_t *ast);
void visit_topologically(ast_list_t *ast, Closure_t fn);
2024-02-04 12:23:59 -08:00
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0