commit ae90623b362dda650c5c058d588d360121a18d79
parent 6d1a49b04ea41ea43874114884012860d8ee72ea
Author: citbl <citbl@citbl.org>
Date: Sat, 23 May 2026 17:14:38 +1000
wip
Diffstat:
11 files changed, 168 insertions(+), 5 deletions(-)
diff --git a/mtcc/src/errors.c b/mtcc/src/errors.c
@@ -0,0 +1,9 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "errors.h"
+
+void
+panic(const char *msg) {
+ fprintf(stderr, "%s\n", msg);
+ exit(1);
+}
diff --git a/mtcc/src/errors.h b/mtcc/src/errors.h
@@ -0,0 +1,3 @@
+#pragma once
+
+void panic(const char *msg);
diff --git a/mtcc/src/main.c b/mtcc/src/main.c
@@ -11,7 +11,6 @@ main(int argc, char **argv) {
file_t file;
struct lexer lexer;
struct parser parser;
-
if (argc < 2) {
const char *cmp = argv[0];
printf("usage: %s <filename.mty>\n", cmp);
diff --git a/mtcc/src/parser.c b/mtcc/src/parser.c
@@ -1,5 +1,56 @@
+#include <stdio.h>
+#include <stdlib.h>
#include "parser.h"
+#include "errors.h"
+
+void add_error(struct parser *p, const char *message);
+struct token peek(struct parser *p);
+struct token consume(struct parser *p);
+bool check(struct parser *p, enum token_type type);
+
+void
+parser_parse(struct parser *p) {
+ // from [x y z] [node
+ // decl / etc.
+ // nodes
+
+ while (p->pos < p->lexer->tok_len) {
+ struct token tok = consume(p);
+ switch (tok.token_type) {
+ case TOKEN_IDENT:
+ struct token type = tok;
+ if (!check(p, TOKEN_IDENT))
+ panic("expected open paren ( after label in function declaration");
+ break;
+ default:
+ panic("error parsing top level");
+ }
+ }
+}
+
+struct token
+peek(struct parser *p) {
+ if (p->pos >= p->lexer->tok_len)
+ panic("token peek out of bounds?");
+ return p->lexer->tokens[p->pos + 1];
+}
+
+struct token
+consume(struct parser *p) {
+ struct token tok = p->lexer->tokens[p->pos++];
+ if (tok.token_type == 0) panic("consume bad token EOF?");
+ return tok;
+}
+
+bool
+check(struct parser *p, enum token_type type) {
+ return (peek(p).token_type == type);
+}
void
-parser_parse(struct parser *parser) {
+add_error(struct parser *p, const char *message) {
+ const char *filename = p->lexer->tokens[p->pos].span.filename;
+ size_t line = p->lexer->tokens[p->pos].span.line;
+ size_t col = p->lexer->tokens[p->pos].span.col;
+ fprintf(stderr, "%s: L%zu:%zu : %s", filename, line, col, message);
}
diff --git a/mtcc/src/token.h b/mtcc/src/token.h
@@ -28,8 +28,8 @@ enum token_type {
TOKEN_COLON,
TOKEN_COLON_COLON,
TOKEN_COMMA,
- TOKEN_EOF,
TOKEN_EQ,
+ TOKEN_EOF,
TOKEN_LITERAL_BOOL,
TOKEN_LITERAL_INT,
TOKEN_LITERAL_FLOAT,
diff --git a/mtcc/src/types.h b/mtcc/src/types.h
@@ -48,6 +48,8 @@ struct node {
struct parser {
struct lexer *lexer;
struct node **nodes;
- size_t nodes_len;
- size_t nodes_cap;
+ size_t nodes_len, nodes_cap;
+ size_t pos;
+ size_t err_len, err_cap;
+ char *errors;
};
diff --git a/mtcl/.gitignore b/mtcl/.gitignore
@@ -0,0 +1,2 @@
+.DS_Store
+*.lua~
diff --git a/mtcl/main.lua b/mtcl/main.lua
@@ -0,0 +1,40 @@
+-- comp
+
+local file = io.open(arg[1], "rb")
+local contents = file:read("*all")
+
+function skip() end
+function read_ident(start, c, str)
+ local a = string.byte("a")
+ local z = string.byte("z")
+ local A = string.byte("A")
+ local Z = string.byte("Z")
+ local zero = string.byte("0")
+ local nine = string.byte("9")
+ for i = start, #str do
+ local c = src:sub(i,i)
+ end
+end
+
+function lex(src)
+ local i = 1
+ local whitespacers = {
+ ["\t"] = skip,
+ ["\r"] = skip,
+ ["\n"] = skip,
+ [" "] = skip,
+ }
+
+ for i = 1, #src do
+ local c = src:sub(i, i)
+ local char_fx = whitespacers[c]
+
+ if char_fx then
+ char_fx()
+ else
+ print(c)
+ end
+ end
+end
+
+lex(contents)
diff --git a/mtcl/makefile b/mtcl/makefile
@@ -0,0 +1,2 @@
+default:
+ lua main.lua target.mty
diff --git a/mtcl/target.mty b/mtcl/target.mty
@@ -0,0 +1,6 @@
+use std
+
+fx main :: int =
+ print("hello")
+ ret 0
+
diff --git a/test.mty b/test.mty
@@ -0,0 +1,49 @@
+fn is_alpha :: (>= 'a' && <= 'z') || (>= 'A' && <= 'z')
+
+fx main ::
+ with []Token tokens
+ with contents = read_file filename | split
+ @ match
+ '+' => tokens += (Token){.type = PLUS}
+ '-' => tokens += (Token){.type = MINUS}
+ is_alpha => tokens += parse @+
+ ??? => throw("unknown token")
+
+fx main :: print "hello" // "hello"
+
+fx main :: with "hello" print // hello
+
+fx main :: with "hello" | split @ print // [h e l l o]
+
+fx sub :: T1 - T2
+
+fx main :: print "hello, world!"
+
+
+fx add :: int, int -> int = A + B
+fx sub :: int, int -> int = A - B
+fx err :: str =
+ fprintf(std.err, str)
+ exit 1
+
+// terse, readable, reliable, enjoyable
+
+use lexer
+
+fx main :: int =
+ filename := std.args[1]
+ contents := std.read_file(filename)
+ tokens := lexer.lex(contents)
+ print_tokens(tokens)
+
+ns lexer
+
+fx lex :: str contents =
+ @[contents]
+ | ignore_whitespace
+ | parse_idents
+ | parse_chars
+
+fn parse_idents :: char x =
+ static str word = ""
+