Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified bin/Splice
Binary file not shown.
Binary file modified bin/spbuild
Binary file not shown.
6 changes: 3 additions & 3 deletions build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,16 @@ echo "Proceeding with build on $OS/$ARCH..."
echo "Building Splice runtime and native module..."

# Compile Splice runtime (with SDK globals)
gcc -DSDK_IMPLEMENTATION -Isrc -Wall -Wextra -c -DNDEBUG -O3 -flto src/splice.c -o "$BIN_DIR/Splice.o"
gcc -DSDK_IMPLEMENTATION -Isrc -Wall -Wextra -c -Ofast -march=native -mtune=native -flto -fomit-frame-pointer -funroll-loops -fno-semantic-interposition -fno-math-errno -fno-trapping-math -fstrict-aliasing -DNDEBUG src/splice.c -o "$BIN_DIR/Splice.o"

# Compile native module without SDK_IMPLEMENTATION
gcc -Isrc -Wall -Wextra -c -DNDEBUG -O3 -flto src/module_stubs.c -o "$BIN_DIR/module_stubs.o"
gcc -Isrc -Wall -Wextra -c -Ofast -march=native -mtune=native -flto -fomit-frame-pointer -funroll-loops -fno-semantic-interposition -fno-math-errno -fno-trapping-math -fstrict-aliasing -DNDEBUG src/module_stubs.c -o "$BIN_DIR/module_stubs.o"

# Link executable (local binary: Splice)
gcc "$BIN_DIR/Splice.o" "$BIN_DIR/module_stubs.o" -o "$BIN_DIR/Splice"

echo "Building spbuild (bytecode compiler)..."
gcc -Isrc -Wall -Wextra -DNDEBUG -O3 -flto src/build.c -o "$BIN_DIR/spbuild"
gcc -Isrc -Wall -Wextra -Ofast -march=native -mtune=native -flto -fomit-frame-pointer -funroll-loops -fno-semantic-interposition -fno-math-errno -fno-trapping-math -fstrict-aliasing -DNDEBUG src/build.c -o "$BIN_DIR/spbuild"

# --- Install section ---
INSTALL_DIR=""
Expand Down
Binary file added recurse
Binary file not shown.
13 changes: 13 additions & 0 deletions recurse.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "ctype.h"

