Add global variables
This commit is contained in:
parent
11158ba4f9
commit
9d7fdbb622
|
|
@ -12,9 +12,11 @@
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
static char* readFile(const char* path) {
|
static char *
|
||||||
FILE* file = fopen(path, "rb");
|
readFile(const char *path)
|
||||||
if (file == NULL) {
|
{
|
||||||
|
FILE *file = fopen(path, "rb");
|
||||||
|
if(file == NULL) {
|
||||||
fprintf(stderr, "Could not open file \"%s\".\n", path);
|
fprintf(stderr, "Could not open file \"%s\".\n", path);
|
||||||
exit(74);
|
exit(74);
|
||||||
}
|
}
|
||||||
|
|
@ -23,13 +25,13 @@ static char* readFile(const char* path) {
|
||||||
size_t fileSize = ftell(file);
|
size_t fileSize = ftell(file);
|
||||||
rewind(file);
|
rewind(file);
|
||||||
|
|
||||||
char* buffer = (char*)malloc(fileSize + 1);
|
char *buffer = (char *)malloc(fileSize + 1);
|
||||||
if (buffer == NULL) {
|
if(buffer == NULL) {
|
||||||
fprintf(stderr, "Not enough memory to read \"%s\".\n", path);
|
fprintf(stderr, "Not enough memory to read \"%s\".\n", path);
|
||||||
exit(74);
|
exit(74);
|
||||||
}
|
}
|
||||||
size_t bytesRead = fread(buffer, sizeof(char), fileSize, file);
|
size_t bytesRead = fread(buffer, sizeof(char), fileSize, file);
|
||||||
if (bytesRead < fileSize) {
|
if(bytesRead < fileSize) {
|
||||||
fprintf(stderr, "Could not read file \"%s\".\n", path);
|
fprintf(stderr, "Could not read file \"%s\".\n", path);
|
||||||
exit(74);
|
exit(74);
|
||||||
}
|
}
|
||||||
|
|
@ -40,14 +42,19 @@ static char* readFile(const char* path) {
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_help() {
|
void
|
||||||
printf("Usage: undar [options] file...\nOptions:\n\t-emit={c|u}\tEmitter output, currently C source and Uxn binary.\n\n");
|
print_help()
|
||||||
|
{
|
||||||
|
printf("Usage: undar [options] file...\nOptions:\n\t-emit={c|u}\tEmitter "
|
||||||
|
"output, currently C source and Uxn binary.\n\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define MEM_SIZE 68000
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
if (argc > 1 && (seq(argv[1], "--help") || seq(argv[1], "-h"))) {
|
if(argc > 1 && (seq(argv[1], "--help") || seq(argv[1], "-h"))) {
|
||||||
print_help();
|
print_help();
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
@ -58,17 +65,19 @@ main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
Emitter e;
|
Emitter e;
|
||||||
if (seq(argv[1], "-emit=c")) {
|
if(seq(argv[1], "-emit=c")) {
|
||||||
e = c_emitter();
|
e = c_emitter();
|
||||||
} else if (seq(argv[1], "-emit=u")) {
|
} else if(seq(argv[1], "-emit=u")) {
|
||||||
e = uxn_emitter();
|
e = uxn_emitter();
|
||||||
} else {
|
} else {
|
||||||
printf("unknown emitter type\n");
|
printf("unknown emitter type\n");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
u8 tape[MEM_SIZE];
|
||||||
|
Arena a = {tape, 0, MEM_SIZE};
|
||||||
|
|
||||||
char* source = readFile(argv[2]);
|
char *source = readFile(argv[2]);
|
||||||
compile(e, source);
|
compile(&a, e, source);
|
||||||
free(source);
|
free(source);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
#ifndef UNDAR_COMMON_H
|
||||||
|
#define UNDAR_COMMON_H
|
||||||
|
|
||||||
|
#include "libc.h"
|
||||||
|
#include "list.h"
|
||||||
|
|
||||||
|
typedef enum symbol_type_e {
|
||||||
|
SYMBOL_VOID,
|
||||||
|
SYMBOL_BOOL,
|
||||||
|
SYMBOL_BYTE,
|
||||||
|
SYMBOL_INT,
|
||||||
|
SYMBOL_NAT,
|
||||||
|
SYMBOL_REAL,
|
||||||
|
SYMBOL_STR,
|
||||||
|
SYMBOL_U8,
|
||||||
|
SYMBOL_I8,
|
||||||
|
SYMBOL_I16,
|
||||||
|
SYMBOL_U16,
|
||||||
|
SYMBOL_I32,
|
||||||
|
SYMBOL_U32,
|
||||||
|
SYMBOL_F32,
|
||||||
|
SYMBOL_ARRAY,
|
||||||
|
SYMBOL_FUNCTION,
|
||||||
|
SYMBOL_PLEX,
|
||||||
|
SYMBOL_METHOD,
|
||||||
|
SYMBOL_TRAIT,
|
||||||
|
SYMBOL_CONST
|
||||||
|
} SymbolType;
|
||||||
|
|
||||||
|
typedef struct symbol_s Symbol;
|
||||||
|
|
||||||
|
#define MAX_SYMBOL_NAME_LENGTH 64
|
||||||
|
struct symbol_s {
|
||||||
|
char name[MAX_SYMBOL_NAME_LENGTH]; /* ptr to name */
|
||||||
|
u8 name_length; /* length of the name, max 64 */
|
||||||
|
SymbolType type; /* the type for this symbol */
|
||||||
|
SymbolType secondary_type; /* return type for functions/methods, or const if type/plex */
|
||||||
|
u32 ref; /* either constant value or pointer to other thing */
|
||||||
|
u32 size; /* either size of the plex or length of the array/list/etc. */
|
||||||
|
List *args; /* function params or plex constructor args */
|
||||||
|
List *fields; /* either plex variable fields, or method signatures */
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
33
emit.h
33
emit.h
|
|
@ -1,6 +1,7 @@
|
||||||
#ifndef UNDAR_EMIT_H
|
#ifndef UNDAR_EMIT_H
|
||||||
#define UNDAR_EMIT_H
|
#define UNDAR_EMIT_H
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
#include "libc.h"
|
#include "libc.h"
|
||||||
|
|
||||||
typedef enum notation_type_e {
|
typedef enum notation_type_e {
|
||||||
|
|
@ -14,13 +15,17 @@ typedef enum output_type_e {
|
||||||
TEXT
|
TEXT
|
||||||
} OutputType;
|
} OutputType;
|
||||||
|
|
||||||
|
typedef void (*SymbolEmit)(Symbol *sym);
|
||||||
|
typedef void (*ErrorMsg)(const char *str, i32 length, i32 line);
|
||||||
typedef void (*VoidArgEmit)();
|
typedef void (*VoidArgEmit)();
|
||||||
typedef void (*StrArgEmit)(const char *str, i32 length);
|
typedef void (*StrArgEmit)(const char *str, i32 length);
|
||||||
|
typedef i32 (*TypeVariableEmit)(const char *str, i32 length);
|
||||||
|
|
||||||
typedef struct emitter_s Emitter;
|
typedef struct emitter_s Emitter;
|
||||||
struct emitter_s {
|
struct emitter_s {
|
||||||
NotationType notation;
|
NotationType notation;
|
||||||
OutputType output;
|
OutputType output;
|
||||||
|
ErrorMsg error;
|
||||||
VoidArgEmit prolog;
|
VoidArgEmit prolog;
|
||||||
VoidArgEmit epilogue;
|
VoidArgEmit epilogue;
|
||||||
VoidArgEmit emit_add;
|
VoidArgEmit emit_add;
|
||||||
|
|
@ -42,19 +47,19 @@ struct emitter_s {
|
||||||
StrArgEmit emit_real;
|
StrArgEmit emit_real;
|
||||||
StrArgEmit emit_byte;
|
StrArgEmit emit_byte;
|
||||||
StrArgEmit emit_str;
|
StrArgEmit emit_str;
|
||||||
VoidArgEmit emit_bool_type;
|
TypeVariableEmit emit_bool_type;
|
||||||
VoidArgEmit emit_byte_type;
|
TypeVariableEmit emit_byte_type;
|
||||||
VoidArgEmit emit_int_type;
|
TypeVariableEmit emit_int_type;
|
||||||
VoidArgEmit emit_nat_type;
|
TypeVariableEmit emit_nat_type;
|
||||||
VoidArgEmit emit_real_type;
|
TypeVariableEmit emit_real_type;
|
||||||
VoidArgEmit emit_str_type;
|
TypeVariableEmit emit_str_type;
|
||||||
VoidArgEmit emit_u8_type;
|
TypeVariableEmit emit_u8_type;
|
||||||
VoidArgEmit emit_i8_type;
|
TypeVariableEmit emit_i8_type;
|
||||||
VoidArgEmit emit_i16_type;
|
TypeVariableEmit emit_i16_type;
|
||||||
VoidArgEmit emit_u16_type;
|
TypeVariableEmit emit_u16_type;
|
||||||
VoidArgEmit emit_i32_type;
|
TypeVariableEmit emit_i32_type;
|
||||||
VoidArgEmit emit_u32_type;
|
TypeVariableEmit emit_u32_type;
|
||||||
VoidArgEmit emit_f32_type;
|
TypeVariableEmit emit_f32_type;
|
||||||
VoidArgEmit emit_array;
|
VoidArgEmit emit_array;
|
||||||
VoidArgEmit emit_function;
|
VoidArgEmit emit_function;
|
||||||
VoidArgEmit emit_plex;
|
VoidArgEmit emit_plex;
|
||||||
|
|
@ -66,6 +71,8 @@ struct emitter_s {
|
||||||
VoidArgEmit emit_not;
|
VoidArgEmit emit_not;
|
||||||
VoidArgEmit emit_open_paren;
|
VoidArgEmit emit_open_paren;
|
||||||
VoidArgEmit emit_close_paren;
|
VoidArgEmit emit_close_paren;
|
||||||
|
StrArgEmit emit_constant;
|
||||||
|
SymbolEmit emit_variable;
|
||||||
};
|
};
|
||||||
|
|
||||||
Emitter c_emitter();
|
Emitter c_emitter();
|
||||||
|
|
|
||||||
101
emit/c/emit.c
101
emit/c/emit.c
|
|
@ -1,5 +1,13 @@
|
||||||
#include "../../emit.h"
|
#include "../../emit.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
void
|
||||||
|
c_emit_error(const char *str, i32 length, i32 line)
|
||||||
|
{
|
||||||
|
printf("Error at line: %d > %.*s\n ", line, length, str);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
c_prolog()
|
c_prolog()
|
||||||
|
|
@ -106,69 +114,95 @@ c_emit_void()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
i32
|
||||||
c_emit_bool_type()
|
c_emit_bool_type(const char *str, i32 length)
|
||||||
{
|
{
|
||||||
|
printf("%.*s ", length, str);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
i32
|
||||||
c_emit_byte_type()
|
c_emit_byte_type(const char *str, i32 length)
|
||||||
{
|
{
|
||||||
|
printf("%.*s ", length, str);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
i32
|
||||||
c_emit_int_type()
|
c_emit_int_type(const char *str, i32 length)
|
||||||
{
|
{
|
||||||
|
printf("%.*s ", length, str);
|
||||||
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
i32
|
||||||
c_emit_nat_type()
|
c_emit_nat_type(const char *str, i32 length)
|
||||||
{
|
{
|
||||||
|
printf("%.*s ", length, str);
|
||||||
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
i32
|
||||||
c_emit_real_type()
|
c_emit_real_type(const char *str, i32 length)
|
||||||
{
|
{
|
||||||
|
printf("%.*s ", length, str);
|
||||||
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
i32
|
||||||
c_emit_str_type()
|
c_emit_str_type(const char *str, i32 length)
|
||||||
{
|
{
|
||||||
|
printf("%.*s ", length, str);
|
||||||
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
i32
|
||||||
c_emit_u8_type()
|
c_emit_u8_type(const char *str, i32 length)
|
||||||
{
|
{
|
||||||
|
printf("%.*s ", length, str);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
i32
|
||||||
c_emit_i8_type()
|
c_emit_i8_type(const char *str, i32 length)
|
||||||
{
|
{
|
||||||
|
printf("%.*s ", length, str);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
i32
|
||||||
c_emit_i16_type()
|
c_emit_i16_type(const char *str, i32 length)
|
||||||
{
|
{
|
||||||
|
printf("%.*s ", length, str);
|
||||||
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
i32
|
||||||
c_emit_u16_type()
|
c_emit_u16_type(const char *str, i32 length)
|
||||||
{
|
{
|
||||||
|
printf("%.*s ", length, str);
|
||||||
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
i32
|
||||||
c_emit_i32_type()
|
c_emit_i32_type(const char *str, i32 length)
|
||||||
{
|
{
|
||||||
|
printf("%.*s ", length, str);
|
||||||
|
return 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
i32
|
||||||
c_emit_u32_type()
|
c_emit_u32_type(const char *str, i32 length)
|
||||||
{
|
{
|
||||||
|
printf("%.*s ", length, str);
|
||||||
|
return 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
i32
|
||||||
c_emit_f32_type()
|
c_emit_f32_type(const char *str, i32 length)
|
||||||
{
|
{
|
||||||
|
printf("%.*s ", length, str);
|
||||||
|
return 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -249,12 +283,25 @@ c_emit_close_paren()
|
||||||
printf(")");
|
printf(")");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
c_emit_constant(const char *str, i32 length)
|
||||||
|
{
|
||||||
|
USED(str);
|
||||||
|
USED(length);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
c_emit_variable(Symbol *sym) {
|
||||||
|
USED(sym);
|
||||||
|
}
|
||||||
|
|
||||||
Emitter
|
Emitter
|
||||||
c_emitter()
|
c_emitter()
|
||||||
{
|
{
|
||||||
return (Emitter){
|
return (Emitter){
|
||||||
INFIX,
|
INFIX,
|
||||||
TEXT,
|
TEXT,
|
||||||
|
c_emit_error,
|
||||||
c_prolog,
|
c_prolog,
|
||||||
c_epilogue,
|
c_epilogue,
|
||||||
c_emit_add,
|
c_emit_add,
|
||||||
|
|
@ -300,5 +347,7 @@ c_emitter()
|
||||||
c_emit_not,
|
c_emit_not,
|
||||||
c_emit_open_paren,
|
c_emit_open_paren,
|
||||||
c_emit_close_paren,
|
c_emit_close_paren,
|
||||||
|
c_emit_constant,
|
||||||
|
c_emit_variable,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
151
emit/uxn/emit.c
151
emit/uxn/emit.c
|
|
@ -8,17 +8,44 @@
|
||||||
|
|
||||||
enum uxn_opcode {
|
enum uxn_opcode {
|
||||||
/* Stack I */ /* Logic */ /* Memory I */ /* Arithmetic*/
|
/* Stack I */ /* Logic */ /* Memory I */ /* Arithmetic*/
|
||||||
BRK = 0x00, EQU = 0x08, LDZ = 0x10, ADD = 0x18,
|
BRK = 0x00,
|
||||||
INC = 0x01, NEQ = 0x09, STZ = 0x11, SUB = 0x19,
|
EQU = 0x08,
|
||||||
POP = 0x02, GTH = 0x0A, LDR = 0x12, MUL = 0x1A,
|
LDZ = 0x10,
|
||||||
NIP = 0x03, LTH = 0x0B, STR = 0x13, DIV = 0x1B,
|
ADD = 0x18,
|
||||||
|
INC = 0x01,
|
||||||
|
NEQ = 0x09,
|
||||||
|
STZ = 0x11,
|
||||||
|
SUB = 0x19,
|
||||||
|
POP = 0x02,
|
||||||
|
GTH = 0x0A,
|
||||||
|
LDR = 0x12,
|
||||||
|
MUL = 0x1A,
|
||||||
|
NIP = 0x03,
|
||||||
|
LTH = 0x0B,
|
||||||
|
STR = 0x13,
|
||||||
|
DIV = 0x1B,
|
||||||
/* Stack II */ /* Stash */ /* Memory II */ /* Bitwise */
|
/* Stack II */ /* Stash */ /* Memory II */ /* Bitwise */
|
||||||
SWP = 0x04, JMP = 0x0C, LDA = 0x14, AND = 0x1C,
|
SWP = 0x04,
|
||||||
ROT = 0x05, JCN = 0x0D, STA = 0x15, ORA = 0x1D,
|
JMP = 0x0C,
|
||||||
DUP = 0x06, JSR = 0x0E, DEI = 0x16, EOR = 0x1E,
|
LDA = 0x14,
|
||||||
OVR = 0x07, STH = 0x0F, DEO = 0x17, SFT = 0x1F,
|
AND = 0x1C,
|
||||||
|
ROT = 0x05,
|
||||||
|
JCN = 0x0D,
|
||||||
|
STA = 0x15,
|
||||||
|
ORA = 0x1D,
|
||||||
|
DUP = 0x06,
|
||||||
|
JSR = 0x0E,
|
||||||
|
DEI = 0x16,
|
||||||
|
EOR = 0x1E,
|
||||||
|
OVR = 0x07,
|
||||||
|
STH = 0x0F,
|
||||||
|
DEO = 0x17,
|
||||||
|
SFT = 0x1F,
|
||||||
|
|
||||||
LIT = 0x80, JCI = 0x20, JMI = 0x40, JSI = 0x60,
|
LIT = 0x80,
|
||||||
|
JCI = 0x20,
|
||||||
|
JMI = 0x40,
|
||||||
|
JSI = 0x60,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -34,16 +61,23 @@ https://rosettacode.org/wiki/Bitwise_operations#Uxntal
|
||||||
%ror { SWP #00 ROT SFT2 ORA }
|
%ror { SWP #00 ROT SFT2 ORA }
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
uxn_emit_error(const char *str, i32 length, i32 line)
|
||||||
|
{
|
||||||
|
printf("Error at line: %d > %.*s\n ", line, length, str);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
uxn_prolog()
|
uxn_prolog()
|
||||||
{
|
{
|
||||||
|
/* essentially the "main" function */
|
||||||
|
printf("|100 @on-reset ( -> )\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
uxn_epilogue()
|
uxn_epilogue()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -141,69 +175,98 @@ uxn_emit_void()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
/* @global $size */
|
||||||
uxn_emit_bool_type()
|
/* &local $size */
|
||||||
|
|
||||||
|
i32
|
||||||
|
uxn_emit_bool_type(const char *str, i32 length)
|
||||||
{
|
{
|
||||||
|
printf("!{ @%.*s $1 } ", length, str);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
i32
|
||||||
uxn_emit_byte_type()
|
uxn_emit_byte_type(const char *str, i32 length)
|
||||||
{
|
{
|
||||||
|
printf("!{ @%.*s $1 } ", length, str);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
i32
|
||||||
uxn_emit_int_type()
|
uxn_emit_int_type(const char *str, i32 length)
|
||||||
{
|
{
|
||||||
|
printf("!{ @%.*s $2 } ", length, str);
|
||||||
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
i32
|
||||||
uxn_emit_nat_type()
|
uxn_emit_nat_type(const char *str, i32 length)
|
||||||
{
|
{
|
||||||
|
printf("!{ @%.*s $2 } ", length, str);
|
||||||
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
i32
|
||||||
uxn_emit_real_type()
|
uxn_emit_real_type(const char *str, i32 length)
|
||||||
{
|
{
|
||||||
|
printf("!{ @%.*s $2 } ", length, str);
|
||||||
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
i32
|
||||||
uxn_emit_str_type()
|
uxn_emit_str_type(const char *str, i32 length)
|
||||||
{
|
{
|
||||||
|
printf("!{ @%.*s $2 } ", length, str);
|
||||||
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
i32
|
||||||
uxn_emit_u8_type()
|
uxn_emit_u8_type(const char *str, i32 length)
|
||||||
{
|
{
|
||||||
|
printf("!{ @%.*s $1 } ", length, str);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
i32
|
||||||
uxn_emit_i8_type()
|
uxn_emit_i8_type(const char *str, i32 length)
|
||||||
{
|
{
|
||||||
|
printf("!{ @%.*s $1 } ", length, str);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
i32
|
||||||
uxn_emit_i16_type()
|
uxn_emit_i16_type(const char *str, i32 length)
|
||||||
{
|
{
|
||||||
|
printf("!{ @%.*s $2 } ", length, str);
|
||||||
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
i32
|
||||||
uxn_emit_u16_type()
|
uxn_emit_u16_type(const char *str, i32 length)
|
||||||
{
|
{
|
||||||
|
printf("!{ @%.*s $2 } ", length, str);
|
||||||
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
i32
|
||||||
uxn_emit_i32_type()
|
uxn_emit_i32_type(const char *str, i32 length)
|
||||||
{
|
{
|
||||||
|
printf("!{ @%.*s $4 } ", length, str);
|
||||||
|
return 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
i32
|
||||||
uxn_emit_u32_type()
|
uxn_emit_u32_type(const char *str, i32 length)
|
||||||
{
|
{
|
||||||
|
printf("!{ @%.*s $4 } ", length, str);
|
||||||
|
return 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
i32
|
||||||
uxn_emit_f32_type()
|
uxn_emit_f32_type(const char *str, i32 length)
|
||||||
{
|
{
|
||||||
|
printf("!{ @%.*s $4 } ", length, str);
|
||||||
|
return 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -244,6 +307,12 @@ uxn_emit_str(const char *str, i32 length)
|
||||||
printf("\"%.*s ", length, str);
|
printf("\"%.*s ", length, str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
uxn_emit_constant(const char *str, i32 length)
|
||||||
|
{
|
||||||
|
printf(";%.*s STA2 ", length, str);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
uxn_emit_array()
|
uxn_emit_array()
|
||||||
{
|
{
|
||||||
|
|
@ -283,12 +352,15 @@ uxn_emit_print()
|
||||||
void
|
void
|
||||||
uxn_emit_open_paren()
|
uxn_emit_open_paren()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
void
|
void
|
||||||
uxn_emit_close_paren()
|
uxn_emit_close_paren()
|
||||||
{
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
uxn_emit_variable(Symbol *sym) {
|
||||||
|
printf(";%.*s LDA2 ", sym->name_length, sym->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
Emitter
|
Emitter
|
||||||
|
|
@ -297,6 +369,7 @@ uxn_emitter()
|
||||||
return (Emitter){
|
return (Emitter){
|
||||||
POSTFIX,
|
POSTFIX,
|
||||||
BINARY,
|
BINARY,
|
||||||
|
uxn_emit_error,
|
||||||
uxn_prolog,
|
uxn_prolog,
|
||||||
uxn_epilogue,
|
uxn_epilogue,
|
||||||
uxn_emit_add,
|
uxn_emit_add,
|
||||||
|
|
@ -342,5 +415,7 @@ uxn_emitter()
|
||||||
uxn_emit_not,
|
uxn_emit_not,
|
||||||
uxn_emit_open_paren,
|
uxn_emit_open_paren,
|
||||||
uxn_emit_close_paren,
|
uxn_emit_close_paren,
|
||||||
|
uxn_emit_constant,
|
||||||
|
uxn_emit_variable,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
2
libc.c
2
libc.c
|
|
@ -19,7 +19,7 @@ scpy(char *to, const char *from, u32 length)
|
||||||
u32 i;
|
u32 i;
|
||||||
if(to == nil || from == nil) return -1;
|
if(to == nil || from == nil) return -1;
|
||||||
if(length == 0) return 0;
|
if(length == 0) return 0;
|
||||||
for(i = 0; i < length - 1 && from[i] != '\0'; i++) to[i] = from[i];
|
for(i = 0; i < length && from[i] != '\0'; i++) to[i] = from[i];
|
||||||
to[i] = '\0';
|
to[i] = '\0';
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
195
parser.c
195
parser.c
|
|
@ -3,13 +3,14 @@
|
||||||
|
|
||||||
Emitter emitter;
|
Emitter emitter;
|
||||||
Parser parser;
|
Parser parser;
|
||||||
|
Arena *arena;
|
||||||
|
|
||||||
/****************************************************
|
/****************************************************
|
||||||
* Scope
|
* Scope
|
||||||
***************************************************/
|
***************************************************/
|
||||||
|
|
||||||
void
|
void
|
||||||
scope_push(Arena *arena)
|
scope_push()
|
||||||
{
|
{
|
||||||
Scope *child = aalloc(arena, sizeof(Scope));
|
Scope *child = aalloc(arena, sizeof(Scope));
|
||||||
child->symbols = new_list(arena);
|
child->symbols = new_list(arena);
|
||||||
|
|
@ -41,20 +42,19 @@ scope_get_symbol(Scope *scope, const char *name, u32 name_length)
|
||||||
}
|
}
|
||||||
|
|
||||||
Symbol *
|
Symbol *
|
||||||
scope_add_symbol(Arena *arena, const char *name, u32 name_length,
|
scope_add_symbol(const char *name, u32 name_length, SymbolType type, u32 size)
|
||||||
SymbolType type, u32 size)
|
|
||||||
{
|
{
|
||||||
Symbol *sym = scope_get_symbol(parser.current_scope, name, name_length);
|
Symbol *sym = scope_get_symbol(parser.current_scope, name, name_length);
|
||||||
if(sym != nil) return sym;
|
if(sym != nil) return sym;
|
||||||
|
|
||||||
sym = aalloc(arena, sizeof(Symbol));
|
sym = aalloc(arena, sizeof(Symbol));
|
||||||
scpy(sym->name, name, slen(name));
|
scpy(sym->name, name, name_length);
|
||||||
sym->name_length = slen(name);
|
sym->name_length = name_length;
|
||||||
sym->type = type;
|
sym->type = type;
|
||||||
sym->secondary_type = VOID;
|
sym->secondary_type = SYMBOL_VOID;
|
||||||
sym->size = size;
|
sym->size = size;
|
||||||
sym->ref = 0;
|
sym->ref = 0;
|
||||||
if(type == PLEX || type == METHOD || type == TRAIT) {
|
if(type == SYMBOL_PLEX || type == SYMBOL_METHOD || type == SYMBOL_TRAIT) {
|
||||||
sym->args = new_list(arena);
|
sym->args = new_list(arena);
|
||||||
sym->fields = new_list(arena);
|
sym->fields = new_list(arena);
|
||||||
}
|
}
|
||||||
|
|
@ -64,6 +64,19 @@ scope_add_symbol(Arena *arena, const char *name, u32 name_length,
|
||||||
return sym;
|
return sym;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
is_global()
|
||||||
|
{
|
||||||
|
return parser.current_scope != nil && parser.current_scope->parent == nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
is_type()
|
||||||
|
{
|
||||||
|
return parser.previous.type >= TOKEN_TYPE_I8 &&
|
||||||
|
parser.previous.type <= TOKEN_TYPE_PTR;
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************
|
/****************************************************
|
||||||
* Parser
|
* Parser
|
||||||
***************************************************/
|
***************************************************/
|
||||||
|
|
@ -117,9 +130,8 @@ binary()
|
||||||
TokenType operatorType = parser.previous.type;
|
TokenType operatorType = parser.previous.type;
|
||||||
ParseRule *rule = get_rule(operatorType);
|
ParseRule *rule = get_rule(operatorType);
|
||||||
|
|
||||||
if (emitter.notation == POSTFIX) {
|
if(emitter.notation == POSTFIX)
|
||||||
parse_precedence((Precedence)(rule->precedence + 1));
|
parse_precedence((Precedence)(rule->precedence + 1));
|
||||||
}
|
|
||||||
|
|
||||||
switch(operatorType) {
|
switch(operatorType) {
|
||||||
case TOKEN_BANG_EQ:
|
case TOKEN_BANG_EQ:
|
||||||
|
|
@ -156,9 +168,8 @@ binary()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (emitter.notation == INFIX) {
|
if(emitter.notation == INFIX)
|
||||||
parse_precedence((Precedence)(rule->precedence + 1));
|
parse_precedence((Precedence)(rule->precedence + 1));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -185,55 +196,135 @@ expression()
|
||||||
parse_precedence(PREC_ASSIGNMENT);
|
parse_precedence(PREC_ASSIGNMENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void variable() {
|
||||||
|
Symbol *sym = scope_get_symbol(parser.current_scope, parser.previous.start, parser.previous.length);
|
||||||
|
if(sym == nil) {
|
||||||
|
emitter.error(parser.previous.start, parser.previous.length, parser.previous.line);
|
||||||
|
}
|
||||||
|
|
||||||
|
emitter.emit_variable(sym);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
variable_declaration()
|
||||||
|
{
|
||||||
|
|
||||||
|
i32 size = 0;
|
||||||
|
TokenType tt = parser.previous.type;
|
||||||
|
Token var = parser.current;
|
||||||
|
|
||||||
|
switch(tt) {
|
||||||
|
case TOKEN_TYPE_INT: {
|
||||||
|
size = emitter.emit_int_type(parser.current.start, parser.current.length);
|
||||||
|
scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_INT, size);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TOKEN_TYPE_NAT: {
|
||||||
|
size = emitter.emit_nat_type(parser.current.start, parser.current.length);
|
||||||
|
scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_NAT, size);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TOKEN_TYPE_REAL: {
|
||||||
|
size = emitter.emit_real_type(parser.current.start, parser.current.length);
|
||||||
|
scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_REAL, size);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TOKEN_TYPE_STR: {
|
||||||
|
/* FIXME: this is wrong, we need to store the size of the string, not just
|
||||||
|
* the pointer */
|
||||||
|
/* size = emitter.emit_str_type(parser.current.start, parser.current.length,
|
||||||
|
*/
|
||||||
|
/* is_global()); */
|
||||||
|
/* scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_STR, size);
|
||||||
|
*/
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TOKEN_TYPE_BOOL: {
|
||||||
|
size = emitter.emit_bool_type(parser.current.start, parser.current.length);
|
||||||
|
scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_BOOL, size);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TOKEN_TYPE_BYTE: {
|
||||||
|
size = emitter.emit_byte_type(parser.current.start, parser.current.length);
|
||||||
|
scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_U8, size);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TOKEN_TYPE_U8: {
|
||||||
|
size = emitter.emit_u8_type(parser.current.start, parser.current.length);
|
||||||
|
scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_U8, size);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TOKEN_TYPE_I8: {
|
||||||
|
size = emitter.emit_i8_type(parser.current.start, parser.current.length);
|
||||||
|
scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_I8, size);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TOKEN_TYPE_U16: {
|
||||||
|
size = emitter.emit_u16_type(parser.current.start, parser.current.length);
|
||||||
|
scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_U16, size);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TOKEN_TYPE_I16: {
|
||||||
|
size = emitter.emit_i16_type(parser.current.start, parser.current.length);
|
||||||
|
scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_I16, size);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
/* probably a variable */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
advance();
|
||||||
|
|
||||||
|
if(match(TOKEN_EQ)) {
|
||||||
|
expression();
|
||||||
|
emitter.emit_constant(var.start, var.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
consume(TOKEN_SEMICOLON);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
declaration()
|
declaration()
|
||||||
{
|
{
|
||||||
if(match(TOKEN_TYPE_INT)) {
|
|
||||||
emitter.emit_int_type();
|
|
||||||
} else if(match(TOKEN_TYPE_NAT)) {
|
|
||||||
emitter.emit_nat_type();
|
|
||||||
} else if(match(TOKEN_TYPE_REAL)) {
|
|
||||||
emitter.emit_real_type();
|
|
||||||
} else if(match(TOKEN_TYPE_STR)) {
|
|
||||||
emitter.emit_str_type();
|
|
||||||
} else if(match(TOKEN_TYPE_BOOL)) {
|
|
||||||
emitter.emit_bool_type();
|
|
||||||
} else if(match(TOKEN_TYPE_BYTE)) {
|
|
||||||
emitter.emit_byte_type();
|
|
||||||
} else if(match(TOKEN_TYPE_U8)) {
|
|
||||||
emitter.emit_u8_type();
|
|
||||||
} else if(match(TOKEN_TYPE_I8)) {
|
|
||||||
emitter.emit_i8_type();
|
|
||||||
} else if(match(TOKEN_TYPE_U16)) {
|
|
||||||
emitter.emit_u16_type();
|
|
||||||
} else if(match(TOKEN_TYPE_I16)) {
|
|
||||||
emitter.emit_i16_type();
|
|
||||||
} else if(match(TOKEN_IDENTIFIER)) {
|
|
||||||
/**
|
/**
|
||||||
* maybe a Plex?
|
* maybe a Plex?
|
||||||
* lookup plex defs
|
* lookup plex defs
|
||||||
* if not then
|
* if not then
|
||||||
*/
|
*/
|
||||||
}
|
|
||||||
|
|
||||||
|
if(is_type())
|
||||||
|
variable_declaration();
|
||||||
|
else
|
||||||
statement();
|
statement();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_statement() {
|
static void
|
||||||
if (emitter.notation == INFIX) {
|
print_statement()
|
||||||
emitter.emit_print();
|
{
|
||||||
}
|
if(emitter.notation == INFIX) emitter.emit_print();
|
||||||
expression();
|
expression();
|
||||||
consume(TOKEN_SEMICOLON);
|
consume(TOKEN_SEMICOLON);
|
||||||
if (emitter.notation == POSTFIX) {
|
if(emitter.notation == POSTFIX) emitter.emit_print();
|
||||||
emitter.emit_print();
|
}
|
||||||
}
|
|
||||||
|
static void
|
||||||
|
block()
|
||||||
|
{
|
||||||
|
while(!check(TOKEN_RBRACE) && !check(TOKEN_EOF)) declaration();
|
||||||
|
|
||||||
|
consume(TOKEN_RBRACE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
statement()
|
statement()
|
||||||
{
|
{
|
||||||
if(match(TOKEN_KEYWORD_PRINT)) {
|
if(match(TOKEN_LBRACE)) {
|
||||||
|
scope_push();
|
||||||
|
block();
|
||||||
|
scope_pop();
|
||||||
|
} else if(match(TOKEN_KEYWORD_PRINT)) {
|
||||||
print_statement();
|
print_statement();
|
||||||
} else {
|
} else {
|
||||||
expression();
|
expression();
|
||||||
|
|
@ -267,9 +358,7 @@ static void
|
||||||
unary()
|
unary()
|
||||||
{
|
{
|
||||||
TokenType operatorType = parser.previous.type;
|
TokenType operatorType = parser.previous.type;
|
||||||
if (emitter.notation == POSTFIX) {
|
if(emitter.notation == POSTFIX) parse_precedence(PREC_UNARY);
|
||||||
parse_precedence(PREC_UNARY);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(operatorType) {
|
switch(operatorType) {
|
||||||
case TOKEN_MINUS:
|
case TOKEN_MINUS:
|
||||||
|
|
@ -282,15 +371,13 @@ unary()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (emitter.notation == INFIX) {
|
if(emitter.notation == INFIX) parse_precedence(PREC_UNARY);
|
||||||
parse_precedence(PREC_UNARY);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ParseRule rules[] = {
|
ParseRule rules[] = {
|
||||||
/* 0 */ {NULL, NULL, PREC_NONE},
|
/* 0 */ {NULL, NULL, PREC_NONE}, /* TOKEN_ERROR */
|
||||||
/* 1 */ {NULL, NULL, PREC_NONE},
|
/* 1 */ {NULL, NULL, PREC_NONE}, /* TOKEN_EOF */
|
||||||
/* 2 */ {NULL, NULL, PREC_NONE},
|
/* 2 */ {variable, NULL, PREC_NONE}, /* TOKEN_IDENTIFIER */
|
||||||
/* 3 */ {number, NULL, PREC_NONE}, /* TOKEN_LITERAL_INT */
|
/* 3 */ {number, NULL, PREC_NONE}, /* TOKEN_LITERAL_INT */
|
||||||
/* 4 */ {number, NULL, PREC_NONE}, /* TOKEN_LITERAL_NAT */
|
/* 4 */ {number, NULL, PREC_NONE}, /* TOKEN_LITERAL_NAT */
|
||||||
/* 5 */ {number, NULL, PREC_NONE}, /* TOKEN_LITERAL_REAL */
|
/* 5 */ {number, NULL, PREC_NONE}, /* TOKEN_LITERAL_REAL */
|
||||||
|
|
@ -377,9 +464,7 @@ parse_precedence(Precedence precedence)
|
||||||
|
|
||||||
advance();
|
advance();
|
||||||
prefixRule = get_rule(parser.previous.type)->prefix;
|
prefixRule = get_rule(parser.previous.type)->prefix;
|
||||||
if(prefixRule == NULL) {
|
if(prefixRule == NULL) return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
prefixRule();
|
prefixRule();
|
||||||
|
|
||||||
|
|
@ -397,11 +482,13 @@ get_rule(TokenType type)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
compile(Emitter e, char *source)
|
compile(Arena *a, Emitter e, char *source)
|
||||||
{
|
{
|
||||||
|
arena = a;
|
||||||
emitter = e;
|
emitter = e;
|
||||||
init_lexer(source);
|
init_lexer(source);
|
||||||
advance();
|
advance();
|
||||||
|
scope_push();
|
||||||
|
|
||||||
emitter.prolog();
|
emitter.prolog();
|
||||||
|
|
||||||
|
|
|
||||||
41
parser.h
41
parser.h
|
|
@ -1,51 +1,14 @@
|
||||||
#ifndef UNDAR_PARSER_H
|
#ifndef UNDAR_PARSER_H
|
||||||
#define UNDAR_PARSER_H
|
#define UNDAR_PARSER_H
|
||||||
|
|
||||||
#include "libc.h"
|
#include "common.h"
|
||||||
#include "list.h"
|
|
||||||
#include "lexer.h"
|
#include "lexer.h"
|
||||||
#include "emit.h"
|
#include "emit.h"
|
||||||
|
|
||||||
typedef enum symbol_type_e {
|
|
||||||
VOID,
|
|
||||||
BOOL,
|
|
||||||
BYTE,
|
|
||||||
INT,
|
|
||||||
NAT,
|
|
||||||
REAL,
|
|
||||||
STR,
|
|
||||||
U8,
|
|
||||||
I8,
|
|
||||||
I16,
|
|
||||||
U16,
|
|
||||||
I32,
|
|
||||||
U32,
|
|
||||||
F32,
|
|
||||||
ARRAY,
|
|
||||||
FUNCTION,
|
|
||||||
PLEX,
|
|
||||||
METHOD,
|
|
||||||
TRAIT,
|
|
||||||
CONST
|
|
||||||
} SymbolType;
|
|
||||||
|
|
||||||
typedef struct symbol_s Symbol;
|
|
||||||
typedef struct scope_s Scope;
|
typedef struct scope_s Scope;
|
||||||
typedef struct parser_s Parser;
|
typedef struct parser_s Parser;
|
||||||
typedef struct parse_rule_s ParseRule;
|
typedef struct parse_rule_s ParseRule;
|
||||||
|
|
||||||
#define MAX_SYMBOL_NAME_LENGTH 64
|
|
||||||
struct symbol_s {
|
|
||||||
char name[MAX_SYMBOL_NAME_LENGTH]; /* ptr to name */
|
|
||||||
u8 name_length; /* length of the name, max 64 */
|
|
||||||
SymbolType type; /* the type for this symbol */
|
|
||||||
SymbolType secondary_type; /* return type for functions/methods, or const if type/plex */
|
|
||||||
u32 ref; /* either constant value or pointer to other thing */
|
|
||||||
u32 size; /* either size of the plex or length of the array/list/etc. */
|
|
||||||
List *args; /* function params or plex constructor args */
|
|
||||||
List *fields; /* either plex variable fields, or method signatures */
|
|
||||||
};
|
|
||||||
|
|
||||||
struct scope_s {
|
struct scope_s {
|
||||||
Scope *parent; /* pointer to this scopes parent to "bubble up"*/
|
Scope *parent; /* pointer to this scopes parent to "bubble up"*/
|
||||||
List *symbols; /* list of symbols that live in this scope */
|
List *symbols; /* list of symbols that live in this scope */
|
||||||
|
|
@ -79,6 +42,6 @@ struct parser_s {
|
||||||
Token previous;
|
Token previous;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool compile(Emitter e, char *source);
|
bool compile(Arena *a, Emitter e, char *source);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
int i = 122;
|
||||||
|
int j = 32;
|
||||||
|
|
||||||
|
print((i - j)); // prints ascii `Z`
|
||||||
Loading…
Reference in New Issue