start adding error message support
This commit is contained in:
2
.gitmodules
vendored
2
.gitmodules
vendored
@@ -6,4 +6,4 @@
|
|||||||
url = https://github.com/likle/cwalk.git
|
url = https://github.com/likle/cwalk.git
|
||||||
[submodule "external/libdye"]
|
[submodule "external/libdye"]
|
||||||
path = external/libdye
|
path = external/libdye
|
||||||
url = https://github.com/kuzalekon/libdye.git
|
url = https://github.com/Ugric/libdye.git
|
||||||
|
|||||||
@@ -30,9 +30,10 @@ add_custom_command(
|
|||||||
add_custom_target(GenerateLexer DEPENDS ${LEXER_C} ${LEXER_H})
|
add_custom_target(GenerateLexer DEPENDS ${LEXER_C} ${LEXER_H})
|
||||||
|
|
||||||
# Step 3: Add executable
|
# Step 3: Add executable
|
||||||
add_executable(argon external/xxhash/xxhash.c external/cwalk/src/cwalk.c ${CFILES} ${LEXER_C})
|
add_executable(argon external/xxhash/xxhash.c external/cwalk/src/cwalk.c external/libdye/src/dye.c ${CFILES} ${LEXER_C})
|
||||||
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
|
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
|
||||||
target_include_directories(argon PRIVATE ${CMAKE_SOURCE_DIR}/external/cwalk/include)
|
target_include_directories(argon PRIVATE ${CMAKE_SOURCE_DIR}/external/cwalk/include)
|
||||||
|
target_include_directories(argon PRIVATE ${CMAKE_SOURCE_DIR}/external/libdye/include)
|
||||||
|
|
||||||
# Step 4: Build order
|
# Step 4: Build order
|
||||||
add_dependencies(argon GenerateLexer)
|
add_dependencies(argon GenerateLexer)
|
||||||
|
|||||||
4
Makefile
4
Makefile
@@ -2,8 +2,8 @@ LEXER_SRC = src/lexer/lex.l
|
|||||||
LEXER_C = src/lexer/lex.yy.c
|
LEXER_C = src/lexer/lex.yy.c
|
||||||
LEXER_H = src/lexer/lex.yy.h
|
LEXER_H = src/lexer/lex.yy.h
|
||||||
|
|
||||||
CFILES = external/xxhash/xxhash.c external/cwalk/src/cwalk.c $(shell find src -name '*.c')
|
CFILES = external/xxhash/xxhash.c external/cwalk/src/cwalk.c external/libdye/src/dye.c $(shell find src -name '*.c')
|
||||||
CFLAGS = $(ARCHFLAGS) -lm -lgc -lgmp -Wall -Wextra -Wno-unused-function -Iexternal/cwalk/include
|
CFLAGS = $(ARCHFLAGS) -lm -lgc -lgmp -Wall -Wextra -Wno-unused-function -Iexternal/cwalk/include -Iexternal/libdye/include
|
||||||
BINARY = bin/argon
|
BINARY = bin/argon
|
||||||
|
|
||||||
all: $(BINARY)
|
all: $(BINARY)
|
||||||
|
|||||||
2
external/libdye
vendored
2
external/libdye
vendored
Submodule external/libdye updated: da48196fff...c3fa048e65
52
src/arobject.h
Normal file
52
src/arobject.h
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
#ifndef AROBJECT_H
|
||||||
|
#define AROBJECT_H
|
||||||
|
|
||||||
|
#include <gmp.h>
|
||||||
|
#include "runtime/internals/dynamic_array_armem/darray_armem.h"
|
||||||
|
|
||||||
|
typedef struct ArgonObject ArgonObject; // forward declaration
|
||||||
|
|
||||||
|
typedef enum ArgonType {
|
||||||
|
TYPE_NULL,
|
||||||
|
TYPE_BOOL,
|
||||||
|
TYPE_NUMBER,
|
||||||
|
TYPE_STRING,
|
||||||
|
TYPE_FUNCTION,
|
||||||
|
TYPE_NATIVE_FUNCTION,
|
||||||
|
TYPE_OBJECT,
|
||||||
|
} ArgonType;
|
||||||
|
|
||||||
|
struct string_struct {
|
||||||
|
char *data;
|
||||||
|
size_t length;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct Stack {
|
||||||
|
ArgonObject *scope;
|
||||||
|
struct Stack *prev;
|
||||||
|
} Stack;
|
||||||
|
|
||||||
|
struct argon_function_struct {
|
||||||
|
darray_armem bytecode;
|
||||||
|
Stack stack;
|
||||||
|
size_t number_of_parameters;
|
||||||
|
char **parameters;
|
||||||
|
};
|
||||||
|
|
||||||
|
// full definition of ArgonObject (no typedef again!)
|
||||||
|
struct ArgonObject {
|
||||||
|
ArgonType type;
|
||||||
|
char *name;
|
||||||
|
ArgonObject *self;
|
||||||
|
ArgonObject *baseObject;
|
||||||
|
struct hashmap_GC *fields;
|
||||||
|
union {
|
||||||
|
mpq_t as_number;
|
||||||
|
bool as_bool;
|
||||||
|
struct string_struct as_str;
|
||||||
|
void *native_fn;
|
||||||
|
struct argon_function_struct argon_fn;
|
||||||
|
} value;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // AROBJECT_H
|
||||||
134
src/err.c
Normal file
134
src/err.c
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
#include "err.h"
|
||||||
|
#include "../external/libdye/include/dye.h"
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
const ArErr no_err = (ArErr){false};
|
||||||
|
|
||||||
|
ArErr create_err(int64_t line, int64_t column, int length, char *path,
|
||||||
|
const char *type, const char *fmt, ...) {
|
||||||
|
ArErr err;
|
||||||
|
err.exists = true;
|
||||||
|
err.path = path;
|
||||||
|
err.line = line;
|
||||||
|
err.column = column;
|
||||||
|
err.length = length;
|
||||||
|
|
||||||
|
// Copy error type safely
|
||||||
|
strncpy(err.type, type, sizeof(err.type) - 1);
|
||||||
|
err.type[sizeof(err.type) - 1] = '\0';
|
||||||
|
|
||||||
|
// Format error message
|
||||||
|
va_list args;
|
||||||
|
va_start(args, fmt);
|
||||||
|
vsnprintf(err.message, sizeof(err.message), fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
void output_err(ArErr err) {
|
||||||
|
if (!err.exists)
|
||||||
|
return;
|
||||||
|
dye(stderr, DYE_WHITE, DYE_RED);
|
||||||
|
fprintf(stderr, "ERROR!");
|
||||||
|
dye(stderr, DYE_RESET, DYE_RESET);
|
||||||
|
fprintf(stderr, " ");
|
||||||
|
dyefg(stderr, DYE_RED);
|
||||||
|
dye_style(stderr, DYE_STYLE_BOLD);
|
||||||
|
fprintf(stderr, "%s", err.type);
|
||||||
|
dye_style(stderr, DYE_STYLE_RESET);
|
||||||
|
dyefg(stderr, DYE_RESET);
|
||||||
|
fprintf(stderr, ": ");
|
||||||
|
dyefg(stderr, DYE_RED);
|
||||||
|
fprintf(stderr, "%s", err.message);
|
||||||
|
dye_style(stderr, DYE_STYLE_RESET);
|
||||||
|
dyefg(stderr, DYE_RESET);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
|
||||||
|
if (err.path && err.line) {
|
||||||
|
dyefg(stderr, DYE_GRAY);
|
||||||
|
fprintf(stderr, " --> ");
|
||||||
|
dyefg(stderr, DYE_CYAN);
|
||||||
|
fprintf(stderr, "%s", err.path);
|
||||||
|
dyefg(stderr, DYE_GRAY);
|
||||||
|
fprintf(stderr, ":");
|
||||||
|
dyefg(stderr, DYE_YELLOW);
|
||||||
|
fprintf(stderr, "%zu", err.line);
|
||||||
|
dyefg(stderr, DYE_GRAY);
|
||||||
|
fprintf(stderr, ":");
|
||||||
|
dyefg(stderr, DYE_YELLOW);
|
||||||
|
fprintf(stderr, "%zu", err.column);
|
||||||
|
dye_style(stderr, DYE_STYLE_RESET);
|
||||||
|
dyefg(stderr, DYE_RESET);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
FILE *file = fopen(err.path, "r");
|
||||||
|
if (file) {
|
||||||
|
dye_style(stderr, DYE_STYLE_RESET);
|
||||||
|
dyefg(stderr, DYE_RESET);
|
||||||
|
int line_number_width = snprintf(NULL, 0, "%zu", err.line);
|
||||||
|
char *buffer = NULL;
|
||||||
|
size_t size = 0;
|
||||||
|
int current_line = 1;
|
||||||
|
ssize_t len;
|
||||||
|
|
||||||
|
while ((len = getline(&buffer, &size, file)) != -1) {
|
||||||
|
if (current_line == err.line) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
current_line++;
|
||||||
|
}
|
||||||
|
fprintf(stderr, " ");
|
||||||
|
for (int i = 0; i < line_number_width; i++) {
|
||||||
|
fprintf(stderr, " ");
|
||||||
|
}
|
||||||
|
fprintf(stderr, "|\n");
|
||||||
|
getline(&buffer, &size, file);
|
||||||
|
|
||||||
|
char *line_starts = buffer;
|
||||||
|
while (*line_starts && isspace((unsigned char)*line_starts)) {
|
||||||
|
line_starts++;
|
||||||
|
err.column--;
|
||||||
|
}
|
||||||
|
fprintf(stderr, " %zu | ", err.line);
|
||||||
|
if (err.length) {
|
||||||
|
fprintf(stderr, "%.*s", (int)err.column - 1, line_starts);
|
||||||
|
dyefg(stderr, DYE_RED);
|
||||||
|
dye_style(stderr, DYE_STYLE_BOLD);
|
||||||
|
fprintf(stderr, "%.*s", err.length, line_starts + err.column - 1);
|
||||||
|
dye_style(stderr, DYE_STYLE_RESET);
|
||||||
|
dyefg(stderr, DYE_RESET);
|
||||||
|
fprintf(stderr, "%s", line_starts + (int)err.column + err.length - 1);
|
||||||
|
for (int64_t i = 0; i < err.column - 1; i++) {
|
||||||
|
fprintf(stderr, " ");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "%s", line_starts);
|
||||||
|
}
|
||||||
|
free(buffer);
|
||||||
|
fprintf(stderr, "\n ");
|
||||||
|
for (int i = 0; i < line_number_width; i++) {
|
||||||
|
fprintf(stderr, " ");
|
||||||
|
}
|
||||||
|
fprintf(stderr, "| ");
|
||||||
|
|
||||||
|
for (int i = 1; i < err.column; i++) {
|
||||||
|
fprintf(stderr, " ");
|
||||||
|
}
|
||||||
|
dyefg(stderr, DYE_RED);
|
||||||
|
dye_style(stderr, DYE_STYLE_BOLD);
|
||||||
|
for (int i = 0; i < err.length; i++) {
|
||||||
|
fprintf(stderr, "^");
|
||||||
|
}
|
||||||
|
dye_style(stderr, DYE_STYLE_RESET);
|
||||||
|
dyefg(stderr, DYE_RESET);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
7
src/err.h
Normal file
7
src/err.h
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#include "returnTypes.h"
|
||||||
|
|
||||||
|
extern const ArErr no_err;
|
||||||
|
|
||||||
|
ArErr create_err(int64_t line, int64_t column, int length, char *path, const char *type,
|
||||||
|
const char *fmt, ...);
|
||||||
|
void output_err(ArErr err);
|
||||||
@@ -3,8 +3,6 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
typedef struct ArgonObject ArgonObject;
|
|
||||||
|
|
||||||
typedef void (*free_val_func)(void *val);
|
typedef void (*free_val_func)(void *val);
|
||||||
|
|
||||||
struct node {
|
struct node {
|
||||||
|
|||||||
@@ -108,8 +108,6 @@ int yywrap(void * unused_param) {
|
|||||||
#[^\n]* { /* skip comment */ }
|
#[^\n]* { /* skip comment */ }
|
||||||
|
|
||||||
. {
|
. {
|
||||||
GET_STATE
|
return TOKEN_INVALID;
|
||||||
fprintf(stderr, "%s:%zu:%zu error: unexpected character '%s'\n", state->path, state->current_line+1, COLUMN_NO+1, yytext);
|
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
%%
|
%%
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
#include "lexer.h"
|
#include "lexer.h"
|
||||||
#include "lex.yy.h"
|
|
||||||
#include "../string/string.h"
|
#include "../string/string.h"
|
||||||
|
#include "lex.yy.h"
|
||||||
|
|
||||||
void lexer(LexerState state) {
|
ArErr lexer(LexerState state) {
|
||||||
size_t line = 1;
|
size_t line = 1;
|
||||||
size_t column = 1;
|
size_t column = 1;
|
||||||
int ch;
|
int ch;
|
||||||
@@ -32,13 +32,16 @@ void lexer(LexerState state) {
|
|||||||
|
|
||||||
int token;
|
int token;
|
||||||
while ((token = yylex(scanner)) != 0) {
|
while ((token = yylex(scanner)) != 0) {
|
||||||
Token token_struct = (Token){
|
if (token == TOKEN_INVALID) {
|
||||||
token,
|
ArErr err = create_err(state.current_line + 1, state.current_column + 1,
|
||||||
state.current_line+1,
|
yyget_leng(scanner), state.path, "Syntax Error",
|
||||||
state.current_column+1,
|
"Invalid Token '%s'", yyget_text(scanner));
|
||||||
yyget_leng(scanner),
|
yylex_destroy(scanner);
|
||||||
cloneString(yyget_text(scanner))
|
return err;
|
||||||
};
|
}
|
||||||
|
Token token_struct =
|
||||||
|
(Token){token, state.current_line + 1, state.current_column + 1,
|
||||||
|
yyget_leng(scanner), cloneString(yyget_text(scanner))};
|
||||||
darray_push(state.tokens, &token_struct);
|
darray_push(state.tokens, &token_struct);
|
||||||
if (token == TOKEN_NEW_LINE) {
|
if (token == TOKEN_NEW_LINE) {
|
||||||
state.current_line += 1;
|
state.current_line += 1;
|
||||||
@@ -48,4 +51,5 @@ void lexer(LexerState state) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
yylex_destroy(scanner);
|
yylex_destroy(scanner);
|
||||||
|
return no_err;
|
||||||
}
|
}
|
||||||
@@ -4,9 +4,10 @@
|
|||||||
#include "../dynamic_array/darray.h"
|
#include "../dynamic_array/darray.h"
|
||||||
#include "token.h"
|
#include "token.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include "../err.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const char *path;
|
char *path;
|
||||||
FILE *file;
|
FILE *file;
|
||||||
size_t current_line;
|
size_t current_line;
|
||||||
size_t current_column;
|
size_t current_column;
|
||||||
@@ -14,6 +15,6 @@ typedef struct {
|
|||||||
// add more fields as needed
|
// add more fields as needed
|
||||||
} LexerState;
|
} LexerState;
|
||||||
|
|
||||||
void lexer(LexerState state);
|
ArErr lexer(LexerState state);
|
||||||
|
|
||||||
#endif // LEXER_H
|
#endif // LEXER_H
|
||||||
@@ -72,6 +72,7 @@ typedef enum {
|
|||||||
TOKEN_COMMA,
|
TOKEN_COMMA,
|
||||||
TOKEN_COLON,
|
TOKEN_COLON,
|
||||||
TOKEN_EXCLAMATION,
|
TOKEN_EXCLAMATION,
|
||||||
|
TOKEN_INVALID,
|
||||||
} TokenType;
|
} TokenType;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|||||||
44
src/main.c
44
src/main.c
@@ -35,6 +35,7 @@
|
|||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
#include "err.h"
|
||||||
|
|
||||||
char *get_current_directory() {
|
char *get_current_directory() {
|
||||||
char *buffer = NULL;
|
char *buffer = NULL;
|
||||||
@@ -160,7 +161,7 @@ FAILED:
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ArgonObject *execute(char*absolute_path) {
|
Execution execute(char *absolute_path) {
|
||||||
clock_t start, end;
|
clock_t start, end;
|
||||||
double time_spent, total_time_spent = 0;
|
double time_spent, total_time_spent = 0;
|
||||||
|
|
||||||
@@ -168,7 +169,10 @@ ArgonObject *execute(char*absolute_path) {
|
|||||||
size_t basename_length;
|
size_t basename_length;
|
||||||
cwk_path_get_basename(absolute_path, &basename_ptr, &basename_length);
|
cwk_path_get_basename(absolute_path, &basename_ptr, &basename_length);
|
||||||
|
|
||||||
if (!basename_ptr) return NULL;
|
if (!basename_ptr)
|
||||||
|
return (Execution){create_err(0, 0 ,0 , NULL, "Path Error",
|
||||||
|
"path has no basename '%s'", absolute_path),
|
||||||
|
(Stack){NULL, NULL}};
|
||||||
|
|
||||||
char basename[FILENAME_MAX];
|
char basename[FILENAME_MAX];
|
||||||
memcpy(basename, basename_ptr, basename_length);
|
memcpy(basename, basename_ptr, basename_length);
|
||||||
@@ -181,15 +185,20 @@ ArgonObject *execute(char*absolute_path) {
|
|||||||
parent_directory[parent_directory_length] = '\0';
|
parent_directory[parent_directory_length] = '\0';
|
||||||
|
|
||||||
char cache_folder_path[FILENAME_MAX];
|
char cache_folder_path[FILENAME_MAX];
|
||||||
cwk_path_join(parent_directory, CACHE_FOLDER, cache_folder_path, sizeof(cache_folder_path));
|
cwk_path_join(parent_directory, CACHE_FOLDER, cache_folder_path,
|
||||||
|
sizeof(cache_folder_path));
|
||||||
|
|
||||||
char cache_file_path[FILENAME_MAX];
|
char cache_file_path[FILENAME_MAX];
|
||||||
cwk_path_join(cache_folder_path, basename, cache_file_path, sizeof(cache_file_path));
|
cwk_path_join(cache_folder_path, basename, cache_file_path,
|
||||||
cwk_path_change_extension(cache_file_path, BYTECODE_EXTENTION, cache_file_path, sizeof(cache_file_path));
|
sizeof(cache_file_path));
|
||||||
|
cwk_path_change_extension(cache_file_path, BYTECODE_EXTENTION,
|
||||||
|
cache_file_path, sizeof(cache_file_path));
|
||||||
|
|
||||||
FILE *file = fopen(absolute_path, "r");
|
FILE *file = fopen(absolute_path, "r");
|
||||||
if (!file) {
|
if (!file) {
|
||||||
return NULL;
|
return (Execution){create_err(0, 0, 0, NULL, "File Error", "Unable to open file '%s'",
|
||||||
|
absolute_path),
|
||||||
|
(Stack){NULL, NULL}};
|
||||||
}
|
}
|
||||||
|
|
||||||
XXH3_state_t *hash_state = XXH3_createState();
|
XXH3_state_t *hash_state = XXH3_createState();
|
||||||
@@ -215,7 +224,13 @@ ArgonObject *execute(char*absolute_path) {
|
|||||||
|
|
||||||
LexerState state = {absolute_path, file, 0, 0, &tokens};
|
LexerState state = {absolute_path, file, 0, 0, &tokens};
|
||||||
start = clock();
|
start = clock();
|
||||||
lexer(state);
|
ArErr err = lexer(state);
|
||||||
|
if (err.exists) {
|
||||||
|
free_translator(&translated);
|
||||||
|
darray_free(&tokens, free_token);
|
||||||
|
return (Execution){err,
|
||||||
|
(Stack){NULL, NULL}};
|
||||||
|
}
|
||||||
end = clock();
|
end = clock();
|
||||||
time_spent = (double)(end - start) / CLOCKS_PER_SEC;
|
time_spent = (double)(end - start) / CLOCKS_PER_SEC;
|
||||||
total_time_spent += time_spent;
|
total_time_spent += time_spent;
|
||||||
@@ -269,7 +284,8 @@ ArgonObject *execute(char*absolute_path) {
|
|||||||
|
|
||||||
start = clock();
|
start = clock();
|
||||||
RuntimeState state = init_runtime_state(translated);
|
RuntimeState state = init_runtime_state(translated);
|
||||||
ArgonObject *resp = runtime(translated,state);
|
Stack main_scope = create_scope(NULL);
|
||||||
|
ArErr err = runtime(translated, state, main_scope);
|
||||||
|
|
||||||
end = clock();
|
end = clock();
|
||||||
time_spent = (double)(end - start) / CLOCKS_PER_SEC;
|
time_spent = (double)(end - start) / CLOCKS_PER_SEC;
|
||||||
@@ -278,7 +294,7 @@ ArgonObject *execute(char*absolute_path) {
|
|||||||
printf("total time taken: %f seconds\n", total_time_spent);
|
printf("total time taken: %f seconds\n", total_time_spent);
|
||||||
|
|
||||||
free_translator(&translated);
|
free_translator(&translated);
|
||||||
return resp;
|
return (Execution){err, main_scope};
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
@@ -291,10 +307,12 @@ int main(int argc, char *argv[]) {
|
|||||||
return -1;
|
return -1;
|
||||||
char *path_non_absolute = argv[1];
|
char *path_non_absolute = argv[1];
|
||||||
char path[FILENAME_MAX];
|
char path[FILENAME_MAX];
|
||||||
cwk_path_get_absolute(CWD, path_non_absolute, path,
|
cwk_path_get_absolute(CWD, path_non_absolute, path, sizeof(path));
|
||||||
sizeof(path));
|
|
||||||
free(CWD);
|
free(CWD);
|
||||||
ArgonObject *resp = execute(path);
|
Execution resp = execute(path);
|
||||||
if (resp) return 0;
|
if (resp.err.exists){
|
||||||
|
output_err(resp.err);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
22
src/returnTypes.h
Normal file
22
src/returnTypes.h
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
#ifndef RETURN_TYPES_H
|
||||||
|
#define RETURN_TYPES_H
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "arobject.h"
|
||||||
|
|
||||||
|
#define ERR_MSG_MAX_LEN 256
|
||||||
|
|
||||||
|
typedef struct ArErr {
|
||||||
|
bool exists;
|
||||||
|
char *path;
|
||||||
|
int64_t line;
|
||||||
|
int64_t column;
|
||||||
|
int length;
|
||||||
|
char type[32];
|
||||||
|
char message[ERR_MSG_MAX_LEN];
|
||||||
|
} ArErr;
|
||||||
|
|
||||||
|
typedef struct Execution {
|
||||||
|
ArErr err;
|
||||||
|
Stack stack;
|
||||||
|
} Execution;
|
||||||
|
#endif // RETURN_TYPES_
|
||||||
@@ -3,8 +3,6 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
typedef struct ArgonObject ArgonObject;
|
|
||||||
|
|
||||||
struct node_GC {
|
struct node_GC {
|
||||||
uint64_t hash;
|
uint64_t hash;
|
||||||
void *key;
|
void *key;
|
||||||
|
|||||||
@@ -1,49 +1,11 @@
|
|||||||
#ifndef OBJECT_H
|
#ifndef OBJECT_H
|
||||||
#define OBJECT_H
|
#define OBJECT_H
|
||||||
#include "../internals/hashmap/hashmap.h"
|
#include "../internals/hashmap/hashmap.h"
|
||||||
#include "../internals/dynamic_array_armem/darray_armem.h"
|
|
||||||
#include <gmp.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include "../runtime.h"
|
#include "../runtime.h"
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
extern ArgonObject *BASE_CLASS;
|
extern ArgonObject *BASE_CLASS;
|
||||||
|
|
||||||
struct string_struct {
|
|
||||||
char *data;
|
|
||||||
size_t length;
|
|
||||||
};
|
|
||||||
struct argon_function_struct {
|
|
||||||
darray_armem bytecode;
|
|
||||||
struct Stack stack;
|
|
||||||
size_t number_of_parameters;
|
|
||||||
char** parameters;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
TYPE_NULL,
|
|
||||||
TYPE_BOOL,
|
|
||||||
TYPE_NUMBER,
|
|
||||||
TYPE_STRING,
|
|
||||||
TYPE_FUNCTION,
|
|
||||||
TYPE_NATIVE_FUNCTION,
|
|
||||||
TYPE_OBJECT, // generic user object
|
|
||||||
} ArgonType;
|
|
||||||
|
|
||||||
struct ArgonObject {
|
|
||||||
ArgonType type;
|
|
||||||
char* name;
|
|
||||||
ArgonObject *self;
|
|
||||||
ArgonObject *baseObject;
|
|
||||||
struct hashmap_GC *fields; // dynamic fields/methods
|
|
||||||
union {
|
|
||||||
mpq_t as_number;
|
|
||||||
bool as_bool;
|
|
||||||
struct string_struct as_str;
|
|
||||||
void *native_fn;
|
|
||||||
struct argon_function_struct argon_fn;
|
|
||||||
// others as needed
|
|
||||||
} value;
|
|
||||||
};
|
|
||||||
typedef struct ArgonObject ArgonObject;
|
typedef struct ArgonObject ArgonObject;
|
||||||
void init_base_field();
|
void init_base_field();
|
||||||
ArgonObject *init_child_argon_object(ArgonObject *cls);
|
ArgonObject *init_child_argon_object(ArgonObject *cls);
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#include "runtime.h"
|
#include "runtime.h"
|
||||||
|
#include "../err.h"
|
||||||
#include "../translator/translator.h"
|
#include "../translator/translator.h"
|
||||||
#include "objects/functions/functions.h"
|
#include "objects/functions/functions.h"
|
||||||
#include "objects/null/null.h"
|
#include "objects/null/null.h"
|
||||||
@@ -62,18 +63,6 @@ void load_const(Translated *translated, RuntimeState *state) {
|
|||||||
state->registers[to_register] = object;
|
state->registers[to_register] = object;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ArErr no_err = (ArErr){false};
|
|
||||||
|
|
||||||
ArErr create_err(char *path, int64_t line, char *type, char *message) {
|
|
||||||
return (ArErr){
|
|
||||||
false,
|
|
||||||
path,
|
|
||||||
line,
|
|
||||||
type,
|
|
||||||
message
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
ArErr run_instruction(Translated *translated, RuntimeState *state,
|
ArErr run_instruction(Translated *translated, RuntimeState *state,
|
||||||
struct Stack stack) {
|
struct Stack stack) {
|
||||||
OperationType opcode = pop_byte(translated, state);
|
OperationType opcode = pop_byte(translated, state);
|
||||||
@@ -88,24 +77,26 @@ ArErr create_err(char *path, int64_t line, char *type, char *message) {
|
|||||||
load_argon_function(translated, state, stack);
|
load_argon_function(translated, state, stack);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "bytecode invalid\n");
|
return create_err(0, 0, 0, NULL, "Runtime Error", "Invalid Opcode %#x", opcode);
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
}
|
||||||
return no_err;
|
return no_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
RuntimeState init_runtime_state(Translated translated) {
|
RuntimeState init_runtime_state(Translated translated) {
|
||||||
RuntimeState state = {
|
return (RuntimeState){
|
||||||
checked_malloc(translated.registerCount * sizeof(ArgonObject *)), 0};
|
checked_malloc(translated.registerCount * sizeof(ArgonObject *)), 0};
|
||||||
return state;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ArgonObject *runtime(Translated translated, RuntimeState state) {
|
Stack create_scope(Stack *prev) { return (Stack){NULL, prev}; }
|
||||||
struct Stack stack = {NULL, NULL};
|
|
||||||
|
ArErr runtime(Translated translated, RuntimeState state, Stack stack) {
|
||||||
state.head = 0;
|
state.head = 0;
|
||||||
while (state.head < translated.bytecode.size) {
|
while (state.head < translated.bytecode.size) {
|
||||||
run_instruction(&translated, &state, stack);
|
ArErr err = run_instruction(&translated, &state, stack);
|
||||||
|
if (err.exists) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
free(state.registers);
|
free(state.registers);
|
||||||
return stack.scope;
|
return no_err;
|
||||||
}
|
}
|
||||||
@@ -2,25 +2,13 @@
|
|||||||
#define RUNTIME_H
|
#define RUNTIME_H
|
||||||
#include "../translator/translator.h"
|
#include "../translator/translator.h"
|
||||||
#include "internals/hashmap/hashmap.h"
|
#include "internals/hashmap/hashmap.h"
|
||||||
|
#include "../returnTypes.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
ArgonObject **registers;
|
ArgonObject **registers;
|
||||||
size_t head;
|
size_t head;
|
||||||
} RuntimeState;
|
} RuntimeState;
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
bool exists;
|
|
||||||
char *path;
|
|
||||||
int64_t line;
|
|
||||||
char *type;
|
|
||||||
char *message;
|
|
||||||
} ArErr;
|
|
||||||
|
|
||||||
typedef struct Stack {
|
|
||||||
ArgonObject *scope;
|
|
||||||
struct Stack *prev;
|
|
||||||
} Stack;
|
|
||||||
|
|
||||||
void init_types();
|
void init_types();
|
||||||
|
|
||||||
uint64_t pop_bytecode(Translated *translated, RuntimeState *state);
|
uint64_t pop_bytecode(Translated *translated, RuntimeState *state);
|
||||||
@@ -30,6 +18,8 @@ ArErr run_instruction(Translated *translated, RuntimeState *state,
|
|||||||
|
|
||||||
RuntimeState init_runtime_state(Translated translated);
|
RuntimeState init_runtime_state(Translated translated);
|
||||||
|
|
||||||
ArgonObject *runtime(Translated translated, RuntimeState state);
|
Stack create_scope(Stack *prev);
|
||||||
|
|
||||||
|
ArErr runtime(Translated translated, RuntimeState state, Stack stack);
|
||||||
|
|
||||||
#endif // RUNTIME_H
|
#endif // RUNTIME_H
|
||||||
1
testing.ar
Normal file
1
testing.ar
Normal file
@@ -0,0 +1 @@
|
|||||||
|
10~10
|
||||||
Reference in New Issue
Block a user