forked from solstice/solstice
Compare commits
55 Commits
631b587d07
...
newvm
| Author | SHA1 | Date | |
|---|---|---|---|
| 668f13d176 | |||
| 02ecef4ce2 | |||
| e0869d526e | |||
| cba5ec1fa2 | |||
| 908af13d8f | |||
| 10046703ed | |||
| ebfd1d5045 | |||
| 1e0abcc0b4 | |||
| c7bd6e7766 | |||
| 68f5868538 | |||
| 692dd6b0db | |||
| 8087a8150e | |||
| 53908d29e2 | |||
| effad2920f | |||
| ac13b7a0ae | |||
| 8b40dbd563 | |||
| 0cf63b034f | |||
| ba6ec79a10 | |||
| f261a1cd0e | |||
| 00bf654882 | |||
| 591adf79a4 | |||
| c7d4a7700e | |||
| d0d1dc7465 | |||
| f8afa2f564 | |||
| 7a81a47986 | |||
| f127c2f5ab | |||
| 23041c041a | |||
| 0bb3741c66 | |||
| af97f1b712 | |||
| dfe37de5c0 | |||
| 5d9cb02e7e | |||
| 547488964a | |||
| f0692eb940 | |||
| 67ea6cc5fc | |||
| 36030f01a2 | |||
| f384e19c06 | |||
| d24462f844 | |||
| 4351821d30 | |||
| 78f974e189 | |||
| 1dedb30a87 | |||
| 2e7b5b7480 | |||
| 1cf995f7ac | |||
| 605d0a87b1 | |||
| 16569d7355 | |||
| fd08b7cdb7 | |||
| 5841a7a999 | |||
| a2fc138ba1 | |||
| 9b55b509f5 | |||
| f694f50d70 | |||
| 5b61a11f00 | |||
| 00d6ed83fb | |||
| 6988f314b0 | |||
| 70dc5eb5a0 | |||
| 1e3bd6c601 | |||
| f66464a7cc |
18
Makefile
18
Makefile
@@ -1,5 +1,9 @@
|
||||
CXX = gcc
|
||||
CXXFLAGS = -Wall -Wextra -pedantic -O3 -ggdb
|
||||
|
||||
GROUND_STATIC = /usr/local/lib/libgroundvm.a
|
||||
GROUND_INCLUDE = /usr/local/include/
|
||||
|
||||
CXXFLAGS = -I$(GROUND_INCLUDE) -Wall -Wextra -pedantic -O3 -ggdb
|
||||
LDFLAGS = -lgroundvm
|
||||
|
||||
BUILD_DIR = build
|
||||
@@ -10,7 +14,7 @@ PREFIX ?= /usr/local
|
||||
BINDIR = $(PREFIX)/bin
|
||||
LIBDIR = /usr/lib
|
||||
|
||||
SRCS = $(SRC_DIR)/main.c $(SRC_DIR)/codegen/SolsScope.c $(SRC_DIR)/codegen/codegen.c $(SRC_DIR)/lexer/SolsLiteral.c $(SRC_DIR)/lexer/SolsToken.c $(SRC_DIR)/lexer/SolsType.c $(SRC_DIR)/lexer/lexer.c $(SRC_DIR)/parser/SolsNode.c $(SRC_DIR)/parser/parser.c $(SRC_DIR)/typeparser/typeparser.c
|
||||
SRCS = $(SRC_DIR)/main.c $(SRC_DIR)/codegen/SolsScope.c $(SRC_DIR)/codegen/codegen.c $(SRC_DIR)/lexer/SolsLiteral.c $(SRC_DIR)/lexer/SolsToken.c $(SRC_DIR)/lexer/SolsType.c $(SRC_DIR)/lexer/lexer.c $(SRC_DIR)/parser/SolsNode.c $(SRC_DIR)/parser/parser.c $(SRC_DIR)/typeparser/typeparser.c $(SRC_DIR)/interactive/interactive.c
|
||||
OBJS = $(patsubst $(SRC_DIR)/%.c, $(BUILD_DIR)/%.o, $(SRCS))
|
||||
TARGET = solstice
|
||||
|
||||
@@ -29,6 +33,9 @@ install: $(TARGET)
|
||||
install -d $(LIBDIR)
|
||||
cp -r libs/* $(LIBDIR)/solstice
|
||||
|
||||
static: $(OBJS)
|
||||
$(CXX) $(OBJS) $(GROUND_STATIC) -o $(TARGET)
|
||||
|
||||
$(BUILD_DIR)/solstice.tar.gz: $(TARGET) $(LIBS_DIR)
|
||||
mkdir -p $(BUILD_DIR)/pkg/bin $(BUILD_DIR)/pkg/lib/
|
||||
cp $(TARGET) $(BUILD_DIR)/pkg/bin/solstice
|
||||
@@ -38,9 +45,12 @@ $(BUILD_DIR)/solstice.tar.gz: $(TARGET) $(LIBS_DIR)
|
||||
package: $(BUILD_DIR)/solstice.tar.gz
|
||||
|
||||
$(BUILD_DIR):
|
||||
mkdir -p $(BUILD_DIR) $(BUILD_DIR)/codegen $(BUILD_DIR)/lexer $(BUILD_DIR)/parser $(BUILD_DIR)/typeparser
|
||||
mkdir -p $(BUILD_DIR) $(BUILD_DIR)/codegen $(BUILD_DIR)/lexer $(BUILD_DIR)/parser $(BUILD_DIR)/typeparser $(BUILD_DIR)/interactive
|
||||
|
||||
clean:
|
||||
rm -rf $(BUILD_DIR) $(TARGET)
|
||||
|
||||
.PHONY: all clean
|
||||
run: $(TARGET)
|
||||
./$(TARGET)
|
||||
|
||||
.PHONY: all clean run
|
||||
|
||||
37
libs/collections.sols
Normal file
37
libs/collections.sols
Normal file
@@ -0,0 +1,37 @@
|
||||
struct List {
|
||||
protected size = 0
|
||||
protected capacity = 0
|
||||
protected memSize = 0
|
||||
|
||||
private ptr = 0
|
||||
|
||||
constructor(int length) {}
|
||||
|
||||
def append(int value) int {}
|
||||
def insert(int value, int index) int {}
|
||||
def remove(int index) int {}
|
||||
def at(int index) int {}
|
||||
def clear() int {}
|
||||
def set(int value, int index) int {}
|
||||
def isEmpty() bool {}
|
||||
def contains(int value) bool {}
|
||||
def reverse() int {}
|
||||
def find(int value) int {}
|
||||
def reserve(int n) int {}
|
||||
}
|
||||
|
||||
struct Hashmap {
|
||||
private ptr = 0
|
||||
|
||||
constructor() {}
|
||||
|
||||
def set(string key, int value) int {}
|
||||
def get(string key) int {}
|
||||
def getOr(string key, int fallback) int {}
|
||||
def remove(string key) int {}
|
||||
def removeIfPresent(string key) bool {}
|
||||
}
|
||||
|
||||
ground {
|
||||
extern "collections"
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
def stringToInt(string in) int {
|
||||
result = 0
|
||||
ground {
|
||||
stoi $in &result
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
def intToString(int in) string {
|
||||
result = ""
|
||||
ground {
|
||||
tostring $in &result
|
||||
}
|
||||
return result
|
||||
}
|
||||
@@ -1,5 +1,18 @@
|
||||
def file_Read(string file) string {}
|
||||
def file_Write(string file, string content) {}
|
||||
struct File {
|
||||
private fileHandle = 0
|
||||
protected filePath = ""
|
||||
protected size = 0
|
||||
protected tell = 0
|
||||
|
||||
constructor (string filePath) {}
|
||||
|
||||
def read() string {}
|
||||
def write(string buffer) int {}
|
||||
def append(string buffer) int {}
|
||||
def flush() int {}
|
||||
def seek(int offset) int {}
|
||||
def seekEnd(int offset) int {}
|
||||
}
|
||||
|
||||
ground {
|
||||
extern "fileio"
|
||||
|
||||
28
libs/strings.sols
Normal file
28
libs/strings.sols
Normal file
@@ -0,0 +1,28 @@
|
||||
def string_CharAt(string str, int index) string {}
|
||||
|
||||
def string_Upper(string str) string {}
|
||||
def string_Lower(string str) string {}
|
||||
def string_Trim(string str) string {}
|
||||
def string_TrimLeft(string str) string {}
|
||||
def string_TrimRight(string str) string {}
|
||||
def string_Substring(string str, int start, int end) string {}
|
||||
def string_Repeat(string str, int times) string {}
|
||||
def string_Replace(string haystack, string needle) string {}
|
||||
def string_Reverse(string str) string {}
|
||||
|
||||
def string_StartsWith(string str, string prefix) bool {}
|
||||
def string_EndsWith(string str, string suffix) bool {}
|
||||
def string_Contains(string haystack, string needle) bool {}
|
||||
|
||||
def string_Find(string haystack, string needle) int {}
|
||||
def string_FindLast(string haystack, string needle) int {}
|
||||
def string_Count(string haystack, string needle) int {}
|
||||
|
||||
def string_isAlpha(string str) bool {}
|
||||
def string_isAlnum(string str) bool {}
|
||||
def string_isDigit(string str) bool {}
|
||||
def string_isSpace(string str) bool {}
|
||||
|
||||
ground {
|
||||
extern "string"
|
||||
}
|
||||
@@ -9,7 +9,13 @@ void addVariableToScope(SolsScope* scope, const char* name, SolsType type) {
|
||||
strncpy(s->id, name, sizeof(s->id) - 1);
|
||||
s->id[sizeof(s->id) - 1] = '\0';
|
||||
|
||||
s->typeinfo = type;
|
||||
s->typeinfo = ({
|
||||
ResultType(SolsType, charptr) _result = copySolsType(&type);
|
||||
if (_result.error) {
|
||||
return;
|
||||
}
|
||||
_result.as.success;
|
||||
});
|
||||
|
||||
HASH_ADD_STR(scope->variables, id, s);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
71
src/include/list.h
Normal file
71
src/include/list.h
Normal file
@@ -0,0 +1,71 @@
|
||||
// list.h - create a list of any kind in C
|
||||
// append, pop, safely retrieve
|
||||
// licenced to you under the MIT license
|
||||
// example:
|
||||
//
|
||||
// #include "list.h"
|
||||
//
|
||||
// UseList(int);
|
||||
//
|
||||
// int main() {
|
||||
// List(int) myList = newList(int);
|
||||
// append(myList, 32);
|
||||
// printf("%d\n", *get(myList, 0));
|
||||
// pop(myList);
|
||||
// destroy(myList);
|
||||
// }
|
||||
//
|
||||
#ifndef LIST_H
|
||||
#define LIST_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define LIST_H_INIT_CAPACITY 32
|
||||
|
||||
#define UseList(type) struct __List_##type { type* pointer; size_t count; size_t capacity; size_t itemsize; }
|
||||
#define List(type) struct __List_##type
|
||||
|
||||
#define newList(type) ({ \
|
||||
List(type) __list_tmp = { .pointer = malloc(sizeof(type) * LIST_H_INIT_CAPACITY), .count = 0, .capacity = LIST_H_INIT_CAPACITY, .itemsize = sizeof(type) };\
|
||||
if (__list_tmp.pointer == NULL) { \
|
||||
printf("list.h:32 (newList(type)) - failed to allocate memory"); exit(1);\
|
||||
}\
|
||||
__list_tmp;\
|
||||
})
|
||||
|
||||
#define append(list, item) {\
|
||||
if (list.pointer == NULL) {\
|
||||
printf("list.h:39 (append(list, item)) - list pointer is null (perhaps you accidently destroyed the list?)"); exit(1);\
|
||||
}\
|
||||
if (list.capacity < list.count + 1) {\
|
||||
list.capacity *= 2;\
|
||||
void* __tmp_ptr = realloc(list.pointer, list.capacity * list.itemsize);\
|
||||
if (__tmp_ptr == NULL) {\
|
||||
printf("list.h:45 (append(list, item)) - failed to allocate memory"); exit(1);\
|
||||
}\
|
||||
list.pointer = __tmp_ptr;\
|
||||
}\
|
||||
list.pointer[list.count] = item;\
|
||||
list.count++;\
|
||||
}
|
||||
|
||||
#define get(list, idx) ({\
|
||||
if (list.pointer == NULL) {\
|
||||
printf("list.h:55 (get(list, idx)) - list pointer is null (perhaps you accidently destroyed the list?)"); exit(1);\
|
||||
}\
|
||||
(idx >= list.count) ? NULL : &list.pointer[idx];\
|
||||
})
|
||||
|
||||
#define pop(list) {\
|
||||
if (list.pointer == NULL) {\
|
||||
printf("list.h:65 (pop(list)) - list pointer is null (perhaps you accidently destroyed the list?)"); exit(1);\
|
||||
}\
|
||||
if (list.count > 0) list.count--;\
|
||||
}
|
||||
|
||||
#define destroy(list) if (list.pointer != NULL) {\
|
||||
free(list.pointer); list.pointer = NULL; \
|
||||
}
|
||||
|
||||
#endif
|
||||
77
src/interactive/interactive.c
Normal file
77
src/interactive/interactive.c
Normal file
@@ -0,0 +1,77 @@
|
||||
#include "interactive.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
Interactive createInteractive() {
|
||||
return (Interactive) {
|
||||
.callbacks.at = malloc(sizeof(InteractiveCallback) * 16),
|
||||
.callbacks.capacity = 16,
|
||||
.callbacks.size = 0
|
||||
};
|
||||
}
|
||||
|
||||
void addCallback(Interactive* interactive, int (*function)(size_t, char**, void*), char* name) {
|
||||
if (interactive->callbacks.size + 1 >= interactive->callbacks.capacity) {
|
||||
interactive->callbacks.at = realloc(interactive->callbacks.at, (interactive->callbacks.capacity * 2) * sizeof(InteractiveCallback));
|
||||
interactive->callbacks.capacity *= 2;
|
||||
}
|
||||
|
||||
interactive->callbacks.at[interactive->callbacks.size].function = function;
|
||||
interactive->callbacks.at[interactive->callbacks.size].name = name;
|
||||
interactive->callbacks.size++;
|
||||
|
||||
}
|
||||
|
||||
typedef struct InteractiveCommand {
|
||||
char* command;
|
||||
size_t argc;
|
||||
size_t capacity;
|
||||
char** argv;
|
||||
} InteractiveCommand;
|
||||
|
||||
static inline InteractiveCommand parseInteractiveCommand(char* input) {
|
||||
InteractiveCommand command = {
|
||||
.command = malloc(sizeof(char*) * 16),
|
||||
.argc = 0,
|
||||
.capacity = 16,
|
||||
.argv = malloc(sizeof(char*) * 16)
|
||||
};
|
||||
for (size_t i = 0; i < command.capacity; i++) {
|
||||
command.argv[i] = malloc(sizeof(char) * 64);
|
||||
}
|
||||
size_t len = strlen(input);
|
||||
char** currentBuf = &command.command;
|
||||
size_t currentLen = 0;
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
if (input[i] == '\n') break;
|
||||
if (input[i] == ' ' || currentLen == 63) {
|
||||
if (command.argc + 1 >= command.capacity) {
|
||||
command.capacity *= 2;
|
||||
command.argv = realloc(command.argv, command.capacity * sizeof(char**));
|
||||
}
|
||||
currentBuf = &command.argv[command.argc];
|
||||
command.argc++;
|
||||
} else {
|
||||
currentBuf[currentLen][i] = input[i];
|
||||
}
|
||||
}
|
||||
return command;
|
||||
}
|
||||
|
||||
void runInteractive(Interactive* interactive, void* ctx) {
|
||||
for (;;) {
|
||||
char buf[512];
|
||||
printf("> ");
|
||||
fgets(buf, sizeof(buf), stdin);
|
||||
InteractiveCommand command = parseInteractiveCommand(buf);
|
||||
if (strcmp(command.command, "exit") == 0) {
|
||||
break;
|
||||
}
|
||||
for (size_t i = 0; i < interactive->callbacks.size; i++) {
|
||||
if (strcmp(command.command, interactive->callbacks.at[i].name) == 0) {
|
||||
interactive->callbacks.at[i].function(command.argc, command.argv, ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
26
src/interactive/interactive.h
Normal file
26
src/interactive/interactive.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#ifndef INTERACTIVE_H
|
||||
#define INTERACTIVE_H
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
// Callback functions are of the form
|
||||
// int callback(int argc, char** argv, void* ctx)
|
||||
|
||||
typedef struct InteractiveCallback {
|
||||
int (*function)(size_t, char**, void*);
|
||||
char* name;
|
||||
} InteractiveCallback;
|
||||
|
||||
typedef struct Interactive {
|
||||
struct {
|
||||
InteractiveCallback* at;
|
||||
size_t size;
|
||||
size_t capacity;
|
||||
} callbacks;
|
||||
} Interactive;
|
||||
|
||||
Interactive createInteractive();
|
||||
void addCallback(Interactive* interactive, int (*function)(size_t, char**, void*), char* name);
|
||||
void runInteractive(Interactive* interactive, void* ctx);
|
||||
|
||||
#endif
|
||||
@@ -1,31 +1,33 @@
|
||||
#include "SolsLiteral.h"
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
|
||||
ResultType(SolsLiteral, charptr) createSolsLiteral(SolsLiteralType type, ...) {
|
||||
ResultType(SolsLiteral, charptr) createSolsLiteral(SolsTypeType type, ...) {
|
||||
va_list args;
|
||||
va_start(args, type);
|
||||
SolsLiteral literal = {
|
||||
.type = type
|
||||
};
|
||||
switch (type) {
|
||||
case SLT_INT: {
|
||||
case STT_INT: {
|
||||
literal.as.intv = va_arg(args, int64_t);
|
||||
break;
|
||||
}
|
||||
case SLT_DOUBLE: {
|
||||
case STT_DOUBLE: {
|
||||
literal.as.doublev = va_arg(args, double);
|
||||
break;
|
||||
}
|
||||
case SLT_BOOL: {
|
||||
case STT_BOOL: {
|
||||
literal.as.boolv = (bool) va_arg(args, int);
|
||||
break;
|
||||
}
|
||||
case SLT_CHAR: {
|
||||
case STT_CHAR: {
|
||||
literal.as.charv = (char) va_arg(args, int);
|
||||
break;
|
||||
}
|
||||
case SLT_STRING: {
|
||||
case STT_STRING: {
|
||||
char* input = va_arg(args, char*);
|
||||
if (input == NULL) {
|
||||
va_end(args);
|
||||
@@ -39,13 +41,44 @@ ResultType(SolsLiteral, charptr) createSolsLiteral(SolsLiteralType type, ...) {
|
||||
strcpy(literal.as.stringv, input);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
return Error(SolsLiteral, charptr, "Cannot create literal of specified type");
|
||||
}
|
||||
}
|
||||
va_end(args);
|
||||
return Success(SolsLiteral, charptr, literal);
|
||||
}
|
||||
|
||||
void freeSolsLiteral(SolsLiteral* lit) {
|
||||
if (lit->type == SLT_STRING && lit->as.stringv != NULL) {
|
||||
if (lit->type == STT_STRING && lit->as.stringv != NULL) {
|
||||
free(lit->as.stringv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void printSolsLiteral(SolsLiteral* lit) {
|
||||
switch (lit->type) {
|
||||
case STT_INT: {
|
||||
printf("%" PRId64, lit->as.intv);
|
||||
break;
|
||||
}
|
||||
case STT_DOUBLE: {
|
||||
printf("%f", lit->as.doublev);
|
||||
break;
|
||||
}
|
||||
case STT_STRING: {
|
||||
printf("%s", lit->as.stringv);
|
||||
break;
|
||||
}
|
||||
case STT_BOOL: {
|
||||
printf(lit->as.boolv ? "true" : "false");
|
||||
break;
|
||||
}
|
||||
case STT_CHAR: {
|
||||
printf("%c", lit->as.charv);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
#include <inttypes.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "SolsType.h"
|
||||
|
||||
#include "../include/error.h"
|
||||
#include "../include/nothing.h"
|
||||
|
||||
@@ -16,7 +18,7 @@ typedef enum SolsLiteralType {
|
||||
// Stores literal values which will be added to the Ground code.
|
||||
// Not much explaining needed here.
|
||||
typedef struct SolsLiteral {
|
||||
SolsLiteralType type;
|
||||
SolsTypeType type;
|
||||
union {
|
||||
int64_t intv;
|
||||
char* stringv;
|
||||
@@ -38,9 +40,12 @@ Result(SolsLiteral, charptr);
|
||||
// An error will only be returned if there is an issue copying a provided char*.
|
||||
// There is no way to detect incorrectly provided types, so ensure that the right type
|
||||
// is provided!!!!
|
||||
ResultType(SolsLiteral, charptr) createSolsLiteral(SolsLiteralType type, ...);
|
||||
ResultType(SolsLiteral, charptr) createSolsLiteral(SolsTypeType type, ...);
|
||||
|
||||
// Frees a SolsLiteral. Primarily concerned with freeing .as.stringv
|
||||
void freeSolsLiteral(SolsLiteral* lit);
|
||||
|
||||
// Prints a SolsLiteral
|
||||
void printSolsLiteral(SolsLiteral* lit);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -10,7 +10,20 @@
|
||||
#include "SolsLiteral.h"
|
||||
|
||||
typedef enum SolsTokenType {
|
||||
STT_IDENTIFIER, STT_LITERAL, STT_TYPE, STT_DOT, STT_OPEN_CURLY, STT_CLOSE_CURLY, STT_OPEN_PAREN, STT_CLOSE_PAREN, STT_OP_ADD, STT_OP_SUB, STT_OP_MUL, STT_OP_DIV, STT_OP_ADDTO, STT_OP_SUBTO, STT_OP_MULTO, STT_OP_DIVTO, STT_OP_INCREMENT, STT_OP_DECREMENT, STT_OP_SET, STT_OP_GREATER, STT_OP_LESSER, STT_OP_EQUAL, STT_OP_INEQUAL, STT_OP_EQGREATER, STT_OP_EQLESSER, STT_KW_DEF, STT_KW_LAMBDA, STT_KW_RETURN, STT_KW_USE, STT_KW_STRUCT, STT_KW_PUTS, STT_KW_IF, STT_KW_WHILE, STT_KW_NEW, STT_KW_GROUND, STT_LINE_END, STT_COMMA
|
||||
STT_IDENTIFIER, STT_LITERAL, STT_TYPE, STT_DOT,
|
||||
STT_OPEN_CURLY, STT_CLOSE_CURLY, STT_OPEN_PAREN, STT_CLOSE_PAREN,
|
||||
STT_OP_ADD, STT_OP_SUB, STT_OP_MUL, STT_OP_DIV,
|
||||
STT_OP_ADDTO, STT_OP_SUBTO, STT_OP_MULTO, STT_OP_DIVTO,
|
||||
STT_OP_INCREMENT, STT_OP_DECREMENT, STT_OP_SET,
|
||||
STT_OP_GREATER, STT_OP_LESSER, STT_OP_EQUAL, STT_OP_INEQUAL, STT_OP_EQGREATER, STT_OP_EQLESSER,
|
||||
STT_KW_DEF, STT_KW_LAMBDA, STT_KW_RETURN,
|
||||
STT_KW_USE, STT_KW_STRUCT, STT_KW_ENUM, STT_KW_CONSTRUCTOR, STT_KW_DESTRUCTOR, STT_KW_DUPLICATOR,
|
||||
STT_KW_AS, STT_KW_SIZEOF,
|
||||
STT_KW_PRIVATE, STT_KW_PROTECTED,
|
||||
STT_KW_PUTS, STT_KW_IF, STT_KW_WHILE,
|
||||
STT_KW_NEW, STT_KW_GROUND, STT_LINE_END, STT_COMMA,
|
||||
STT_OPEN_SQUARE, STT_CLOSE_SQUARE,
|
||||
STT_KW_PRAGMA,
|
||||
} SolsTokenType;
|
||||
|
||||
typedef char* charptr;
|
||||
@@ -57,7 +70,7 @@ void freeSolsToken(SolsToken* token);
|
||||
|
||||
// Represents a Solstice program, seperated into tokens.
|
||||
// .at is a pointer to the tokens
|
||||
// .count is how many tokens are currently being stored
|
||||
// .count is how many tokens are currently being stored
|
||||
// .capacity is how many tokens worth of memory is allocated
|
||||
typedef struct SolsTokens {
|
||||
SolsToken* at;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#include "SolsType.h"
|
||||
#include "lexer.h"
|
||||
#include "../include/error.h"
|
||||
#include "../include/estr.h"
|
||||
#include <groundvm.h>
|
||||
@@ -10,10 +9,116 @@ ResultType(SolsType, charptr) createSolsType(SolsTypeType in) {
|
||||
if (ptr == NULL) {
|
||||
return Error(SolsType, charptr, "Couldn't allocate memory (in createSolsType() function)");
|
||||
}
|
||||
SolsType type = { .type = in, .children.capacity = 32, .children.at = ptr };
|
||||
SolsType type = {
|
||||
.type = in == STT_GENERIC ? STT_TEMPLATE : in,
|
||||
.identifierType = NULL,
|
||||
.returnType = NULL,
|
||||
.children.capacity = 32,
|
||||
.children.count = 0,
|
||||
.children.at = ptr,
|
||||
.typeIsKnown = true,
|
||||
.needsGroundStruct = false,
|
||||
.metadata.isPrivate = false,
|
||||
.metadata.isProtected = false,
|
||||
.metadata.isEnum = false,
|
||||
.metadata.isGenericField = in == STT_GENERIC,
|
||||
.metadata.isGenericStruct = false,
|
||||
.metadata.genericStructNode = NULL
|
||||
};
|
||||
return Success(SolsType, charptr, type);
|
||||
}
|
||||
|
||||
ResultType(SolsType, charptr) createIdentifiedSolsType(char* in) {
|
||||
char* copy = malloc(strlen(in) + 1);
|
||||
if (copy == NULL) {
|
||||
return Error(SolsType, charptr, "Couldn't allocate memory (in createIdentifiedSolsType() function)");
|
||||
}
|
||||
strcpy(copy, in);
|
||||
return Success(SolsType, charptr, ((SolsType) {
|
||||
.type = STT_UNKNOWN,
|
||||
.identifierType = copy,
|
||||
.returnType = NULL,
|
||||
.children.capacity = 0,
|
||||
.children.count = 0,
|
||||
.children.at = NULL,
|
||||
.typeIsKnown = false,
|
||||
.needsGroundStruct = false,
|
||||
.metadata.isPrivate = false,
|
||||
.metadata.isProtected = false,
|
||||
.metadata.isEnum = false,
|
||||
.metadata.isGenericField = false,
|
||||
.metadata.isGenericStruct = false,
|
||||
.metadata.genericStructNode = NULL
|
||||
}));
|
||||
}
|
||||
|
||||
ResultType(SolsType, charptr) copySolsType(SolsType* type) {
|
||||
SolsType ret = {
|
||||
.type = type->type,
|
||||
.identifierType = NULL,
|
||||
.typeIsKnown = type->typeIsKnown,
|
||||
.needsGroundStruct = type->needsGroundStruct,
|
||||
.returnType = NULL,
|
||||
.children.count = type->children.count,
|
||||
.children.capacity = type->children.capacity,
|
||||
.children.at = NULL,
|
||||
.metadata = type->metadata
|
||||
};
|
||||
|
||||
if (type->identifierType != NULL) {
|
||||
ret.identifierType = malloc(strlen(type->identifierType) + 1);
|
||||
if (ret.identifierType == NULL) {
|
||||
return Error(SolsType, charptr, "Couldn't allocate memory (in copySolsType() function)");
|
||||
}
|
||||
strcpy(ret.identifierType, type->identifierType);
|
||||
}
|
||||
|
||||
if (type->returnType != NULL && type->returnType->type != STT_NONE) {
|
||||
ResultType(SolsType, charptr) copiedReturn = copySolsType(type->returnType);
|
||||
if (copiedReturn.error) {
|
||||
Estr err = CREATE_ESTR(copiedReturn.as.error);
|
||||
APPEND_ESTR(err, " (in copySolsType() function)");
|
||||
return Error(SolsType, charptr, err.str);
|
||||
}
|
||||
|
||||
ret.returnType = malloc(sizeof(SolsType));
|
||||
if (ret.returnType == NULL) {
|
||||
return Error(SolsType, charptr, "Couldn't allocate memory (in copySolsType() function)");
|
||||
}
|
||||
*ret.returnType = copiedReturn.as.success;
|
||||
}
|
||||
|
||||
if (type->children.capacity > 0) {
|
||||
SolsTypeField* ptr = malloc(sizeof(SolsTypeField) * type->children.capacity);
|
||||
if (ptr == NULL) {
|
||||
return Error(SolsType, charptr, "Couldn't allocate memory (in copySolsType() function)");
|
||||
}
|
||||
ret.children.at = ptr;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < type->children.count; i++) {
|
||||
ResultType(SolsType, charptr) copied = copySolsType(&type->children.at[i].type);
|
||||
if (copied.error) {
|
||||
Estr err = CREATE_ESTR(copied.as.error);
|
||||
APPEND_ESTR(err, " (in copySolsType() function)");
|
||||
return Error(SolsType, charptr, err.str);
|
||||
}
|
||||
ret.children.at[i].type = copied.as.success;
|
||||
|
||||
if (type->children.at[i].name == NULL) {
|
||||
ret.children.at[i].name = NULL;
|
||||
} else {
|
||||
ret.children.at[i].name = malloc(strlen(type->children.at[i].name) + 1);
|
||||
if (ret.children.at[i].name == NULL) {
|
||||
return Error(SolsType, charptr, "Couldn't allocate memory (in copySolsType() function)");
|
||||
}
|
||||
strcpy(ret.children.at[i].name, type->children.at[i].name);
|
||||
}
|
||||
}
|
||||
|
||||
return Success(SolsType, charptr, ret);
|
||||
}
|
||||
/*
|
||||
ResultType(SolsType, charptr) copySolsType(SolsType* type) {
|
||||
SolsType ret = { .type = type->type, .children.count = type->children.count, .children.capacity = type->children.capacity};
|
||||
|
||||
@@ -48,6 +153,7 @@ ResultType(SolsType, charptr) copySolsType(SolsType* type) {
|
||||
}
|
||||
return Success(SolsType, charptr, ret);
|
||||
}
|
||||
*/
|
||||
|
||||
ResultType(Nothing, charptr) addChildToSolsType(SolsType* type, SolsType child, const char* name) {
|
||||
if (type->children.capacity < type->children.count + 1) {
|
||||
@@ -144,7 +250,7 @@ bool compareTypes(SolsType* left, SolsType* right) {
|
||||
}
|
||||
}
|
||||
|
||||
ResultType(GroundArg, charptr) createGroundArgFromSolsType(SolsType* type) {
|
||||
ResultType(GroundArg, charptr) createGroundArgFromSolsType(SolsType* type, struct SolsScope* scope) {
|
||||
switch (type->type) {
|
||||
case STT_INT: {
|
||||
return Success(GroundArg, charptr, groundCreateReference(TYPEREF, "int"));
|
||||
@@ -168,9 +274,89 @@ ResultType(GroundArg, charptr) createGroundArgFromSolsType(SolsType* type) {
|
||||
return Success(GroundArg, charptr, groundCreateReference(TYPEREF, "struct"));
|
||||
}
|
||||
case STT_OBJECT: {
|
||||
// FIXME Do this later
|
||||
return Error(GroundArg, charptr, "FIXME");
|
||||
if (!type->needsGroundStruct) {
|
||||
return Success(GroundArg, charptr, groundCreateReference(TYPEREF, type->identifierType));
|
||||
} else {
|
||||
// FIXME do this later
|
||||
return Error(GroundArg, charptr, "Anonymous structs are not supported yet");
|
||||
}
|
||||
}
|
||||
case STT_UNKNOWN: {
|
||||
if (!type->needsGroundStruct) {
|
||||
return Success(GroundArg, charptr, groundCreateReference(TYPEREF, type->identifierType));
|
||||
} else {
|
||||
// FIXME do this later
|
||||
return Error(GroundArg, charptr, "Anonymous structs are not supported yet");
|
||||
}
|
||||
}
|
||||
case STT_NONE: {
|
||||
return Success(GroundArg, charptr, groundCreateReference(TYPEREF, "none"));
|
||||
}
|
||||
}
|
||||
return Error(GroundArg, charptr, "How did we get here?");
|
||||
}
|
||||
|
||||
ResultType(SolsType, charptr) findStructMemberType(SolsType* type, char* member) {
|
||||
for (size_t i = 0; i < type->children.count; i++) {
|
||||
if (strcmp(type->children.at[i].name, member) == 0) {
|
||||
return Success(SolsType, charptr, type->children.at[i].type);
|
||||
}
|
||||
}
|
||||
return Error(SolsType, charptr, "Could not find member");
|
||||
}
|
||||
|
||||
void printSolsType(SolsType* type) {
|
||||
printf("Type: ");
|
||||
switch (type->type) {
|
||||
case STT_INT:
|
||||
printf("int");
|
||||
break;
|
||||
case STT_DOUBLE:
|
||||
printf("double");
|
||||
break;
|
||||
case STT_STRING:
|
||||
printf("string");
|
||||
break;
|
||||
case STT_BOOL:
|
||||
printf("bool");
|
||||
break;
|
||||
case STT_CHAR:
|
||||
printf("char");
|
||||
break;
|
||||
case STT_FUN:
|
||||
printf("fun");
|
||||
break;
|
||||
case STT_TEMPLATE:
|
||||
printf("template");
|
||||
break;
|
||||
case STT_OBJECT:
|
||||
printf("object");
|
||||
break;
|
||||
case STT_UNKNOWN:
|
||||
printf("(unknown)");
|
||||
break;
|
||||
case STT_NONE:
|
||||
printf("(none)");
|
||||
break;
|
||||
case STT_GENERIC:
|
||||
printf("(generic");
|
||||
break;
|
||||
}
|
||||
|
||||
if (type->returnType != NULL) {
|
||||
printf("\nReturn type: ");
|
||||
printSolsType(type->returnType);
|
||||
}
|
||||
|
||||
if (type->children.count > 0) {
|
||||
printf("\nChildren {");
|
||||
for (size_t i = 0; i < type->children.count; i++) {
|
||||
if (type->children.at[i].name != NULL) {
|
||||
printf("\nName: %s", type->children.at[i].name);
|
||||
}
|
||||
printf("\nType: ");
|
||||
printSolsType(&type->children.at[i].type);
|
||||
}
|
||||
printf("}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,13 +8,14 @@
|
||||
#include "../include/nothing.h"
|
||||
|
||||
typedef enum SolsTypeType {
|
||||
STT_INT, STT_STRING, STT_DOUBLE, STT_BOOL, STT_CHAR, STT_FUN, STT_TEMPLATE, STT_OBJECT
|
||||
STT_INT, STT_STRING, STT_DOUBLE, STT_BOOL, STT_CHAR, STT_FUN, STT_TEMPLATE, STT_OBJECT, STT_UNKNOWN, STT_GENERIC, STT_NONE
|
||||
} SolsTypeType;
|
||||
|
||||
// Definition of charptr for Result() and ResultType() macros
|
||||
typedef char* charptr;
|
||||
|
||||
struct SolsTypeField;
|
||||
struct SolsNode; // for generic struct
|
||||
|
||||
// Holds type information for a struct, object or function.
|
||||
// Say, for example, your type signature looks like this:
|
||||
@@ -53,6 +54,12 @@ typedef struct SolsType {
|
||||
// For use when type is identified with a name
|
||||
char* identifierType;
|
||||
|
||||
// If type is identified with a name, record whether we have found the actual type
|
||||
bool typeIsKnown;
|
||||
|
||||
// If using anonymous struct, record whether we need to generate a Ground struct
|
||||
bool needsGroundStruct;
|
||||
|
||||
// For use in functions
|
||||
struct SolsType* returnType;
|
||||
|
||||
@@ -62,6 +69,18 @@ typedef struct SolsType {
|
||||
size_t count;
|
||||
size_t capacity;
|
||||
} children;
|
||||
|
||||
struct {
|
||||
bool isPrivate;
|
||||
bool isProtected;
|
||||
bool isEnum;
|
||||
bool isGenericField;
|
||||
bool isGenericStruct;
|
||||
|
||||
// For use by generic struct
|
||||
// We will codegen this where required
|
||||
struct SolsNode* genericStructNode;
|
||||
} metadata;
|
||||
} SolsType;
|
||||
|
||||
// Assists with holding child types in the SolsType struct.
|
||||
@@ -73,16 +92,20 @@ typedef struct SolsTypeField {
|
||||
|
||||
Result(SolsType, charptr);
|
||||
|
||||
// Creates a SolsType, with the provided type type.
|
||||
// Creates a SolsType, with the provided type type.
|
||||
// Use the "addChildToSolsType()" function to add children, in case this type has children.
|
||||
// Returns:
|
||||
// Success: The constructed SolsType
|
||||
// Failure: char* detailing what went wrong (usually memory failure)
|
||||
ResultType(SolsType, charptr) createSolsType(SolsTypeType in);
|
||||
|
||||
// Creates a SolsType which is identified by a name.
|
||||
// The type details are not known yet, so the type is marked as unknown.
|
||||
ResultType(SolsType, charptr) createIdentifiedSolsType(char* in);
|
||||
|
||||
Result(Nothing, charptr);
|
||||
|
||||
// Adds a child SolsType to a given SolsType.
|
||||
// Adds a child SolsType to a given SolsType.
|
||||
// Returns:
|
||||
// Success: Nothing
|
||||
// Failure: char* detailing what went wrong (usually memory failure)
|
||||
@@ -93,8 +116,10 @@ ResultType(SolsType, charptr) copySolsType(SolsType* type);
|
||||
|
||||
Result(GroundArg, charptr);
|
||||
|
||||
struct SolsScope;
|
||||
|
||||
// Represents a SolsType as a GroundArg (in typeref form)
|
||||
ResultType(GroundArg, charptr) createGroundArgFromSolsType(SolsType* type);
|
||||
ResultType(GroundArg, charptr) createGroundArgFromSolsType(SolsType* type, struct SolsScope* scope);
|
||||
|
||||
// Frees a SolsType
|
||||
void freeSolsType(SolsType* type);
|
||||
@@ -102,4 +127,9 @@ void freeSolsType(SolsType* type);
|
||||
// Compares two SolsTypes
|
||||
bool compareTypes(SolsType* left, SolsType* right);
|
||||
|
||||
// Finds the type of a struct member. Errors if the member is not found.
|
||||
ResultType(SolsType, charptr) findStructMemberType(SolsType* type, char* member);
|
||||
|
||||
void printSolsType(SolsType* type);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -15,11 +15,23 @@ struct _SolsTokenTypeMap SolsTokenTypeMap[] = {
|
||||
{"return", STT_KW_RETURN},
|
||||
{"use", STT_KW_USE},
|
||||
{"struct", STT_KW_STRUCT},
|
||||
{"enum", STT_KW_ENUM},
|
||||
{"constructor", STT_KW_CONSTRUCTOR},
|
||||
{"destructor", STT_KW_DESTRUCTOR},
|
||||
{"duplicator", STT_KW_DUPLICATOR},
|
||||
{"private", STT_KW_PRIVATE},
|
||||
{"protected", STT_KW_PROTECTED},
|
||||
{"ground", STT_KW_GROUND},
|
||||
{"new", STT_KW_NEW},
|
||||
{"as", STT_KW_AS},
|
||||
{"sizeof", STT_KW_SIZEOF},
|
||||
{"pragma", STT_KW_PRAGMA},
|
||||
{"{", STT_OPEN_CURLY},
|
||||
{"}", STT_CLOSE_CURLY},
|
||||
{"(", STT_OPEN_PAREN},
|
||||
{")", STT_CLOSE_PAREN},
|
||||
{"[", STT_OPEN_SQUARE},
|
||||
{"]", STT_CLOSE_SQUARE},
|
||||
{"+", STT_OP_ADD},
|
||||
{"-", STT_OP_SUB},
|
||||
{"*", STT_OP_MUL},
|
||||
@@ -42,7 +54,7 @@ struct _SolsTokenTypeMap SolsTokenTypeMap[] = {
|
||||
{",", STT_COMMA},
|
||||
// Shh, this is our little secret
|
||||
// Your reward for actually reading the source code
|
||||
// Enable this by adding -DSUPER_SILLY_MODE to your
|
||||
// Enable this by adding -DSUPER_SILLY_MODE to your
|
||||
// compile flags (not recommended for production)
|
||||
#ifdef SUPER_SILLY_MODE
|
||||
{"plus", STT_OP_ADD},
|
||||
@@ -62,6 +74,8 @@ struct _SolsTokenTypeMap SolsTokenTypeMap[] = {
|
||||
{"subtracts", STT_OP_SUBTO},
|
||||
{"multiplies", STT_OP_MULTO},
|
||||
{"divides", STT_OP_DIVTO},
|
||||
{"class", STT_KW_STRUCT},
|
||||
{"compilerpleasedothisforme", STT_KW_PRAGMA}
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -246,7 +260,7 @@ ResultType(SolsToken, charptr) identifyToken(const char* token) {
|
||||
tokencopy[strlen(token) - 2] = '\0';
|
||||
|
||||
// Create a literal
|
||||
ResultType(SolsLiteral, charptr) literal = createSolsLiteral(SLT_STRING, tokencopy);
|
||||
ResultType(SolsLiteral, charptr) literal = createSolsLiteral(STT_STRING, tokencopy);
|
||||
// Free our copy of the string, createSolsLiteral creates a copy
|
||||
free(tokencopy);
|
||||
if (literal.error) {
|
||||
@@ -271,7 +285,7 @@ ResultType(SolsToken, charptr) identifyToken(const char* token) {
|
||||
return Error(SolsToken, charptr, "Characters can only hold one character at a time (try using \"this\" for strings?)");
|
||||
}
|
||||
if (token[2] == '\'') {
|
||||
ResultType(SolsLiteral, charptr) literal = createSolsLiteral(SLT_CHAR, token[1]);
|
||||
ResultType(SolsLiteral, charptr) literal = createSolsLiteral(STT_CHAR, token[1]);
|
||||
if (literal.error) {
|
||||
Estr str = CREATE_ESTR(literal.as.error);
|
||||
APPEND_ESTR(str, " (in identifyToken() function)");
|
||||
@@ -305,7 +319,7 @@ ResultType(SolsToken, charptr) identifyToken(const char* token) {
|
||||
}
|
||||
if (isInt) {
|
||||
int64_t newInt = atoll(token);
|
||||
ResultType(SolsLiteral, charptr) literal = createSolsLiteral(SLT_INT, newInt);
|
||||
ResultType(SolsLiteral, charptr) literal = createSolsLiteral(STT_INT, newInt);
|
||||
if (literal.error) {
|
||||
Estr str = CREATE_ESTR(literal.as.error);
|
||||
APPEND_ESTR(str, " (in identifyToken() function)");
|
||||
@@ -320,7 +334,7 @@ ResultType(SolsToken, charptr) identifyToken(const char* token) {
|
||||
|
||||
if (isDouble) {
|
||||
double newDouble = atof(token);
|
||||
ResultType(SolsLiteral, charptr) literal = createSolsLiteral(SLT_DOUBLE, newDouble);
|
||||
ResultType(SolsLiteral, charptr) literal = createSolsLiteral(STT_DOUBLE, newDouble);
|
||||
if (literal.error) {
|
||||
Estr str = CREATE_ESTR(literal.as.error);
|
||||
APPEND_ESTR(str, " (in identifyToken() function)");
|
||||
@@ -336,7 +350,7 @@ ResultType(SolsToken, charptr) identifyToken(const char* token) {
|
||||
|
||||
// Handle boolean (true/false)
|
||||
if (strcmp(token, "true") == 0) {
|
||||
ResultType(SolsLiteral, charptr) literal = createSolsLiteral(SLT_BOOL, true);
|
||||
ResultType(SolsLiteral, charptr) literal = createSolsLiteral(STT_BOOL, true);
|
||||
if (literal.error) {
|
||||
Estr str = CREATE_ESTR(literal.as.error);
|
||||
APPEND_ESTR(str, " (in identifyToken() function)");
|
||||
@@ -349,7 +363,7 @@ ResultType(SolsToken, charptr) identifyToken(const char* token) {
|
||||
return Success(SolsToken, charptr, tok);
|
||||
}
|
||||
if (strcmp(token, "false") == 0) {
|
||||
ResultType(SolsLiteral, charptr) literal = createSolsLiteral(SLT_BOOL, false);
|
||||
ResultType(SolsLiteral, charptr) literal = createSolsLiteral(STT_BOOL, false);
|
||||
if (literal.error) {
|
||||
Estr str = CREATE_ESTR(literal.as.error);
|
||||
APPEND_ESTR(str, " (in identifyToken() function)");
|
||||
@@ -577,13 +591,15 @@ ResultType(Nothing, charptr) lex(SolsLexer* lexer) {
|
||||
}
|
||||
|
||||
// These characters require themselves added seperately from the previous token.
|
||||
case '{':
|
||||
case '{':
|
||||
case '}':
|
||||
case '(':
|
||||
case ')':
|
||||
case ',':
|
||||
case ':':
|
||||
case ';':
|
||||
case '[':
|
||||
case ']':
|
||||
case '\n':
|
||||
{
|
||||
ResultType(Nothing, charptr) res = identifyAndAdd(lexer, &buf, &lineNum, ¤tLine, chr.as.success, &skipDelimiter);
|
||||
@@ -593,7 +609,7 @@ ResultType(Nothing, charptr) lex(SolsLexer* lexer) {
|
||||
DESTROY_ESTR(currentLine);
|
||||
return Error(Nothing, charptr, err);
|
||||
}
|
||||
|
||||
|
||||
if (skipDelimiter) break;
|
||||
|
||||
char tmp[] = {chr.as.success, '\0'};
|
||||
@@ -613,7 +629,7 @@ ResultType(Nothing, charptr) lex(SolsLexer* lexer) {
|
||||
return Error(Nothing, charptr, err);
|
||||
}
|
||||
strcpy(result.as.success.line.content, currentLine.str);
|
||||
|
||||
|
||||
addTokenToSolsTokens(&lexer->output, result.as.success);
|
||||
break;
|
||||
}
|
||||
@@ -694,7 +710,7 @@ ResultType(Nothing, charptr) lex(SolsLexer* lexer) {
|
||||
addTokenToSolsTokens(&lexer->output, result.as.success);
|
||||
lexerConsume(lexer);
|
||||
}
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
// These characters may be followed by an equals sign, or nothing else.
|
||||
|
||||
54
src/main.c
54
src/main.c
@@ -7,13 +7,19 @@
|
||||
#include "include/estr.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#ifdef _WIN32
|
||||
#include <direct.h>
|
||||
#else
|
||||
#include <sys/stat.h>
|
||||
#include <libgen.h>
|
||||
#endif
|
||||
#include <groundvm.h>
|
||||
|
||||
extern bool groundDisableTypeChecking;
|
||||
|
||||
char* fileDir = NULL;
|
||||
|
||||
typedef enum SolsAction {
|
||||
SA_PRINT, SA_EXEC, SA_BYTECODE, SA_COMPILE, SA_EXIT, SA_EXITOK
|
||||
} SolsAction;
|
||||
@@ -91,41 +97,12 @@ Args parseArgs(int argc, char** argv) {
|
||||
return args;
|
||||
}
|
||||
|
||||
char* getFileContents(const char* filename) {
|
||||
// https://stackoverflow.com/questions/3747086/reading-the-whole-text-file-into-a-char-array-in-c
|
||||
FILE* fp;
|
||||
long lSize;
|
||||
char* file;
|
||||
|
||||
fp = fopen(filename, "rb");
|
||||
if (!fp) {
|
||||
perror(filename);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fseek(fp, 0L, SEEK_END);
|
||||
lSize = ftell(fp);
|
||||
rewind(fp);
|
||||
|
||||
file = calloc(1, lSize + 1);
|
||||
if (!file) {
|
||||
fclose(fp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (1!=fread(file, lSize, 1, fp)) {
|
||||
fclose(fp);
|
||||
free(file);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// we done
|
||||
fclose(fp);
|
||||
|
||||
return file;
|
||||
}
|
||||
// Use ground's getFileContents
|
||||
char* getFileContents(const char* filename);
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
groundDisableTypeChecking = true;
|
||||
|
||||
Args args = parseArgs(argc, argv);
|
||||
|
||||
if (args.action == SA_EXIT) {
|
||||
@@ -135,6 +112,17 @@ int main(int argc, char** argv) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
fileDir = NULL;
|
||||
#else
|
||||
{
|
||||
char tmp[FILENAME_MAX];
|
||||
char pwd[FILENAME_MAX];
|
||||
getcwd(pwd, sizeof(pwd));
|
||||
snprintf(tmp, FILENAME_MAX, "%s/%s", pwd, args.inputFile);
|
||||
fileDir = dirname(tmp);
|
||||
}
|
||||
#endif
|
||||
char* fileContents = getFileContents(args.inputFile);
|
||||
|
||||
if (fileContents == NULL) {
|
||||
|
||||
@@ -68,3 +68,198 @@ SolsNode deepCopySolsNode(SolsNode node) {
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
void printSolsNodeType(SolsNodeType type) {
|
||||
switch (type) {
|
||||
case SNT_IDENTIFIER:
|
||||
printf("Identifier");
|
||||
break;
|
||||
case SNT_LITERAL:
|
||||
printf("Literal");
|
||||
break;
|
||||
case SNT_TYPE:
|
||||
printf("Type");
|
||||
break;
|
||||
case SNT_CODE_BLOCK:
|
||||
printf("Code Block");
|
||||
break;
|
||||
case SNT_OP_ADD:
|
||||
printf("+");
|
||||
break;
|
||||
case SNT_OP_SUB:
|
||||
printf("-");
|
||||
break;
|
||||
case SNT_OP_MUL:
|
||||
printf("*");
|
||||
break;
|
||||
case SNT_OP_DIV:
|
||||
printf("/");
|
||||
break;
|
||||
case SNT_OP_ADDTO:
|
||||
printf("+=");
|
||||
break;
|
||||
case SNT_OP_SUBTO:
|
||||
printf("-=");
|
||||
break;
|
||||
case SNT_OP_MULTO:
|
||||
printf("*=");
|
||||
break;
|
||||
case SNT_OP_DIVTO:
|
||||
printf("/=");
|
||||
break;
|
||||
case SNT_OP_INCREMENT:
|
||||
printf("++");
|
||||
break;
|
||||
case SNT_OP_DECREMENT:
|
||||
printf("--");
|
||||
break;
|
||||
case SNT_OP_SET:
|
||||
printf("=");
|
||||
break;
|
||||
case SNT_OP_GREATER:
|
||||
printf(">");
|
||||
break;
|
||||
case SNT_OP_LESSER:
|
||||
printf("<");
|
||||
break;
|
||||
case SNT_OP_EQUAL:
|
||||
printf("==");
|
||||
break;
|
||||
case SNT_OP_INEQUAL:
|
||||
printf("!=");
|
||||
break;
|
||||
case SNT_OP_EQGREATER:
|
||||
printf(">=");
|
||||
break;
|
||||
case SNT_OP_EQLESSER:
|
||||
printf("<=");
|
||||
break;
|
||||
case SNT_DEF:
|
||||
printf("def");
|
||||
break;
|
||||
case SNT_LAMBDA:
|
||||
printf("lambda");
|
||||
break;
|
||||
case SNT_FUNCTION_CALL:
|
||||
printf("Function call");
|
||||
break;
|
||||
case SNT_RETURN:
|
||||
printf("return");
|
||||
break;
|
||||
case SNT_SET_PRIVATE:
|
||||
printf("Private =");
|
||||
break;
|
||||
case SNT_SET_PROTECTED:
|
||||
printf("Protected =");
|
||||
break;
|
||||
case SNT_DEF_PRIVATE:
|
||||
printf("Private def");
|
||||
break;
|
||||
case SNT_DEF_PROTECTED:
|
||||
printf("Protected def");
|
||||
break;
|
||||
case SNT_USE:
|
||||
printf("use");
|
||||
break;
|
||||
case SNT_LOCAL_USE:
|
||||
printf("Local use");
|
||||
break;
|
||||
case SNT_STRUCT:
|
||||
printf("struct");
|
||||
break;
|
||||
case SNT_ENUM:
|
||||
printf("enum");
|
||||
break;
|
||||
case SNT_CONSTRUCTOR:
|
||||
printf("constructor");
|
||||
break;
|
||||
case SNT_DESTRUCTOR:
|
||||
printf("destructor");
|
||||
break;
|
||||
case SNT_DUPLICATOR:
|
||||
printf("duplicator");
|
||||
break;
|
||||
case SNT_STRUCT_AS:
|
||||
printf("struct as");
|
||||
break;
|
||||
case SNT_AS:
|
||||
printf("as");
|
||||
break;
|
||||
case SNT_SIZE_OF:
|
||||
printf("sizeof");
|
||||
break;
|
||||
case SNT_PUTS:
|
||||
printf("puts");
|
||||
break;
|
||||
case SNT_IF:
|
||||
printf("if");
|
||||
break;
|
||||
case SNT_WHILE:
|
||||
printf("while");
|
||||
break;
|
||||
case SNT_NEW:
|
||||
printf("new");
|
||||
break;
|
||||
case SNT_GROUND:
|
||||
printf("ground");
|
||||
break;
|
||||
case SNT_ROOT:
|
||||
printf("Root node");
|
||||
break;
|
||||
case SNT_EXPR_IN_PAREN:
|
||||
printf("Parenthases");
|
||||
break;
|
||||
case SNT_DOT:
|
||||
printf(".");
|
||||
break;
|
||||
case SNT_GENERIC:
|
||||
printf("Generic");
|
||||
break;
|
||||
case SNT_GENERIC_INIT:
|
||||
printf("Generic init");
|
||||
break;
|
||||
case SNT_PRAGMA:
|
||||
printf("pragma");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void printSolsNode(SolsNode* node) {
|
||||
|
||||
printf("Node (\nNodeType: ");
|
||||
printSolsNodeType(node->type);
|
||||
printf("\n");
|
||||
printf("Line: num: %zu, content: %s",node->line.num, node->line.content);
|
||||
|
||||
switch (node->type) {
|
||||
case SNT_IDENTIFIER: {
|
||||
printf("\nIdentifier name: '%s'", node->as.idName);
|
||||
break;
|
||||
}
|
||||
case SNT_GROUND: {
|
||||
printf("\nInline Ground: '%s'", node->as.inlineGround);
|
||||
break;
|
||||
}
|
||||
case SNT_LITERAL: {
|
||||
printf("\nLiteral: ");
|
||||
printSolsLiteral(&node->as.literal);
|
||||
break;
|
||||
}
|
||||
case SNT_TYPE: {
|
||||
printf("\nType: ");
|
||||
printSolsType(&node->as.type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
printf("\nChildren count: %zu", node->children.count);
|
||||
if (node->children.count > 0) {
|
||||
printf("\nChildren: (\n");
|
||||
for (size_t i = 0; i < node->children.count; i++) {
|
||||
printSolsNode(&node->children.at[i]);
|
||||
}
|
||||
printf("\n)");
|
||||
}
|
||||
|
||||
printf("\n)\n");
|
||||
|
||||
}
|
||||
|
||||
@@ -11,7 +11,21 @@
|
||||
#include "../lexer/SolsToken.h"
|
||||
|
||||
typedef enum SolsNodeType {
|
||||
SNT_IDENTIFIER, SNT_LITERAL, SNT_TYPE, SNT_CODE_BLOCK, SNT_OP_ADD, SNT_OP_SUB, SNT_OP_MUL, SNT_OP_DIV, SNT_OP_ADDTO, SNT_OP_SUBTO, SNT_OP_MULTO, SNT_OP_DIVTO, SNT_OP_INCREMENT, SNT_OP_DECREMENT, SNT_OP_SET, SNT_OP_GREATER, SNT_OP_LESSER, SNT_OP_EQUAL, SNT_OP_INEQUAL, SNT_OP_EQGREATER, SNT_OP_EQLESSER, SNT_DEF, SNT_LAMBDA, SNT_FUNCTION_CALL, SNT_RETURN, SNT_USE, SNT_STRUCT, SNT_PUTS, SNT_IF, SNT_WHILE, SNT_NEW, SNT_GROUND, SNT_ROOT
|
||||
SNT_IDENTIFIER, SNT_LITERAL, SNT_TYPE,
|
||||
SNT_CODE_BLOCK,
|
||||
SNT_OP_ADD, SNT_OP_SUB, SNT_OP_MUL, SNT_OP_DIV,
|
||||
SNT_OP_ADDTO, SNT_OP_SUBTO, SNT_OP_MULTO, SNT_OP_DIVTO,
|
||||
SNT_OP_INCREMENT, SNT_OP_DECREMENT,
|
||||
SNT_OP_SET,
|
||||
SNT_OP_GREATER, SNT_OP_LESSER, SNT_OP_EQUAL, SNT_OP_INEQUAL, SNT_OP_EQGREATER, SNT_OP_EQLESSER,
|
||||
SNT_DEF, SNT_LAMBDA, SNT_FUNCTION_CALL, SNT_RETURN,
|
||||
SNT_SET_PRIVATE, SNT_SET_PROTECTED, SNT_DEF_PRIVATE, SNT_DEF_PROTECTED,
|
||||
SNT_USE, SNT_LOCAL_USE, SNT_STRUCT, SNT_ENUM, SNT_CONSTRUCTOR, SNT_DESTRUCTOR, SNT_DUPLICATOR,
|
||||
SNT_STRUCT_AS, SNT_AS, SNT_SIZE_OF,
|
||||
SNT_PUTS, SNT_IF, SNT_WHILE, SNT_NEW,
|
||||
SNT_GROUND, SNT_ROOT, SNT_EXPR_IN_PAREN, SNT_DOT,
|
||||
SNT_GENERIC, SNT_GENERIC_INIT,
|
||||
SNT_PRAGMA
|
||||
} SolsNodeType;
|
||||
|
||||
struct SolsNode;
|
||||
@@ -59,6 +73,8 @@ ResultType(SolsNode, charptr) createSolsNode(SolsNodeType type, ...);
|
||||
// Failure: char* detailing what went wrong (usually memory failure)
|
||||
ResultType(Nothing, charptr) addChildToSolsNode(SolsNode* parent, SolsNode child);
|
||||
|
||||
void printSolsNode(SolsNode* node);
|
||||
|
||||
// Deep copies a SolsNode
|
||||
SolsNode deepCopySolsNode(SolsNode node);
|
||||
|
||||
|
||||
1064
src/parser/parser.c
1064
src/parser/parser.c
File diff suppressed because it is too large
Load Diff
@@ -59,7 +59,7 @@ ResultType(SolsType, charptr) parseType(SolsTokens* in, size_t* index) {
|
||||
freeSolsType(&funType);
|
||||
return retType;
|
||||
}
|
||||
|
||||
|
||||
// Allocate memory for returnType pointer
|
||||
funType.returnType = malloc(sizeof(SolsType));
|
||||
if (funType.returnType == NULL) {
|
||||
@@ -91,7 +91,7 @@ ResultType(SolsType, charptr) parseType(SolsTokens* in, size_t* index) {
|
||||
freeSolsType(&complexType);
|
||||
return fieldType;
|
||||
}
|
||||
|
||||
|
||||
char* fieldName = NULL;
|
||||
if (*index < in->count && in->at[*index].type == STT_IDENTIFIER) {
|
||||
fieldName = in->at[*index].as.idName;
|
||||
@@ -116,7 +116,7 @@ ResultType(SolsType, charptr) parseType(SolsTokens* in, size_t* index) {
|
||||
(*index)++; // skip )
|
||||
return Success(SolsType, charptr, complexType);
|
||||
}
|
||||
|
||||
|
||||
// Handle user-defined types (as identifiers)
|
||||
// For now, let's just create an OBJECT type with identifierType set
|
||||
ResultType(SolsType, charptr) userTypeRes = createSolsType(STT_OBJECT);
|
||||
@@ -143,9 +143,9 @@ ResultType(SolsTokens, charptr) addTypeInfo(SolsTokens* in) {
|
||||
SolsTokens tokens = tokensres.as.success;
|
||||
|
||||
for (size_t i = 0; i < in->count; ) {
|
||||
if (in->at[i].type == STT_IDENTIFIER &&
|
||||
(strcmp(in->at[i].as.idName, "fun") == 0 ||
|
||||
strcmp(in->at[i].as.idName, "object") == 0 ||
|
||||
if (in->at[i].type == STT_IDENTIFIER &&
|
||||
(strcmp(in->at[i].as.idName, "fun") == 0 ||
|
||||
strcmp(in->at[i].as.idName, "object") == 0 ||
|
||||
strcmp(in->at[i].as.idName, "template") == 0)) {
|
||||
size_t startIndex = i;
|
||||
ResultType(SolsType, charptr) typeRes = parseType(in, &i);
|
||||
@@ -153,13 +153,13 @@ ResultType(SolsTokens, charptr) addTypeInfo(SolsTokens* in) {
|
||||
// For now, return error
|
||||
return Error(SolsTokens, charptr, typeRes.as.error);
|
||||
}
|
||||
|
||||
|
||||
ResultType(SolsToken, charptr) tokenRes = createSolsToken(STT_TYPE, typeRes.as.success);
|
||||
if (tokenRes.error) {
|
||||
freeSolsType(&typeRes.as.success);
|
||||
return Error(SolsTokens, charptr, tokenRes.as.error);
|
||||
}
|
||||
|
||||
|
||||
// Add line info from original token
|
||||
tokenRes.as.success.line.num = in->at[startIndex].line.num;
|
||||
if (in->at[startIndex].line.content) {
|
||||
@@ -170,7 +170,7 @@ ResultType(SolsTokens, charptr) addTypeInfo(SolsTokens* in) {
|
||||
} else {
|
||||
tokenRes.as.success.line.content = NULL;
|
||||
}
|
||||
|
||||
|
||||
addTokenToSolsTokens(&tokens, tokenRes.as.success);
|
||||
// SolsToken now owns typeRes.as.success and its buffers.
|
||||
} else {
|
||||
@@ -180,7 +180,7 @@ ResultType(SolsTokens, charptr) addTypeInfo(SolsTokens* in) {
|
||||
// But 'in' tokens might be freed later.
|
||||
// Actually, we are creating a *new* SolsTokens.
|
||||
// So we should probably copy the token properly.
|
||||
|
||||
|
||||
SolsToken original = in->at[i];
|
||||
SolsToken copy = {0};
|
||||
copy.type = original.type;
|
||||
@@ -202,8 +202,8 @@ ResultType(SolsTokens, charptr) addTypeInfo(SolsTokens* in) {
|
||||
case STT_LITERAL:
|
||||
// Literals also need deep copy?
|
||||
// SolsLiteral has stringv.
|
||||
if (original.as.literal.type == SLT_STRING) {
|
||||
copy.as.literal.type = SLT_STRING;
|
||||
if (original.as.literal.type == STT_STRING) {
|
||||
copy.as.literal.type = STT_STRING;
|
||||
copy.as.literal.as.stringv = malloc(strlen(original.as.literal.as.stringv) + 1);
|
||||
if (copy.as.literal.as.stringv) strcpy(copy.as.literal.as.stringv, original.as.literal.as.stringv);
|
||||
} else {
|
||||
|
||||
150
src/vm/vm.c
Normal file
150
src/vm/vm.c
Normal file
@@ -0,0 +1,150 @@
|
||||
#include "vm.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
[[noreturn]] static void criticalRuntimeError(char* msg) {
|
||||
fprintf(stderr, "SolsVM critical runtime error: %s\n", msg);
|
||||
fprintf(stderr, "If you believe this to be a bug, please report at https://chookspace.com/solstice/solstice\n");
|
||||
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static SolsVMValue* getRegister(SolsVMRegister reg, SolsVMState* state) {
|
||||
switch (reg) {
|
||||
case SVM_R0: return &state->registers.r0;
|
||||
case SVM_R1: return &state->registers.r1;
|
||||
case SVM_R2: return &state->registers.r2;
|
||||
case SVM_R3: return &state->registers.r3;
|
||||
case SVM_R4: return &state->registers.r4;
|
||||
case SVM_R5: return &state->registers.r5;
|
||||
case SVM_R6: return &state->registers.r6;
|
||||
case SVM_R7: return &state->registers.r7;
|
||||
case SVM_R8: return &state->registers.r8;
|
||||
case SVM_R9: return &state->registers.r9;
|
||||
case SVM_R10: return &state->registers.r10;
|
||||
case SVM_R11: return &state->registers.r11;
|
||||
case SVM_R12: return &state->registers.r12;
|
||||
case SVM_R13: return &state->registers.r13;
|
||||
case SVM_R14: return &state->registers.r14;
|
||||
case SVM_R15: return &state->registers.r15;
|
||||
}
|
||||
}
|
||||
|
||||
static size_t getSizeOf(SolsTypeType type) {
|
||||
switch (type) {
|
||||
case STT_INT:
|
||||
case STT_DOUBLE:
|
||||
case STT_STRING:
|
||||
return 8;
|
||||
case STT_BOOL:
|
||||
case STT_CHAR:
|
||||
return 1;
|
||||
case STT_FUN:
|
||||
return sizeof(SolsVMFunction);
|
||||
case STT_TEMPLATE:
|
||||
return sizeof(SolsVMStruct);
|
||||
case STT_OBJECT:
|
||||
return 0; // Object has custom size, signal with 0
|
||||
case STT_GENERIC:
|
||||
case STT_UNKNOWN:
|
||||
case STT_NONE:
|
||||
criticalRuntimeError("Unresolved type during runtime");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* puts instruction
|
||||
* Args: register, core type
|
||||
* Does: puts something on the console
|
||||
*/
|
||||
|
||||
static inline void inst_puts(SolsVMInstruction* inst, SolsVMState* state) {
|
||||
SolsVMValue reg = *getRegister(inst->args.at[0].as.reg, state);
|
||||
switch (inst->args.at[1].as.type) {
|
||||
case STT_INT: {
|
||||
printf("%" PRId64 "\n", *(int64_t*)reg);
|
||||
break;
|
||||
}
|
||||
case STT_DOUBLE: {
|
||||
printf("%f\n", *(double*)reg);
|
||||
break;
|
||||
}
|
||||
case STT_STRING: {
|
||||
printf("%s\n", *(char**)reg);
|
||||
break;
|
||||
}
|
||||
case STT_CHAR: {
|
||||
printf("%c\n", *(char*)reg);
|
||||
break;
|
||||
}
|
||||
case STT_BOOL: {
|
||||
printf("%s\n", (*(bool*)reg) ? "true" : "false");
|
||||
break;
|
||||
}
|
||||
case STT_FUN: {
|
||||
printf("<function>\n");
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
// FIXME handle structs and objects later
|
||||
printf("<FIXME>\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* store instruction
|
||||
* Stores a literal in a register
|
||||
* Args: register, literal
|
||||
* Does: Stores provided literal in the provided register
|
||||
*/
|
||||
static inline void inst_store(SolsVMInstruction* inst, SolsVMState* state) {
|
||||
SolsVMValue* reg = getRegister(inst->args.at[0].as.reg, state);
|
||||
if (*reg != NULL) free(*reg);
|
||||
*reg = malloc(getSizeOf(inst->args.at[1].as.literal.type));
|
||||
}
|
||||
|
||||
void runSolsVMInstruction(SolsVMInstruction* inst, SolsVMState* state) {
|
||||
switch (inst->inst) {
|
||||
case SVM_IT_PUTS: inst_puts(inst, state); break;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void inst_put(SolsVMInstruction* inst, SolsVMState* state) {}
|
||||
|
||||
void runSolsVM(SolsVMInstructionList* list) {
|
||||
SolsVMState state = {
|
||||
.registers = {
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
|
||||
},
|
||||
.stackSize = 0
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < list->size; i++) {
|
||||
runSolsVMInstruction(&list->instructions[i], &state);
|
||||
}
|
||||
|
||||
// Cleanup - free registers and stack
|
||||
if (state.registers.r0 != NULL) free(state.registers.r0);
|
||||
if (state.registers.r1 != NULL) free(state.registers.r1);
|
||||
if (state.registers.r2 != NULL) free(state.registers.r2);
|
||||
if (state.registers.r3 != NULL) free(state.registers.r3);
|
||||
if (state.registers.r4 != NULL) free(state.registers.r4);
|
||||
if (state.registers.r5 != NULL) free(state.registers.r5);
|
||||
if (state.registers.r6 != NULL) free(state.registers.r6);
|
||||
if (state.registers.r7 != NULL) free(state.registers.r7);
|
||||
if (state.registers.r8 != NULL) free(state.registers.r8);
|
||||
if (state.registers.r9 != NULL) free(state.registers.r9);
|
||||
if (state.registers.r10 != NULL) free(state.registers.r10);
|
||||
if (state.registers.r11 != NULL) free(state.registers.r11);
|
||||
if (state.registers.r12 != NULL) free(state.registers.r12);
|
||||
if (state.registers.r13 != NULL) free(state.registers.r13);
|
||||
if (state.registers.r14 != NULL) free(state.registers.r14);
|
||||
if (state.registers.r15 != NULL) free(state.registers.r15);
|
||||
|
||||
for (size_t i = 0; i < state.stackSize; i++) {
|
||||
if (state.stack[i] != NULL) free(state.stack[i]);
|
||||
}
|
||||
}
|
||||
69
src/vm/vm.h
Normal file
69
src/vm/vm.h
Normal file
@@ -0,0 +1,69 @@
|
||||
#ifndef VM_H
|
||||
#define VM_H
|
||||
|
||||
#define SVM_STACK_SIZE 8192
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "../lexer/SolsLiteral.h"
|
||||
#include "../lexer/SolsType.h"
|
||||
|
||||
typedef enum SolsVMRegister {
|
||||
SVM_R0, SVM_R1, SVM_R2, SVM_R3, SVM_R4, SVM_R5, SVM_R6, SVM_R7, SVM_R8, SVM_R9, SVM_R10, SVM_R11, SVM_R12, SVM_R13, SVM_R14, SVM_R15
|
||||
} SolsVMRegister;
|
||||
|
||||
typedef void* SolsVMValue;
|
||||
|
||||
typedef struct SolsVMState {
|
||||
struct {
|
||||
SolsVMValue r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15;
|
||||
} registers;
|
||||
SolsVMValue stack[SVM_STACK_SIZE];
|
||||
uint32_t stackSize;
|
||||
} SolsVMState;
|
||||
|
||||
typedef enum SolsVMInstructionType {
|
||||
SVM_IT_PUTS
|
||||
} SolsVMInstructionType;
|
||||
|
||||
typedef enum SolsVMInstructionArgType {
|
||||
SVM_AT_LITERAL, SVM_AT_REGISTER, SVM_AT_TYPE
|
||||
} SolsVMInstructionArgType;
|
||||
|
||||
typedef struct SolsVMInstructionArg {
|
||||
SolsVMInstructionArgType type;
|
||||
union {
|
||||
SolsVMRegister reg;
|
||||
SolsLiteral literal;
|
||||
SolsTypeType type;
|
||||
} as;
|
||||
} SolsVMInstructionArg;
|
||||
|
||||
typedef struct SolsVMInstruction {
|
||||
SolsVMInstructionType inst;
|
||||
struct {
|
||||
SolsVMInstructionArg* at;
|
||||
size_t size;
|
||||
size_t capacity;
|
||||
} args;
|
||||
} SolsVMInstruction;
|
||||
|
||||
typedef struct SolsVMInstructionList {
|
||||
SolsVMInstruction* instructions;
|
||||
size_t size;
|
||||
size_t capacity;
|
||||
} SolsVMInstructionList;
|
||||
|
||||
typedef struct SolsVMFunction {
|
||||
SolsVMInstructionList list;
|
||||
SolsVMState state;
|
||||
} SolsVMFunction;
|
||||
|
||||
typedef struct SolsVMStruct {
|
||||
int x; // Placeholder
|
||||
} SolsVMStruct;
|
||||
|
||||
void runSolsVM(SolsVMInstructionList* list);
|
||||
|
||||
#endif
|
||||
10
src/vm/vm.md
Normal file
10
src/vm/vm.md
Normal file
@@ -0,0 +1,10 @@
|
||||
VM Architecture
|
||||
|
||||
* Everything is a `void*`, and the Solstice compiler will resolve all types before execution. No type safety is in the VM
|
||||
* 16 registers which all hold a `void*`.
|
||||
* `void*` can hold:
|
||||
* A literal (int64_t, char*, double, bool, char)
|
||||
* A function (stored as SolsVMFunction)
|
||||
* A struct (stored as SolsVMStruct)
|
||||
* An object (multiple fields after each other, each thing has 8 bytes of padding)
|
||||
* Overwritten registers are freed
|
||||
11
tests/enum.sols
Normal file
11
tests/enum.sols
Normal file
@@ -0,0 +1,11 @@
|
||||
enum Food {
|
||||
Apple, Banana, Orange,
|
||||
}
|
||||
|
||||
def function(Food food) Food {
|
||||
return food
|
||||
}
|
||||
|
||||
puts Food
|
||||
|
||||
puts function(Food.Banana)
|
||||
46
tests/generics.sols
Normal file
46
tests/generics.sols
Normal file
@@ -0,0 +1,46 @@
|
||||
struct Hash {
|
||||
protected hashstr = ""
|
||||
}
|
||||
|
||||
struct Person {
|
||||
age = 0
|
||||
name = ""
|
||||
|
||||
constructor(int age, string name) {
|
||||
self.age = age
|
||||
self.name = name
|
||||
}
|
||||
|
||||
as Hash {
|
||||
// hash the Person here
|
||||
}
|
||||
}
|
||||
|
||||
struct HashTable<Key can Hash, Value> {
|
||||
|
||||
private ptr = 0
|
||||
protected size = 0
|
||||
private capacity = 0
|
||||
|
||||
def find(Key key) {
|
||||
hash = key as Hash
|
||||
// find in table using hash
|
||||
}
|
||||
|
||||
def set(Key key, Value value) {
|
||||
hash = key as Hash
|
||||
// store Value in the table
|
||||
}
|
||||
|
||||
constructor() {
|
||||
// malloc the pointer and set up hash information
|
||||
}
|
||||
|
||||
duplicator {
|
||||
// copy all contents
|
||||
}
|
||||
|
||||
destructor {
|
||||
// free the ptr
|
||||
}
|
||||
}
|
||||
23
tests/nested-object.sols
Normal file
23
tests/nested-object.sols
Normal file
@@ -0,0 +1,23 @@
|
||||
struct x {
|
||||
a = 5
|
||||
def modifyA(int a) int {
|
||||
self.a = a
|
||||
return a
|
||||
}
|
||||
}
|
||||
|
||||
struct y {
|
||||
b = new x
|
||||
}
|
||||
|
||||
z = new y
|
||||
puts z
|
||||
|
||||
puts z.b
|
||||
puts z.b.a
|
||||
|
||||
z.b.a = 10
|
||||
puts z
|
||||
|
||||
z.b.modifyA(15)
|
||||
puts z
|
||||
7
tests/sizeof.sols
Normal file
7
tests/sizeof.sols
Normal file
@@ -0,0 +1,7 @@
|
||||
puts sizeof "dingleing"
|
||||
|
||||
struct MyStruct {
|
||||
size = 32
|
||||
}
|
||||
|
||||
puts sizeof new MyStruct
|
||||
@@ -1,18 +1,42 @@
|
||||
use io
|
||||
struct Person {
|
||||
protected name = ""
|
||||
private age = 0
|
||||
|
||||
def greet() string {
|
||||
return "Hello, " + self.name + "!"
|
||||
}
|
||||
|
||||
def dance() string {
|
||||
return "Dancing..."
|
||||
}
|
||||
|
||||
constructor(string name, int age) {
|
||||
self.name = name
|
||||
self.age = age
|
||||
}
|
||||
|
||||
destructor {
|
||||
// We don't need to do anything here.
|
||||
}
|
||||
|
||||
duplicator {
|
||||
puts "Duplicator called!"
|
||||
// Also nothing here
|
||||
}
|
||||
|
||||
as string {
|
||||
return "dingus"
|
||||
}
|
||||
|
||||
struct dingus {
|
||||
x = 5
|
||||
y = "dingus"
|
||||
}
|
||||
|
||||
e = new dingus
|
||||
puts e
|
||||
puts dingus
|
||||
max = Person("Max", 16)
|
||||
|
||||
puts e.x
|
||||
println(e.y)
|
||||
puts max
|
||||
puts max.greet()
|
||||
puts max.name
|
||||
puts max as string
|
||||
// puts max.age (causes compile time error, age is private)
|
||||
// max.name = "Maximilian" (causes compile time error, name is protected)
|
||||
|
||||
e.x = 7
|
||||
e.y = "heheheha"
|
||||
puts e.x
|
||||
println(e.y)
|
||||
max.dance()
|
||||
|
||||
@@ -5,37 +5,41 @@ if exists("b:current_syntax")
|
||||
endif
|
||||
|
||||
" Keywords
|
||||
syn keyword solsticeConditional if
|
||||
syn keyword solsticeRepeat while
|
||||
syn keyword solsticeKeyword def struct return use
|
||||
syn keyword solsticeType int string bool double char
|
||||
syn keyword solsticeBoolean true false
|
||||
syn keyword solsKeyword puts if while def lambda return use struct new private protected constructor destructor duplicator as ground
|
||||
syn keyword solsBool true false
|
||||
|
||||
" Built-in functions
|
||||
syn keyword solsticeBuiltin puts print println input
|
||||
" Types
|
||||
syn keyword solsType int double string char bool fun template object
|
||||
|
||||
" Data Types
|
||||
syn match solsticeNumber "\d\+\(\.\d\+\)\="
|
||||
syn region solsticeString start=/"/ end=/"/
|
||||
syn match solsticeCharacter /'[^']'/
|
||||
" Strings and chars
|
||||
syn region solsString start=/"/ skip=/\\"/ end=/"/
|
||||
syn region solsChar start=/'/ skip=/\\'/ end=/'/
|
||||
|
||||
" Numbers
|
||||
syn match solsFloat /\<[0-9]\+\.[0-9]*\>/
|
||||
syn match solsInt /\<[0-9]\+\>/
|
||||
|
||||
" Operators
|
||||
syn match solsticeOperator "==\|!=\|>=\|<=\|++\|--\|+\=\|-\=\|\*=\|\/="
|
||||
syn match solsticeOperator "[><=+\-*/]"
|
||||
syn match solsOperator /+\|-\|\*\|\/\|=\|!\|>\|<\|+=\|-=\|\*=\|\/=\|++\|--\|==\|!=\|>=\|<=/
|
||||
|
||||
" Delimiters
|
||||
syn match solsticeDelimiter "[{()}]"
|
||||
syn match solsDelimiter /[{}(),;\[\]]/
|
||||
|
||||
hi def link solsticeConditional Conditional
|
||||
hi def link solsticeRepeat Repeat
|
||||
hi def link solsticeKeyword Keyword
|
||||
hi def link solsticeType Type
|
||||
hi def link solsticeBoolean Boolean
|
||||
hi def link solsticeBuiltin Function
|
||||
hi def link solsticeNumber Number
|
||||
hi def link solsticeString String
|
||||
hi def link solsticeCharacter Character
|
||||
hi def link solsticeOperator Operator
|
||||
hi def link solsticeDelimiter Delimiter
|
||||
" Comments
|
||||
syn match solsComment /\/\/.*$/
|
||||
syn match solsComment /#.*$/
|
||||
|
||||
" Highlight links
|
||||
hi def link solsKeyword Keyword
|
||||
hi def link solsBool Boolean
|
||||
hi def link solsType Type
|
||||
hi def link solsString String
|
||||
hi def link solsChar Character
|
||||
hi def link solsFloat Float
|
||||
hi def link solsInt Number
|
||||
hi def link solsOperator Operator
|
||||
hi def link solsDelimiter Delimiter
|
||||
hi def link solsComment Comment
|
||||
|
||||
let b:current_syntax = "solstice"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user