Initial working version
This commit is contained in:
parent
711afee405
commit
13a9304dec
2
Makefile
2
Makefile
@ -30,7 +30,7 @@ CFLAGS_PLACEHOLDER="$$(echo -e '\033[2m<flags...>\033[m')"
|
||||
LDLIBS=-lgc -lcord -lm -lunistring -lgmp -ldl
|
||||
BUILTIN_OBJS=builtins/siphash.o builtins/array.o builtins/bool.o builtins/channel.o builtins/nums.o builtins/functions.o builtins/integers.o \
|
||||
builtins/pointer.o builtins/memory.o builtins/text.o builtins/thread.o builtins/c_string.o builtins/table.o \
|
||||
builtins/types.o builtins/util.o builtins/files.o builtins/range.o builtins/shell.o
|
||||
builtins/types.o builtins/util.o builtins/files.o builtins/range.o builtins/shell.o builtins/path.o
|
||||
TESTS=$(patsubst %.tm,%.tm.testresult,$(wildcard test/*.tm))
|
||||
|
||||
all: libtomo.so tomo
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Boolean methods/type info
|
||||
// A lang for Shell Command Language
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
#include "types.h"
|
||||
#include "util.h"
|
||||
|
||||
public Pattern_t Shell$escape_text(Text_t text)
|
||||
public Shell_t Shell$escape_text(Text_t text)
|
||||
{
|
||||
// TODO: optimize for ASCII and short strings
|
||||
Array_t shell_graphemes = {.atomic=1};
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "macros.h"
|
||||
#include "memory.h"
|
||||
#include "nums.h"
|
||||
#include "path.h"
|
||||
#include "pointer.h"
|
||||
#include "range.h"
|
||||
#include "shell.h"
|
||||
|
@ -3041,6 +3041,8 @@ CORD compile_type_info(env_t *env, type_t *t)
|
||||
return "&Pattern$info";
|
||||
else if (streq(text->lang, "Shell"))
|
||||
return "&Shell$info";
|
||||
else if (streq(text->lang, "Path"))
|
||||
return "&Path$info";
|
||||
return CORD_all("(&", namespace_prefix(text->env->libname, text->env->namespace->parent), text->lang, ")");
|
||||
}
|
||||
case StructType: {
|
||||
|
@ -248,6 +248,11 @@ env_t *new_compilation_unit(CORD *libname)
|
||||
{"Pattern", Type(TextType, .lang="Pattern", .env=namespace_env(env, "Pattern")), "Pattern_t", "Pattern$info", TypedArray(ns_entry_t,
|
||||
{"escape_text", "Pattern$escape_text", "func(text:Text)->Pattern"},
|
||||
)},
|
||||
{"Path", Type(TextType, .lang="Path", .env=namespace_env(env, "Path")), "Text_t", "Text$info", TypedArray(ns_entry_t,
|
||||
{"escape_text", "Path$escape_text", "func(text:Text)->Path"},
|
||||
{"resolved", "Path$resolved", "func(path:Path, relative_to=./)->Path"},
|
||||
{"relative", "Path$relative", "func(path:Path, relative_to=./)->Path"},
|
||||
)},
|
||||
{"Shell", Type(TextType, .lang="Shell", .env=namespace_env(env, "Shell")), "Shell_t", "Shell$info", TypedArray(ns_entry_t,
|
||||
{"escape_text", "Shell$escape_text", "func(text:Text)->Shell"},
|
||||
{"run", "Shell$run", "func(command:Shell, status=!&Int32?)->Text"},
|
||||
|
115
parse.c
115
parse.c
@ -84,37 +84,37 @@ static ast_t *parse_comprehension_suffix(parse_ctx_t *ctx, ast_t *lhs);
|
||||
static ast_t *parse_optional_conditional_suffix(parse_ctx_t *ctx, ast_t *lhs);
|
||||
static ast_t *parse_optional_suffix(parse_ctx_t *ctx, ast_t *lhs);
|
||||
static arg_ast_t *parse_args(parse_ctx_t *ctx, const char **pos, bool allow_unnamed);
|
||||
static type_ast_t *parse_type(parse_ctx_t *ctx, const char *pos);
|
||||
static PARSER(parse_array);
|
||||
static PARSER(parse_block);
|
||||
static PARSER(parse_channel);
|
||||
static PARSER(parse_for);
|
||||
static PARSER(parse_declaration);
|
||||
static PARSER(parse_do);
|
||||
static PARSER(parse_while);
|
||||
static PARSER(parse_if);
|
||||
static PARSER(parse_when);
|
||||
static PARSER(parse_doctest);
|
||||
static PARSER(parse_enum_def);
|
||||
static PARSER(parse_expr);
|
||||
static PARSER(parse_extended_expr);
|
||||
static PARSER(parse_term_no_suffix);
|
||||
static PARSER(parse_term);
|
||||
static PARSER(parse_statement);
|
||||
static PARSER(parse_block);
|
||||
static PARSER(parse_var);
|
||||
static PARSER(parse_enum_def);
|
||||
static PARSER(parse_struct_def);
|
||||
static PARSER(parse_lang_def);
|
||||
static PARSER(parse_text);
|
||||
static PARSER(parse_func_def);
|
||||
static PARSER(parse_extern);
|
||||
static PARSER(parse_file_body);
|
||||
static PARSER(parse_for);
|
||||
static PARSER(parse_func_def);
|
||||
static PARSER(parse_if);
|
||||
static PARSER(parse_inline_c);
|
||||
static PARSER(parse_declaration);
|
||||
static PARSER(parse_top_declaration);
|
||||
static PARSER(parse_doctest);
|
||||
static PARSER(parse_say);
|
||||
static PARSER(parse_use);
|
||||
static PARSER(parse_lang_def);
|
||||
static PARSER(parse_linker);
|
||||
static PARSER(parse_namespace);
|
||||
static PARSER(parse_file_body);
|
||||
|
||||
static type_ast_t *parse_type(parse_ctx_t *ctx, const char *pos);
|
||||
static PARSER(parse_path);
|
||||
static PARSER(parse_say);
|
||||
static PARSER(parse_statement);
|
||||
static PARSER(parse_struct_def);
|
||||
static PARSER(parse_term);
|
||||
static PARSER(parse_term_no_suffix);
|
||||
static PARSER(parse_text);
|
||||
static PARSER(parse_top_declaration);
|
||||
static PARSER(parse_use);
|
||||
static PARSER(parse_var);
|
||||
static PARSER(parse_when);
|
||||
static PARSER(parse_while);
|
||||
|
||||
//
|
||||
// Print a parse error and exit (or use the on_err longjmp)
|
||||
@ -630,6 +630,7 @@ PARSER(parse_num) {
|
||||
const char *start = pos;
|
||||
bool negative = match(&pos, "-");
|
||||
if (!isdigit(*pos) && *pos != '.') return NULL;
|
||||
else if (*pos == '.' && !isdigit(pos[1])) return NULL;
|
||||
|
||||
size_t len = strspn(pos, "0123456789_");
|
||||
if (strncmp(pos+len, "..", 2) == 0)
|
||||
@ -1295,6 +1296,75 @@ PARSER(parse_text) {
|
||||
return NewAST(ctx->file, start, pos, TextJoin, .lang=lang, .children=chunks);
|
||||
}
|
||||
|
||||
PARSER(parse_path) {
|
||||
// ("~/" / "./" / "../" / "/") *([^ \t\r\n\\;] / "\" .)
|
||||
const char *start = pos;
|
||||
|
||||
if (!(match(&pos, "~/")
|
||||
|| match(&pos, "./")
|
||||
|| match(&pos, "../")
|
||||
|| match(&pos, "/")))
|
||||
return NULL;
|
||||
|
||||
const char *chunk_start = start;
|
||||
ast_list_t *chunks = NULL;
|
||||
CORD chunk_text = CORD_EMPTY;
|
||||
int depths[] = {[(int)'('] = 0, [(int)'{'] = 0, [(int)'['] = 0};
|
||||
while (pos < ctx->file->text + ctx->file->len) {
|
||||
switch (*pos) {
|
||||
case '\r': case '\n': case ';': case ':': goto end_of_path;
|
||||
case '\\': {
|
||||
++pos;
|
||||
chunk_text = CORD_asprintf("%r%.*s%c", chunk_text, (size_t)(pos - chunk_start), chunk_start, *pos);
|
||||
++pos;
|
||||
continue;
|
||||
}
|
||||
case '$': {
|
||||
const char *interp_start = pos;
|
||||
if (chunk_text) {
|
||||
ast_t *literal = NewAST(ctx->file, chunk_start, pos, TextLiteral, .cord=chunk_text);
|
||||
chunks = new(ast_list_t, .ast=literal, .next=chunks);
|
||||
chunk_text = CORD_EMPTY;
|
||||
}
|
||||
++pos;
|
||||
if (*pos == ' ' || *pos == '\t')
|
||||
parser_err(ctx, pos, pos+1, "Whitespace is not allowed before an interpolation here");
|
||||
ast_t *interp = expect(ctx, interp_start, &pos, parse_term_no_suffix, "I expected an interpolation term here");
|
||||
chunks = new(ast_list_t, .ast=interp, .next=chunks);
|
||||
chunk_start = pos;
|
||||
continue;
|
||||
}
|
||||
case ')': case '}': case ']': {
|
||||
if (depths[(int)*pos] <= 0)
|
||||
goto end_of_path;
|
||||
depths[(int)*pos] -= 1;
|
||||
++pos;
|
||||
continue;
|
||||
}
|
||||
case '(': case '{': case '[': {
|
||||
depths[(int)*pos] += 1;
|
||||
++pos;
|
||||
continue;
|
||||
}
|
||||
default: ++pos; continue;
|
||||
}
|
||||
}
|
||||
end_of_path:;
|
||||
|
||||
if (pos > chunk_start)
|
||||
chunk_text = CORD_asprintf("%r%.*s", chunk_text, (size_t)(pos - chunk_start), chunk_start);
|
||||
|
||||
if (chunk_text != CORD_EMPTY) {
|
||||
ast_t *literal = NewAST(ctx->file, chunk_start, pos, TextLiteral, .cord=chunk_text);
|
||||
chunks = new(ast_list_t, .ast=literal, .next=chunks);
|
||||
}
|
||||
|
||||
match(&pos, ";"); // optional trailing semicolon
|
||||
|
||||
REVERSE_LIST(chunks);
|
||||
return NewAST(ctx->file, start, pos, TextJoin, .lang="Path", .children=chunks);
|
||||
}
|
||||
|
||||
PARSER(parse_pass) {
|
||||
const char *start = pos;
|
||||
return match_word(&pos, "pass") ? NewAST(ctx->file, start, pos, Pass) : NULL;
|
||||
@ -1382,6 +1452,7 @@ PARSER(parse_term_no_suffix) {
|
||||
|| (term=parse_stack_reference(ctx, pos))
|
||||
|| (term=parse_bool(ctx, pos))
|
||||
|| (term=parse_text(ctx, pos))
|
||||
|| (term=parse_path(ctx, pos))
|
||||
|| (term=parse_lambda(ctx, pos))
|
||||
|| (term=parse_parens(ctx, pos))
|
||||
|| (term=parse_table(ctx, pos))
|
||||
|
Loading…
Reference in New Issue
Block a user