void recurse(int a) {
printf("%d\n", a);
recurse(a + 1);
}
int main() {
recurse(1);
return 0;
}
Binary file added recurse.spc
Binary file not shown.
5 changes: 5 additions & 0 deletions recurse.spl
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
func hi(a) {
print(a);
hi(a + 1);
}
hi(1);
98 changes: 48 additions & 50 deletions src/build.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ static void tv_push(TokVec *v, Tok x) {
if (v->count >= v->cap) {
v->cap = v->cap ? v->cap*2 : 256;
Tok *nd = (Tok*)realloc(v->data, sizeof(Tok) * (size_t)v->cap);
if (!nd) error(0, "oom realloc tokens");
if (!nd) error(0, "Splice/SystemError oom realloc tokens");
v->data = nd;
}
v->data[v->count++] = x;
Expand Down Expand Up @@ -140,7 +140,7 @@ static void tokenize(const char *src, TokVec *out) {
while (*p && *p!='"') p++;
size_t n = (size_t)(p - s);
char *str = (char*)malloc(n+1);
if (!str) error(line, "oom string");
if (!str) error(line, "Splice/SystemErroroom string");
memcpy(str, s, n);
str[n]=0;
Tok t = { .t=TK_STRING, .lex=str, .line=line };
Expand All @@ -155,7 +155,7 @@ static void tokenize(const char *src, TokVec *out) {
while (isdigit((unsigned char)*p) || *p=='.') p++;
char tmp[128];
size_t n = (size_t)(p - s);
if (n >= sizeof(tmp)) error(line, "number too long");
if (n >= sizeof(tmp)) error(line, "Splice/OverflowError number too long");
memcpy(tmp, s, n);
tmp[n]=0;
Tok t = { .t=TK_NUMBER, .num=strtod(tmp,NULL), .line=line };
Expand All @@ -169,7 +169,7 @@ static void tokenize(const char *src, TokVec *out) {
while (isalnum((unsigned char)*p) || *p=='_') p++;
size_t n = (size_t)(p - s);
char *id = (char*)malloc(n+1);
if (!id) error(line, "oom ident");
if (!id) error(line, "Splice/SystemErroroom ident");
memcpy(id, s, n);
id[n]=0;

Expand Down Expand Up @@ -228,7 +228,7 @@ static void tokenize(const char *src, TokVec *out) {
case '>': tv_push(out,(Tok){.t=TK_GT,.line=line}); p++; break;

default:
error(line, "Unknown char: '%c'", *p);
error(line, "Splice/SyntaxError Unknown char: '%c'", *p);
}
}

Expand Down Expand Up @@ -284,7 +284,7 @@ static ASTNode *parse_primary(void) {
if (!match(TK_COMMA)) break;
}
}
consume(TK_RPAREN, "Expected ')' after call args");
consume(TK_RPAREN, "Splice/SyntaxError Expected ')' after call args");

ASTNode *c = ast_new(AST_FUNCTION_CALL);
c->funccall.funcname = name;
Expand All @@ -296,7 +296,7 @@ static ASTNode *parse_primary(void) {
/* ident[index] */
if (match(TK_LBRACKET)) {
ASTNode *idx = parse_expression();
consume(TK_RBRACKET, "Expected ']' after index");
consume(TK_RBRACKET, "Splice/SyntaxError Expected ']' after index");

ASTNode *id = ast_new(AST_IDENTIFIER);
id->string = name;
Expand Down Expand Up @@ -333,7 +333,7 @@ static ASTNode *parse_primary(void) {
items[count++] = parse_expression();
} while (match(TK_COMMA));

consume(TK_RPAREN, "Expected ')' after tuple");
consume(TK_RPAREN, "Splice/SyntaxError Expected ')' after tuple");

ASTNode *t = ast_new(AST_TUPLE);
t->tuple.items = items;
Expand All @@ -342,23 +342,23 @@ static ASTNode *parse_primary(void) {
}

/* otherwise normal grouping */
consume(TK_RPAREN, "Expected ')'");
consume(TK_RPAREN, "Splice/SyntaxError Expected ')'");
return first;
}

if (match(TK_READ)) {
consume(TK_LPAREN, "Expected '(' after read");
consume(TK_LPAREN, "Splice/SyntaxError Expected '(' after read");
ASTNode *e = parse_expression();
consume(TK_RPAREN, "Expected ')' after read");
consume(TK_RPAREN, "Splice/SyntaxError Expected ')' after read");

ASTNode *n = ast_new(AST_READ);
n->read.expr = e;
return n;
}
if (match(TK_INPUT)) {
consume(TK_LPAREN, "Expected '(' after input");
consume(TK_LPAREN, "Splice/SyntaxError Expected '(' after input");
ASTNode *e = parse_expression();
consume(TK_RPAREN, "Expected ')' after input prompt");
consume(TK_RPAREN, "Splice/SyntaxError Expected ')' after input prompt");
ASTNode *n = ast_new(AST_INPUT);
n->input.prompt = e;
return n;
Expand All @@ -375,15 +375,15 @@ static ASTNode *parse_primary(void) {
if (!match(TK_COMMA)) break;
}
}
consume(TK_RBRACKET, "Expected ']' after array literal");
consume(TK_RBRACKET, "Splice/SyntaxError Expected ']' after array literal");

ASTNode *a = ast_new(AST_ARRAY_LITERAL);
a->arraylit.elements = els;
a->arraylit.count = ec;
return a;
}

error(peek()->line, "Expected expression");
error(peek()->line, "Splice/SyntaxError Expected expression");
return NULL;
}

Expand Down Expand Up @@ -486,8 +486,8 @@ static ASTNode *parse_statements_until(TokType end) {

static ASTNode *parse_statement(void) {
if (match(TK_LET)) {
Tok *id = consume(TK_IDENT, "Expected identifier after let");
consume(TK_ASSIGN, "Expected '=' after let name");
Tok *id = consume(TK_IDENT, "Splice/SyntaxError Expected identifier after let");
consume(TK_ASSIGN, "Splice/SyntaxError Expected '=' after let name");
ASTNode *rhs = parse_expression();

ASTNode *n = ast_new(AST_LET);
Expand All @@ -497,15 +497,15 @@ static ASTNode *parse_statement(void) {
}

if (match(TK_PRINT)) {
consume(TK_LPAREN, "Expected '(' after print");
consume(TK_LPAREN, "Splice/SyntaxError Expected '(' after print");
ASTNode *e = parse_expression();
consume(TK_RPAREN, "Expected ')' after print expr");
consume(TK_RPAREN, "Splice/SyntaxError Expected ')' after print expr");
ASTNode *n = ast_new(AST_PRINT);
n->print.expr = e;
return n;
}
if (match(TK_IMPORT)) {
Tok *f = consume(TK_STRING, "Expected string filename after import");
Tok *f = consume(TK_STRING, "Splice/SyntaxError Expected string filename after import");

ASTNode *n = ast_new(AST_IMPORT);

Expand All @@ -517,22 +517,21 @@ static ASTNode *parse_statement(void) {
}

if (match(TK_WRITE)) {
consume(TK_LPAREN, "Expected '(' after write");
consume(TK_LPAREN, "Splice/SyntaxError Expected '(' after write");
ASTNode *path = parse_expression();
consume(TK_COMMA, "Expected ',' after write path");
consume(TK_COMMA, "Splice/SyntaxError Expected ',' after write path");
ASTNode *val = parse_expression();
consume(TK_RPAREN, "Expected ')' after write");

consume(TK_RPAREN, "Splice/SyntaxError Expected ')' after write");
ASTNode *n = ast_new(AST_WRITE);
n->write.path = path;
n->write.value = val;
return n;
}

if (match(TK_RAISE)) {
consume(TK_LPAREN, "Expected '(' after raise");
consume(TK_LPAREN, "Splice/SyntaxError Expected '(' after raise");
ASTNode *e = parse_expression();
consume(TK_RPAREN, "Expected ')' after raise expr");
consume(TK_RPAREN, "Splice/SyntaxError Expected ')' after raise expr");
ASTNode *n = ast_new(AST_RAISE);
n->raise.expr = e;
return n;
Expand All @@ -547,26 +546,25 @@ static ASTNode *parse_statement(void) {
}

if (match(TK_FUNC)) {
Tok *id = consume(TK_IDENT, "Expected function name");
consume(TK_LPAREN, "Expected '(' after func name");
Tok *id = consume(TK_IDENT, "Splice/SyntaxError Expected function name");
consume(TK_LPAREN, "Splice/SyntaxError Expected '(' after func name");

char **params=NULL;
int pc=0, cap=0;

if (!at(TK_RPAREN)) {
for (;;) {
Tok *p = consume(TK_IDENT, "Expected param name");
Tok *p = consume(TK_IDENT, "Splice/SyntaxError Expected param name");
if (pc>=cap) { cap=cap?cap*2:8; params=(char**)realloc(params,sizeof(char*)*(size_t)cap); }
params[pc++] = strdup(p->lex);
if (!match(TK_COMMA)) break;
}
}
consume(TK_RPAREN, "Expected ')' after params");
consume(TK_RPAREN, "Splice/SyntaxError Expected ')' after params");

consume(TK_LBRACE, "Expected '{' before func body");
consume(TK_LBRACE, "Splice/SyntaxError Expected '{' before func body");
ASTNode *body = parse_statements_until(TK_RBRACE);
consume(TK_RBRACE, "Expected '}' after func body");

consume(TK_RBRACE, "Splice/SyntaxError Expected '}' after func body");
ASTNode *n = ast_new(AST_FUNC_DEF);
n->funcdef.funcname = strdup(id->lex);
n->funcdef.params = params;
Expand All @@ -576,18 +574,18 @@ static ASTNode *parse_statement(void) {
}

if (match(TK_IF)) {
consume(TK_LPAREN, "Expected '(' after if");
consume(TK_LPAREN, "Splice/SyntaxError Expected '(' after if");
ASTNode *cond = parse_expression();
consume(TK_RPAREN, "Expected ')' after if cond");
consume(TK_LBRACE, "Expected '{' after if");
consume(TK_RPAREN, "Splice/SyntaxError Expected ')' after if cond");
consume(TK_LBRACE, "Splice/SyntaxError Expected '{' after if");
ASTNode *thenb = parse_statements_until(TK_RBRACE);
consume(TK_RBRACE, "Expected '}' after if body");
consume(TK_RBRACE, "Splice/SyntaxError Expected '}' after if body");

ASTNode *elseb = NULL;
if (match(TK_ELSE)) {
consume(TK_LBRACE, "Expected '{' after else");
consume(TK_LBRACE, "Splice/SyntaxError Expected '{' after else");
elseb = parse_statements_until(TK_RBRACE);
consume(TK_RBRACE, "Expected '}' after else body");
consume(TK_RBRACE, "Splice/SyntaxError Expected '}' after else body");
}

ASTNode *n = ast_new(AST_IF);
Expand All @@ -598,12 +596,12 @@ static ASTNode *parse_statement(void) {
}

if (match(TK_WHILE)) {
consume(TK_LPAREN, "Expected '(' after while");
consume(TK_LPAREN, "Splice/SyntaxError Expected '(' after while");
ASTNode *cond = parse_expression();
consume(TK_RPAREN, "Expected ')' after while cond");
consume(TK_LBRACE, "Expected '{' after while");
consume(TK_RPAREN, "Splice/SyntaxError Expected ')' after while cond");
consume(TK_LBRACE, "Splice/SyntaxError Expected '{' after while");
ASTNode *body = parse_statements_until(TK_RBRACE);
consume(TK_RBRACE, "Expected '}' after while body");
consume(TK_RBRACE, "Splice/SyntaxError Expected '}' after while body");

ASTNode *n = ast_new(AST_WHILE);
n->whilestmt.cond = cond;
Expand All @@ -612,14 +610,14 @@ static ASTNode *parse_statement(void) {
}

if (match(TK_FOR)) {
Tok *id = consume(TK_IDENT, "Expected for variable");
consume(TK_IN, "Expected 'in' after for var");
Tok *id = consume(TK_IDENT, "Splice/SyntaxError Expected for variable");
consume(TK_IN, "Splice/SyntaxError Expected 'in' after for var");
ASTNode *start = parse_expression();
consume(TK_DOT, "Expected '.' in for range");
consume(TK_DOT, "Splice/SyntaxError Expected '.' in for range");
ASTNode *end = parse_expression();
consume(TK_LBRACE, "Expected '{' after for range");
consume(TK_LBRACE, "Splice/SyntaxError Expected '{' after for range");
ASTNode *body = parse_statements_until(TK_RBRACE);
consume(TK_RBRACE, "Expected '}' after for body");
consume(TK_RBRACE, "Splice/SyntaxError Expected '}' after for body");

ASTNode *n = ast_new(AST_FOR);
n->forstmt.for_var = strdup(id->lex);
Expand All @@ -645,8 +643,8 @@ static ASTNode *parse_statement(void) {
/* ident[expr] = expr */
if (match(TK_LBRACKET)) {
ASTNode *idx = parse_expression();
consume(TK_RBRACKET, "Expected ']' after index");
consume(TK_ASSIGN, "Expected '=' after index");
consume(TK_RBRACKET, "Splice/SyntaxError Expected ']' after index");
consume(TK_ASSIGN, "Splice/SyntaxError Expected '=' after index");
ASTNode *rhs = parse_expression();

ASTNode *target = ast_new(AST_IDENTIFIER);
Expand Down
1 change: 0 additions & 1 deletion src/splice.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ int main(int argc, char **argv) {

ASTNode *root = read_ast_from_spc(arg);
info(0, "Loaded AST from %s", arg);

interpret(root);
free_ast(root);

Expand Down
Loading
Loading