throwing away a bunch of stuff, lets do the whole compiler inside the VM

This commit is contained in:
zongor 2025-07-08 21:59:56 -04:00
parent 9c94e4a6ef
commit fefc9e803a
15 changed files with 70 additions and 609 deletions

View File

@ -7,7 +7,7 @@
! Camera .
!!
type Camera {
init(pos [3]real, look [3]real) {
init(real[3] pos, real[3] look) {
this.setting = "CAMERA_PERSPECTIVE";
this.pov = 45.0;
this.up = [0.0, 1.0, 0.0];
@ -20,7 +20,7 @@ type Camera {
! Player .
!!
type Player {
init(username str, pos real[3], color Color) {
init(str username, real[3] pos, Color color) {
this.server = Client("tcp://localhost:25565");
this.username = username;
this.pos = pos;

View File

@ -2,7 +2,6 @@
#define ZRE_DEBUG_H
#include "vm.h"
#include "parser.h"
#include "opcodes.h"
int core_dump(VM *vm);

View File

@ -1,89 +0,0 @@
#ifndef HASHMAP_H
#define HASHMAP_H
#include <stdlib.h>
#include <string.h>
char *strdup(const char *s) {
size_t len = strlen(s) + 1;
char *copy = (char*)malloc(len);
if (copy) {
memcpy(copy, s, len);
}
return copy;
}
#define DEFINE_HASHMAP(StructType, HASHSIZE) \
unsigned int hash_##StructType(char *s) { \
unsigned int hashval; \
for (hashval = 0; *s != '\0'; s++) \
hashval = *s + 31 * hashval; \
return hashval % HASHSIZE; \
} \
\
StructType *get_##StructType(StructType **map, char *s) { \
StructType *np; \
for (np = map[hash_##StructType(s)]; np != NULL; np = np->next) \
if (strcmp(s, np->keyword) == 0) \
return np; \
return NULL; \
} \
\
StructType *put_##StructType(StructType **map, char *keyword, TokenType token) { \
StructType *np; \
unsigned int hashval; \
if ((np = get_##StructType(map, keyword)) == NULL) { \
np = (StructType *)malloc(sizeof(*np)); \
if (np == NULL || (np->keyword = strdup(keyword)) == NULL) \
return NULL; \
hashval = hash_##StructType(keyword); \
np->next = map[hashval]; \
map[hashval] = np; \
} \
np->token = token; \
return np; \
} \
\
int delete_##StructType(StructType **map, char *keyword) { \
unsigned int hashval = hash_##StructType(keyword); \
StructType *current = map[hashval]; \
StructType *prev = NULL; \
while (current) { \
if (strcmp(current->keyword, keyword) == 0) { \
if (prev) { \
prev->next = current->next; \
} else { \
map[hashval] = current->next; \
} \
free(current->keyword); \
free(current); \
return 1; \
} \
prev = current; \
current = current->next; \
} \
return 0; \
} \
\
StructType **new_##StructType() { \
StructType **map = (StructType **)calloc(HASHSIZE, sizeof(StructType *)); \
if (!map) return NULL; \
return map; \
} \
\
void free_##StructType(StructType **map) { \
if (!map) return; \
int i; \
for (i = 0; i < HASHSIZE; i++) { \
StructType *current = map[i]; \
while (current) { \
StructType *next = current->next; \
free(current->keyword); \
free(current); \
current = next; \
} \
} \
free(map); \
}
#endif

View File

@ -1,14 +1,10 @@
#include "compiler.h"
#include "test.h"
#include "debug.h"
#include "parser.h"
#include "vm.h"
#include <errno.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
@ -30,27 +26,6 @@ void mainloop() {
}
int main(int argc, char **argv) {
if (argc != 2) {
printf("usage: zre input.zre");
return EXIT_FAILURE;
}
char *buffer;
int length = 0;
int sp = open(argv[1], O_RDONLY);
if (sp) {
length = lseek(sp, (size_t)0, SEEK_END);
lseek(sp, (size_t)0, SEEK_SET);
buffer = malloc(length);
if (buffer) {
read(sp, buffer, length * sizeof(char));
}
close(sp);
}
initTokenMap();
compile(vm.memory, buffer);
vm.frames_size = FRAMES_SIZE;
vm.stack_size = STACK_SIZE;
vm.memory_size = MEMORY_SIZE;

View File

@ -15,9 +15,9 @@ typedef struct {
uint32_t end;
} Slice;
#define MAX_REGS 256
#define MAX_REGS 32
typedef struct {
Value registers[MAX_REGS]; /* R0-R255 */
Value registers[MAX_REGS]; /* R0-R31 */
uint32_t rp; /* register pointer (last unused) */
Slice allocated; /* start and end of global allocated block */
} Frame;
@ -55,9 +55,9 @@ typedef enum {
OP_POPF, /* popf : pop float from stack onto the register */
OP_POPS, /* pops : pop str ref from stack and move/copy to register */
OP_ADD_INT, /* addi : dest = src1 + src2 */
OP_SUB_INT, /* subs : dest = src1 - src2 */
OP_MUL_INT, /* mulm : dest = src1 * src2 */
OP_DIV_INT, /* divd : dest = src1 / src2 */
OP_SUB_INT, /* subi : dest = src1 - src2 */
OP_MUL_INT, /* muli : dest = src1 * src2 */
OP_DIV_INT, /* divi : dest = src1 / src2 */
OP_JEQ_INT, /* jeqi : jump to address dest if src1 as int == src2 as int */
OP_JGT_INT, /* jgti : jump to address dest if src1 as int > src2 as int*/
OP_JLT_INT, /* jlti : jump to address dest if src1 as int < src2 as int */
@ -92,8 +92,8 @@ typedef enum {
OP_INT_TO_STRING, /* itos : dest = src1 as str */
OP_UINT_TO_STRING, /* utos : dest = src1 as str */
OP_REAL_TO_STRING, /* rtos : dest = src1 as str */
OP_READ_STRING, /* read : dest = read as str */
OP_PRINT_STRING, /* wrte : write src1 to stdout */
OP_READ_STRING, /* gets : dest = gets as str */
OP_PRINT_STRING, /* puts : write src1 to stdout */
OP_CMP_STRING, /* cmps : dest = (str == src2) as bool */
} Opcode;

View File

@ -1,312 +0,0 @@
#include "parser.h"
#include "hashmap.h"
DEFINE_HASHMAP(TokenMap, 150);
TokenMap **tokenMap;
void initTokenMap() {
tokenMap = new_TokenMap();
put_TokenMap(tokenMap, "fn", TOKEN_FN);
put_TokenMap(tokenMap, "to", TOKEN_TO);
put_TokenMap(tokenMap, "in", TOKEN_IN);
put_TokenMap(tokenMap, "is", TOKEN_IS);
put_TokenMap(tokenMap, "as", TOKEN_AS);
put_TokenMap(tokenMap, "use", TOKEN_USE);
put_TokenMap(tokenMap, "if", TOKEN_IF);
put_TokenMap(tokenMap, "else", TOKEN_ELSE);
put_TokenMap(tokenMap, "default", TOKEN_DEFAULT);
put_TokenMap(tokenMap, "for", TOKEN_FOR);
put_TokenMap(tokenMap, "try", TOKEN_TRY);
put_TokenMap(tokenMap, "catch", TOKEN_CATCH);
put_TokenMap(tokenMap, "while", TOKEN_WHILE);
put_TokenMap(tokenMap, "do", TOKEN_DO);
put_TokenMap(tokenMap, "exit", TOKEN_EXIT);
put_TokenMap(tokenMap, "switch", TOKEN_SWITCH);
put_TokenMap(tokenMap, "return", TOKEN_RETURN);
put_TokenMap(tokenMap, "const", TOKEN_CONST);
put_TokenMap(tokenMap, "type", TOKEN_TYPE);
put_TokenMap(tokenMap, "this", TOKEN_THIS);
put_TokenMap(tokenMap, "yield", TOKEN_YIELD);
put_TokenMap(tokenMap, "case", TOKEN_CASE);
put_TokenMap(tokenMap, "assert", TOKEN_ASSERT);
put_TokenMap(tokenMap, "break", TOKEN_BREAK);
put_TokenMap(tokenMap, "let", TOKEN_LET);
put_TokenMap(tokenMap, "print", TOKEN_PRINT);
put_TokenMap(tokenMap, "nil", TOKEN_NULL);
put_TokenMap(tokenMap, "and", TOKEN_AND);
put_TokenMap(tokenMap, "or", TOKEN_OR);
put_TokenMap(tokenMap, "xor", TOKEN_XOR);
put_TokenMap(tokenMap, "mod", TOKEN_MOD);
put_TokenMap(tokenMap, "eq", TOKEN_EQ);
put_TokenMap(tokenMap, "ge", TOKEN_GE);
put_TokenMap(tokenMap, "lt", TOKEN_LT);
put_TokenMap(tokenMap, "le", TOKEN_LE);
put_TokenMap(tokenMap, "ne", TOKEN_NE);
put_TokenMap(tokenMap, "gt", TOKEN_GT);
put_TokenMap(tokenMap, "ge", TOKEN_GE);
put_TokenMap(tokenMap, "srl", TOKEN_SHIFTRIGHT);
put_TokenMap(tokenMap, "sll", TOKEN_SHIFTLEFT);
put_TokenMap(tokenMap, "toS", TOKEN_TO_S);
}
typedef struct Tokenizer Tokenizer;
struct Tokenizer {
char *start;
char *current;
int32_t line;
};
Tokenizer tokenizer;
void initTokenizer(char *src) {
tokenizer.start = src;
tokenizer.current = src;
tokenizer.line = 1;
}
static bool isAlpha(char c) {
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' ||
c == '\'' || c == '?';
}
static bool isDigit(char c) { return (c >= '0' && c <= '9') || c == '-'; }
static bool isAtEnd() { return *tokenizer.current == '\0'; }
static Token makeToken(TokenType type) {
Token token;
token.type = type;
token.start = tokenizer.start;
token.length = (int32_t)(tokenizer.current - tokenizer.start);
token.line = tokenizer.line;
return token;
}
static Token errorToken(char *msg) {
Token token;
token.type = TOKEN_ERROR;
token.start = msg;
token.length = (int32_t)strlen(msg);
token.line = tokenizer.line;
return token;
}
static char advance() {
tokenizer.current++;
return tokenizer.current[-1];
}
static char peek() { return *tokenizer.current; }
static char peekNext() {
if (isAtEnd())
return '\0';
return tokenizer.current[1];
}
static void skipWhitespace() {
for (;;) {
char c = peek();
switch (c) {
case ' ':
case '\r':
case '\t':
advance();
break;
case '\n':
tokenizer.line++;
advance();
break;
case '!':
while (peek() != '\n' && !isAtEnd())
advance();
break;
default:
return;
}
}
}
static char *currentTokenToS() {
int32_t size = tokenizer.current - tokenizer.start;
char *str = (char *)malloc(sizeof(size));
strncpy(str, tokenizer.start, size);
str[size] = '\0';
return str;
}
TokenType getToken(char *s) {
TokenMap *np;
for (np = tokenMap[hash_TokenMap(s)]; np != NULL; np = np->next)
if (strcmp(s, np->keyword) == 0)
return np->token;
return TOKEN_IDENTIFIER;
}
static TokenType identifierType() {
char *check = currentTokenToS();
TokenType t = getToken(check);
free(check);
return t;
}
static Token identifier() {
while (isAlpha(peek()) || isDigit(peek()))
advance();
return makeToken(identifierType());
}
static Token number() {
bool is_float = false;
while (isDigit(peek()))
advance();
/* Look for a fractional part. */
if (peek() == '.' && isDigit(peekNext())) {
is_float = true;
/* Consume the ".". */
advance();
while (isDigit(peek()))
advance();
}
return makeToken((is_float)
? TOKEN_FLOAT
: TOKEN_INT); /* or measure if ends in postscript */
}
static Token string() {
while (peek() != '"' && !isAtEnd()) {
if (peek() == '\n')
tokenizer.line++;
advance();
}
if (isAtEnd())
return errorToken("Unterminated string.");
/* The closing quote. */
advance();
return makeToken(TOKEN_STRING);
}
Token nextToken() {
skipWhitespace();
tokenizer.start = tokenizer.current;
if (isAtEnd())
return makeToken(TOKEN_EOF);
char c = advance();
if (isAlpha(c))
return identifier();
if (isDigit(c))
return number();
switch (c) {
case '(':
return makeToken(TOKEN_LEFT_PAREN);
case ')':
return makeToken(TOKEN_RIGHT_PAREN);
case '{':
return makeToken(TOKEN_LEFT_BRACE);
case '}':
return makeToken(TOKEN_RIGHT_BRACE);
case '+':
return makeToken(TOKEN_ADD);
case '/':
return makeToken(TOKEN_DIV);
case '-':
return makeToken(TOKEN_SUB);
case '*':
return makeToken(TOKEN_MUL);
case ';':
return makeToken(TOKEN_SEMICOLON);
case '=':
return makeToken(TOKEN_EQUALS);
case '.':
return makeToken(TOKEN_DOT);
case '"':
return string();
}
return errorToken("Unexpected character.");
}
void printToken(Token t) {
char *str = currentTokenToS();
switch (t.type) {
PRINT_TOKEN_CASE(TOKEN_EQUALS)
PRINT_TOKEN_CASE(TOKEN_DOT)
PRINT_TOKEN_CASE(TOKEN_LEFT_PAREN)
PRINT_TOKEN_CASE(TOKEN_RIGHT_PAREN)
PRINT_TOKEN_CASE(TOKEN_LEFT_BRACE)
PRINT_TOKEN_CASE(TOKEN_RIGHT_BRACE)
PRINT_TOKEN_CASE(TOKEN_SEMICOLON)
PRINT_TOKEN_CASE(TOKEN_IDENTIFIER)
PRINT_TOKEN_CASE(TOKEN_STRING)
PRINT_TOKEN_CASE(TOKEN_FLOAT)
PRINT_TOKEN_CASE(TOKEN_U8)
PRINT_TOKEN_CASE(TOKEN_I8)
PRINT_TOKEN_CASE(TOKEN_U16)
PRINT_TOKEN_CASE(TOKEN_I16)
PRINT_TOKEN_CASE(TOKEN_U64)
PRINT_TOKEN_CASE(TOKEN_I64)
PRINT_TOKEN_CASE(TOKEN_INT)
PRINT_TOKEN_CASE(TOKEN_UINT)
/* PRINT_TOKEN_CASE(TOKEN_ARRAY) */
/* PRINT_TOKEN_CASE(TOKEN_MAP) */
PRINT_TOKEN_CASE(TOKEN_FALSE)
PRINT_TOKEN_CASE(TOKEN_TRUE)
PRINT_TOKEN_CASE(TOKEN_NULL)
PRINT_TOKEN_CASE(TOKEN_EOF)
PRINT_TOKEN_CASE(TOKEN_ERROR)
PRINT_TOKEN_CASE(TOKEN_ADD)
PRINT_TOKEN_CASE(TOKEN_SUB)
PRINT_TOKEN_CASE(TOKEN_MUL)
PRINT_TOKEN_CASE(TOKEN_DIV)
PRINT_TOKEN_CASE(TOKEN_MOD)
PRINT_TOKEN_CASE(TOKEN_GT)
PRINT_TOKEN_CASE(TOKEN_LT)
PRINT_TOKEN_CASE(TOKEN_EQ)
PRINT_TOKEN_CASE(TOKEN_GE)
PRINT_TOKEN_CASE(TOKEN_LE)
PRINT_TOKEN_CASE(TOKEN_NE)
PRINT_TOKEN_CASE(TOKEN_AND)
PRINT_TOKEN_CASE(TOKEN_OR)
PRINT_TOKEN_CASE(TOKEN_XOR)
PRINT_TOKEN_CASE(TOKEN_SHIFTRIGHT)
PRINT_TOKEN_CASE(TOKEN_SHIFTLEFT)
PRINT_TOKEN_CASE(TOKEN_FN)
PRINT_TOKEN_CASE(TOKEN_TO)
PRINT_TOKEN_CASE(TOKEN_IN)
PRINT_TOKEN_CASE(TOKEN_IS)
PRINT_TOKEN_CASE(TOKEN_AS)
PRINT_TOKEN_CASE(TOKEN_USE)
PRINT_TOKEN_CASE(TOKEN_IF)
PRINT_TOKEN_CASE(TOKEN_ELSE)
PRINT_TOKEN_CASE(TOKEN_DEFAULT)
PRINT_TOKEN_CASE(TOKEN_FOR)
PRINT_TOKEN_CASE(TOKEN_TRY)
PRINT_TOKEN_CASE(TOKEN_CATCH)
PRINT_TOKEN_CASE(TOKEN_WHILE)
PRINT_TOKEN_CASE(TOKEN_DO)
PRINT_TOKEN_CASE(TOKEN_EXIT)
PRINT_TOKEN_CASE(TOKEN_SWITCH)
PRINT_TOKEN_CASE(TOKEN_RETURN)
PRINT_TOKEN_CASE(TOKEN_CONST)
PRINT_TOKEN_CASE(TOKEN_TYPE)
PRINT_TOKEN_CASE(TOKEN_THIS)
PRINT_TOKEN_CASE(TOKEN_YIELD)
PRINT_TOKEN_CASE(TOKEN_CASE)
PRINT_TOKEN_CASE(TOKEN_ASSERT)
PRINT_TOKEN_CASE(TOKEN_BREAK)
PRINT_TOKEN_CASE(TOKEN_LET)
PRINT_TOKEN_CASE(TOKEN_PRINT)
PRINT_TOKEN_CASE(TOKEN_TO_S)
}
free(str);
}

View File

@ -1,118 +0,0 @@
#ifndef ZRE_PARSER_H
#define ZRE_PARSER_H
#include "common.h"
#include <string.h>
typedef enum TokenType
{
/* Single char tokens */
TOKEN_LEFT_PAREN,
TOKEN_RIGHT_PAREN,
TOKEN_LEFT_BRACE,
TOKEN_RIGHT_BRACE,
TOKEN_SEMICOLON,
TOKEN_EQUALS,
TOKEN_DOT,
/* Literals */
TOKEN_IDENTIFIER,
TOKEN_STRING,
TOKEN_FLOAT,
TOKEN_U8,
TOKEN_I8,
TOKEN_U16,
TOKEN_I16,
TOKEN_U64,
TOKEN_I64,
TOKEN_INT,
TOKEN_UINT,
/* TOKEN_ARRAY, */
/* TOKEN_MAP, */
TOKEN_FALSE,
TOKEN_TRUE,
TOKEN_NULL,
TOKEN_EOF,
TOKEN_ERROR,
/* Operators */
TOKEN_ADD,
TOKEN_SUB,
TOKEN_MUL,
TOKEN_DIV,
TOKEN_MOD,
TOKEN_GT,
TOKEN_LT,
TOKEN_EQ,
TOKEN_GE,
TOKEN_LE,
TOKEN_NE,
TOKEN_AND,
TOKEN_OR,
TOKEN_XOR,
TOKEN_SHIFTRIGHT,
TOKEN_SHIFTLEFT,
/* Keywords */
TOKEN_FN,
TOKEN_TO,
TOKEN_IN,
TOKEN_IS,
TOKEN_AS,
TOKEN_USE,
TOKEN_IF,
TOKEN_ELSE,
TOKEN_DEFAULT,
TOKEN_FOR,
TOKEN_TRY,
TOKEN_CATCH,
TOKEN_WHILE,
TOKEN_DO,
TOKEN_EXIT,
TOKEN_SWITCH,
TOKEN_RETURN,
TOKEN_CONST,
TOKEN_TYPE,
TOKEN_THIS,
TOKEN_YIELD,
TOKEN_CASE,
TOKEN_ASSERT,
TOKEN_BREAK,
TOKEN_LET,
TOKEN_PRINT,
TOKEN_TO_S,
} TokenType;
#define PRINT_TOKEN_CASE(token_suffix) \
case token_suffix: \
printf("" #token_suffix " %s line_no=%d\n", str, t.line); \
break;
typedef struct Token Token;
struct Token
{
TokenType type;
char *start;
int32_t length;
int32_t line;
};
typedef struct SourceCode SourceCode;
struct SourceCode
{
size_t size;
char *buf;
int count;
};
typedef struct TokenMap TokenMap;
struct TokenMap
{
struct TokenMap* next;
char* keyword;
TokenType token;
};
void initTokenMap();
void initTokenizer (char *src);
void printToken (Token t);
Token nextToken();
#endif

View File

@ -1,5 +1,4 @@
#include "compiler.h"
#include "parser.h"
#include "test.h"
uint32_t test_add_compile(Value *memory) {
uint32_t i = 0;
@ -76,44 +75,32 @@ uint32_t test_add_function_compile(Value *memory) {
}
uint32_t test_recursive_function_compile(Value *memory) {
uint32_t i = 0;
uint32_t i = 3;
memory[i++].u = OP(OP_POPU, 0, 0, 0); /* return ptr */
memory[i++].u = OP(OP_POPI, 1, 0, 0); /* n int */
/* if (n < 2) */
/* return n; */
memory[i++].u = OP(OP_POPI, 2, 0, 0); /* fib(n - 2) */
memory[i++].u = OP(OP_POPI, 3, 0, 0); /* fib(n - 1) */
memory[i++].u = OP(OP_ADD_INT, 4, 3, 2); /* add */
memory[i++].u = OP(OP_PUSHI, 4, 0, 0); /* return */
memory[i++].u = OP(OP_RETURN, 0, 0, 0);
uint32_t main = i;
memory[0].u = OP(OP_LOADF, 0, 0, 0);
memory[1].u = main;
memory[2].u = OP(OP_JMP, 0, 0, 0); /* jump to 'main' */
memory[i++].u = OP(OP_LOADI, 0, 0, 0); /* 35 */
memory[i++].i = 35;
memory[i++].u = OP(OP_PUSHI, 0, 0, 0);
uint32_t add_fn_return = i + 6; /* after the call */
memory[i++].u = OP(OP_LOADI, 0, 0, 0); /* return */
memory[i++].u = add_fn_return;
memory[i++].u = OP(OP_PUSHU, 0, 0, 0);
memory[i++].u = OP(OP_LOADU, 0, 0, 0); /* add fn ptr */
memory[i++].u = 3;
memory[i++].u = OP(OP_CALL, 0, 0, 0); /* ); */
memory[i++].u = OP(OP_POPI, 0, 0, 0); /* get return value */
memory[i++].u = OP(OP_INT_TO_STRING, 1, 0, 0);
memory[i++].u = OP(OP_HALT, 0, 0, 0);
return i;
}
static void letDeclaration() {
/* uint8_t global = parseVariable("Expect variable name."); */
/* if (match(TOKEN_EQUAL)) { */
/* expression(); */
/* } else { */
/* emitByte(OP_NIL); */
/* } */
/* consume(TOKEN_SEMICOLON, */
/* "Expect ';' after variable declaration."); */
/* defineVariable(global); */
}
static void declaration(Token t) {
if (t.type == TOKEN_LET) {
letDeclaration();
} else {
/* statement(); */
}
}
/**
* Compile.
*/
uint32_t compile(Value *memory, char *buffer) {
uint32_t i = 0;
initTokenizer(buffer);
Token t = nextToken();
while (t.type != TOKEN_EOF) {
printToken(t);
declaration(t);
t = nextToken();
}
return i;
}

View File

@ -1,5 +1,5 @@
#ifndef ZRE_COMPILER_H
#define ZRE_COMPILER_H
#ifndef ZRE_TEST_H
#define ZRE_TEST_H
#include "opcodes.h"
@ -7,6 +7,5 @@ uint32_t test_add_compile (Value *memory);
uint32_t test_loop_compile (Value *memory);
uint32_t test_add_function_compile(Value *memory);
uint32_t test_recursive_function_compile(Value *memory);
uint32_t compile (Value* memory, char *buffer);
#endif

View File

@ -258,7 +258,7 @@ bool step_vm(VM *vm) {
}
vm->memory[str_dest].u = length;
vm->frames[vm->fp].allocated.end +=
length + 1; /* increment to end of allocated */
((length / 4) + (length % 4) + 1); /* increment to end of allocated */
return true;
}
case OP_PRINT_STRING: {

View File

@ -1,6 +1,6 @@
fn add(int a, int b) int {
int add(int a, int b) {
return a + b;
}
let sum = add(1, 1);
int sum = add(1, 1);
print(sum.toS());

18
test/add.asm Normal file
View File

@ -0,0 +1,18 @@
main:
loadi $0 1 ;load 1 into r0
pushi $0 ;push onto stack
loadi $0 1 ;1
pushi $0
call &add ; call memory location for tag "add"
popi $0 ;get value from function call "add"
itos $1 $0 ;convert int to string
puts $1 ;print string to stdout
halt
add:
popu $0 ; pop unsigned int
popi $1 ; int a
popi $2 ; int b
addi $3 $2 $1 ; a + b
pushi $3 ; push a + b onto stack for return
return $0 ; actually do the return

View File

@ -1,2 +1,2 @@
let sum = 1 + 2;
int sum = 1 + 2;
print(sum.toS());

View File

@ -1,6 +1,8 @@
fn fib(int n) {
if (n < 2) return n;
int fib(int n) {
if (n < 2) {
return n;
}
return fib(n - 2) + fib(n - 1);
}
print fib(35);
print(fib(35).toS());

View File

@ -1,9 +1,9 @@
let a = 5.0;
do (i = 5, 0, -1) {
real a = 5.0;
do (int i = 5, 0, -1) {
a += 5.0;
}
let b = a as nat;
let user_string = gets();
nat b = a as nat;
str user_string = readln();
print(a.toS());
print(b.toS());
print(user_string);