Compare commits
1 Commits
bd07952569
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9da2bb5404 |
57
.gitignore
vendored
57
.gitignore
vendored
@@ -1,57 +0,0 @@
|
|||||||
# ---> C
|
|
||||||
# Prerequisites
|
|
||||||
*.d
|
|
||||||
|
|
||||||
# Object files
|
|
||||||
*.o
|
|
||||||
*.ko
|
|
||||||
*.obj
|
|
||||||
*.elf
|
|
||||||
|
|
||||||
# Linker output
|
|
||||||
*.ilk
|
|
||||||
*.map
|
|
||||||
*.exp
|
|
||||||
|
|
||||||
# Precompiled Headers
|
|
||||||
*.gch
|
|
||||||
*.pch
|
|
||||||
|
|
||||||
# Libraries
|
|
||||||
*.lib
|
|
||||||
*.a
|
|
||||||
*.la
|
|
||||||
*.lo
|
|
||||||
|
|
||||||
# Shared objects (inc. Windows DLLs)
|
|
||||||
*.dll
|
|
||||||
*.so
|
|
||||||
*.so.*
|
|
||||||
*.dylib
|
|
||||||
|
|
||||||
# Executables
|
|
||||||
*.exe
|
|
||||||
*.out
|
|
||||||
*.app
|
|
||||||
*.i*86
|
|
||||||
*.x86_64
|
|
||||||
*.hex
|
|
||||||
|
|
||||||
# Debug files
|
|
||||||
*.dSYM/
|
|
||||||
*.su
|
|
||||||
*.idb
|
|
||||||
*.pdb
|
|
||||||
|
|
||||||
# Kernel Module Compile Results
|
|
||||||
*.mod*
|
|
||||||
*.cmd
|
|
||||||
.tmp_versions/
|
|
||||||
modules.order
|
|
||||||
Module.symvers
|
|
||||||
Mkfile.old
|
|
||||||
dkms.conf
|
|
||||||
|
|
||||||
sasm
|
|
||||||
sylt
|
|
||||||
vmbl
|
|
||||||
1
src/sylt/ast.c
Normal file
1
src/sylt/ast.c
Normal file
@@ -0,0 +1 @@
|
|||||||
|
#include "ast.h"
|
||||||
65
src/sylt/ast.h
Normal file
65
src/sylt/ast.h
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
#ifndef AST_H
|
||||||
|
#define AST_H
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
NODE_PROGRAM,
|
||||||
|
|
||||||
|
// Statements
|
||||||
|
NODE_EXPRESSION_STATEMENT,
|
||||||
|
|
||||||
|
// Expressions
|
||||||
|
NODE_INFIX_EXPRESSION,
|
||||||
|
|
||||||
|
// Literals
|
||||||
|
NODE_INT_LITERAL,
|
||||||
|
NODE_FLOAT_LITERAL
|
||||||
|
} AST_Type;
|
||||||
|
|
||||||
|
typedef struct AST AST;
|
||||||
|
struct AST
|
||||||
|
{
|
||||||
|
AST_Type type;
|
||||||
|
char *(*to_json)(AST *node);
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
AST base;
|
||||||
|
AST **statements;
|
||||||
|
size_t statementCount;
|
||||||
|
} Program;
|
||||||
|
char *programToJSON(AST *node);
|
||||||
|
|
||||||
|
// statements
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
AST base;
|
||||||
|
AST *expr;
|
||||||
|
} ExpressionStatement;
|
||||||
|
char *expressionStatementToJSON(AST *node);
|
||||||
|
|
||||||
|
// expressions
|
||||||
|
typedef struct {
|
||||||
|
AST base;
|
||||||
|
AST *left;
|
||||||
|
char *operator;
|
||||||
|
AST *right;
|
||||||
|
} InfixExpression;
|
||||||
|
char *infixExpressionToJSON(AST *node);
|
||||||
|
|
||||||
|
// literals
|
||||||
|
typedef struct {
|
||||||
|
AST base;
|
||||||
|
int value;
|
||||||
|
} IntegerLiteral;
|
||||||
|
char *integerLiteralToJSON(AST *node);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
AST base;
|
||||||
|
double value;
|
||||||
|
} FloatLiteral;
|
||||||
|
char *floatLiteralToJSON(AST *node);
|
||||||
|
|
||||||
|
#endif // !AST_H
|
||||||
21
src/sylt/exception.c
Normal file
21
src/sylt/exception.c
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
#include "exception.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "../utils/ansii.h"
|
||||||
|
|
||||||
|
char *exceptionTypeToCString(ExceptionType type) {
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case EXCEPTION_MALFORMED_NUMBER:
|
||||||
|
return "MalformedNumberException";
|
||||||
|
|
||||||
|
case EXCEPTION_MEMORY_ALLOCATION_FAILURE:
|
||||||
|
return "MemoryAllocationFailException";
|
||||||
|
|
||||||
|
default:
|
||||||
|
return "UnkownException (fix me please)";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void exceptionMessage(ExceptionType type, char *message, int lineNumber, int position) {
|
||||||
|
printf(ESC_RED_FG ESC_BOLD "%s: %s" ESC_RESET "\n", exceptionTypeToCString(type), message);
|
||||||
|
}
|
||||||
12
src/sylt/exception.h
Normal file
12
src/sylt/exception.h
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#ifndef EXCEPTION_H
|
||||||
|
#define EXCEPTION_H
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
EXCEPTION_MALFORMED_NUMBER,
|
||||||
|
EXCEPTION_MEMORY_ALLOCATION_FAILURE
|
||||||
|
} ExceptionType;
|
||||||
|
|
||||||
|
char *exceptionTypeToCString(ExceptionType type);
|
||||||
|
void exceptionMessage(ExceptionType type, char *message, int lineNumber, int position);
|
||||||
|
|
||||||
|
#endif // !EXCEPTION_H
|
||||||
1
src/sylt/parser.c
Normal file
1
src/sylt/parser.c
Normal file
@@ -0,0 +1 @@
|
|||||||
|
#include "parser.h"
|
||||||
28
src/sylt/parser.h
Normal file
28
src/sylt/parser.h
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
#ifndef PARSER_H
|
||||||
|
#define PARSER_H
|
||||||
|
|
||||||
|
#include "lexer.h"
|
||||||
|
#include "ast.h"
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
PRECEDENCE_LOWEST = 0,
|
||||||
|
PRECEDENCE_EQUALS,
|
||||||
|
PRECEDENCE_LESSGREATER,
|
||||||
|
PRECEDENCE_SUM,
|
||||||
|
PRECEDENCE_PRODUCT,
|
||||||
|
PRECEDENCE_EXPONENT,
|
||||||
|
PRECEDENCE_PREFIX,
|
||||||
|
PRECEDENCE_CALL,
|
||||||
|
PRECEDENCE_INDEX,
|
||||||
|
} PrecedenceType;
|
||||||
|
|
||||||
|
PrecedenceType PRECEDENCES[] = {
|
||||||
|
[TOKEN_PLUS] = PRECEDENCE_SUM,
|
||||||
|
[TOKEN_MINUS] = PRECEDENCE_SUM,
|
||||||
|
[TOKEN_SLASH] = PRECEDENCE_PRODUCT,
|
||||||
|
[TOKEN_ASTERISK] = PRECEDENCE_PRODUCT,
|
||||||
|
[TOKEN_MODULUS] = PRECEDENCE_PRODUCT,
|
||||||
|
[TOKEN_POW] = PRECEDENCE_EXPONENT,
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // !PARSER_H
|
||||||
45
src/sylt/token.c
Normal file
45
src/sylt/token.c
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
#include "token.h"
|
||||||
|
|
||||||
|
char *tokenTypeToCString(TokenType type) {
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case TOKEN_EOF:
|
||||||
|
return "TOKEN_EOF";
|
||||||
|
|
||||||
|
case TOKEN_ILLEGAL:
|
||||||
|
return "TOKEN_ILLEGAL";
|
||||||
|
|
||||||
|
case TOKEN_INT:
|
||||||
|
return "TOKEN_INT";
|
||||||
|
|
||||||
|
case TOKEN_FLOAT:
|
||||||
|
return "TOKEN_FLOAT";
|
||||||
|
|
||||||
|
case TOKEN_PLUS:
|
||||||
|
return "TOKEN_EOF";
|
||||||
|
|
||||||
|
case TOKEN_MINUS:
|
||||||
|
return "TOKEN_MINUS";
|
||||||
|
|
||||||
|
case TOKEN_ASTERISK:
|
||||||
|
return "TOKEN_ASTERISK";
|
||||||
|
|
||||||
|
case TOKEN_SLASH:
|
||||||
|
return "TOKEN_SLASH";
|
||||||
|
|
||||||
|
case TOKEN_POW:
|
||||||
|
return "TOKEN_POW";
|
||||||
|
|
||||||
|
case TOKEN_MODULUS:
|
||||||
|
return "TOKEN_MODULUS";
|
||||||
|
|
||||||
|
case TOKEN_LPAREN:
|
||||||
|
return "TOKEN_LPAREN";
|
||||||
|
|
||||||
|
case TOKEN_RPAREN:
|
||||||
|
return "TOKEN_RPAREN";
|
||||||
|
|
||||||
|
default:
|
||||||
|
return "UNKOWN (fix me please)";
|
||||||
|
}
|
||||||
|
}
|
||||||
39
src/vmbl/exception.c
Normal file
39
src/vmbl/exception.c
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
#include "exception.h"
|
||||||
|
|
||||||
|
char* exceptionAsCString(VMBL_Exception exception)
|
||||||
|
{
|
||||||
|
switch (exception.type)
|
||||||
|
{
|
||||||
|
case EXCEPTION_NONE:
|
||||||
|
return "EXCEPTION_NONE";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EXCEPTION_STACK_OVERFLOW:
|
||||||
|
return "EXCEPTION_STACK_OVERFLOW";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EXCEPTION_STACK_UNDERFLOW:
|
||||||
|
return "EXCEPTION_STACK_UNDERFLOW";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EXCEPTION_INVALID_OPCODE:
|
||||||
|
return "EXCEPTION_INVALID_OPCODE";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EXCEPTION_INVALID_OPPERAND:
|
||||||
|
return "EXCEPTION_INVALID_OPPERAND";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EXCEPTION_INVALID_INSTRUCTION_ACCESS:
|
||||||
|
return "EXCEPTION_INVALID_INSTRUCTION_ACCESS";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EXCEPTION_DIVIDE_BY_ZERO:
|
||||||
|
return "EXCEPTION_DIVIDE_BY_ZERO";
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return "EXCEPTION_UNKOWN";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
21
src/vmbl/exception.h
Normal file
21
src/vmbl/exception.h
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
#ifndef EXCEPTION_H
|
||||||
|
#define EXCEPTION_H
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
EXCEPTION_NONE,
|
||||||
|
EXCEPTION_STACK_OVERFLOW,
|
||||||
|
EXCEPTION_STACK_UNDERFLOW,
|
||||||
|
EXCEPTION_INVALID_OPCODE,
|
||||||
|
EXCEPTION_INVALID_OPPERAND,
|
||||||
|
EXCEPTION_INVALID_INSTRUCTION_ACCESS,
|
||||||
|
EXCEPTION_DIVIDE_BY_ZERO
|
||||||
|
} VMBL_ExceptionType;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
VMBL_ExceptionType type;
|
||||||
|
} VMBL_Exception;
|
||||||
|
|
||||||
|
char* exceptionAsCString(VMBL_Exception exception);
|
||||||
|
|
||||||
|
#endif
|
||||||
18
src/vmbl/main.c
Normal file
18
src/vmbl/main.c
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#include "vmbl.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]));
|
||||||
|
|
||||||
|
VMBL_Instruction program[] = {
|
||||||
|
MAKE_INST_JMP(0)
|
||||||
|
};
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
VMBL_State vmblState = {};
|
||||||
|
|
||||||
|
VMBL_LoadExecutable(&vmblState, program, sizeof(program));
|
||||||
|
VMBL_SaveExecutable("fib.vmbl", program, sizeof(program));
|
||||||
|
VMBL_StartVM(&vmblState);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
260
src/vmbl/vmbl.c
Normal file
260
src/vmbl/vmbl.c
Normal file
@@ -0,0 +1,260 @@
|
|||||||
|
#include "vmbl.h"
|
||||||
|
#include "../utils/file_utils.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define MATH_OP(vmblState, operation) \
|
||||||
|
do { \
|
||||||
|
if ((vmblState)->stackSize < 2) { \
|
||||||
|
return (VMBL_Exception){ EXCEPTION_STACK_UNDERFLOW }; \
|
||||||
|
} \
|
||||||
|
(vmblState)->stack[(vmblState)->stackSize - 2] = (vmblState)->stack[(vmblState)->stackSize - 2] operation (vmblState)->stack[(vmblState)->stackSize - 1]; \
|
||||||
|
(vmblState)->stackSize--; \
|
||||||
|
} while (0);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
VMBL_Exception VBML_ExecuteInstruction(VMBL_State *vmblState, VMBL_Instruction instruction) {
|
||||||
|
switch (instruction.type)
|
||||||
|
{
|
||||||
|
case INSTRUCTION_PUSH:
|
||||||
|
if (vmblState->stackSize >= VMBL_STACK_SIZE) {
|
||||||
|
return (VMBL_Exception){ EXCEPTION_STACK_OVERFLOW };
|
||||||
|
}
|
||||||
|
|
||||||
|
vmblState->stack[vmblState->stackSize++] = instruction.opperands[0];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case INSTRUCTION_ADD:
|
||||||
|
MATH_OP(vmblState, +);
|
||||||
|
break;
|
||||||
|
case INSTRUCTION_SUB:
|
||||||
|
MATH_OP(vmblState, -);
|
||||||
|
break;
|
||||||
|
case INSTRUCTION_MUL:
|
||||||
|
MATH_OP(vmblState, *);
|
||||||
|
break;
|
||||||
|
case INSTRUCTION_DIV:
|
||||||
|
if (vmblState->stack[vmblState->stackSize-1] == 0) {
|
||||||
|
return (VMBL_Exception){ EXCEPTION_DIVIDE_BY_ZERO };
|
||||||
|
}
|
||||||
|
|
||||||
|
MATH_OP(vmblState, /);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case INSTRUCTION_DUPLICATE:
|
||||||
|
if (vmblState->stackSize - instruction.opperands[0] <= 0) {
|
||||||
|
return (VMBL_Exception){ EXCEPTION_STACK_UNDERFLOW };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vmblState->stackSize >= VMBL_STACK_SIZE) {
|
||||||
|
return (VMBL_Exception){ EXCEPTION_STACK_OVERFLOW };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (instruction.opperands[0] < 0) {
|
||||||
|
return (VMBL_Exception) { EXCEPTION_INVALID_OPPERAND };
|
||||||
|
}
|
||||||
|
|
||||||
|
vmblState->stack[vmblState->stackSize++] = vmblState->stack[vmblState->stackSize - 1 - instruction.opperands[0]];
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case INSTRUCTION_JUMP:
|
||||||
|
|
||||||
|
vmblState->ip = instruction.opperands[0];
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case INSTRUCTION_HALT:
|
||||||
|
vmblState->halted = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case INSTRUCTION_EQUAL:
|
||||||
|
MATH_OP(vmblState, ==);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case INSTRUCTION_JUMP_CONDITIONAL:
|
||||||
|
if (instruction.opperands[0] < 0) {
|
||||||
|
return (VMBL_Exception) { EXCEPTION_INVALID_OPPERAND };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vmblState->stack[vmblState->stackSize--]) {
|
||||||
|
vmblState->ip = instruction.opperands[0];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case INSTRUCTION_DROP:
|
||||||
|
if (vmblState->stackSize <= 0) {
|
||||||
|
return (VMBL_Exception){ EXCEPTION_STACK_UNDERFLOW };
|
||||||
|
}
|
||||||
|
|
||||||
|
vmblState->stackSize--;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case INSTRUCTION_NOP:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return (VMBL_Exception) { EXCEPTION_INVALID_OPCODE };
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (VMBL_Exception) { EXCEPTION_NONE };
|
||||||
|
}
|
||||||
|
|
||||||
|
void VMBL_Dump(VMBL_State vmblState, VMBL_Exception exception) {
|
||||||
|
fprintf(stderr, "EXCEPTION: %s\n\n", exceptionAsCString(exception));
|
||||||
|
fprintf(stderr, "Stack:\n");
|
||||||
|
|
||||||
|
if (vmblState.stackSize > 0) {
|
||||||
|
for (size_t i = 0; i < vmblState.stackSize; i++) {
|
||||||
|
fprintf(stderr, " 0x%lX: %ld\n", i, vmblState.stack[i]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, " [empty]\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void VMBL_StartVM(VMBL_State *vmblState) {
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
// fetch next instruction
|
||||||
|
if (vmblState->ip >= VMBL_PROGRAM_SIZE) {
|
||||||
|
VMBL_Dump(*vmblState, (VMBL_Exception){ EXCEPTION_INVALID_INSTRUCTION_ACCESS});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VMBL_Instruction instruction = vmblState->program[vmblState->ip++];
|
||||||
|
//printf("%s 0x%lx, 0x%lx, 0x%lx\n", instructionTypeToCStr(instruction.type), instruction.opperands[0], instruction.opperands[1], instruction.opperands[2]);
|
||||||
|
|
||||||
|
VMBL_Exception exception = VBML_ExecuteInstruction(vmblState, instruction);
|
||||||
|
|
||||||
|
if (exception.type != EXCEPTION_NONE) {
|
||||||
|
VMBL_Dump(*vmblState, exception);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vmblState->halted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// executable operations
|
||||||
|
void VMBL_LoadExecutable(VMBL_State *vmblState, VMBL_Instruction *program, size_t programSize) {
|
||||||
|
if (programSize > VMBL_PROGRAM_SIZE) {
|
||||||
|
fprintf(stderr, "VMBL: failed to load program from memory because it is %ld words in size, while the max size is %d.", programSize, VMBL_PROGRAM_SIZE);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(&vmblState->program, program, programSize);
|
||||||
|
|
||||||
|
vmblState->programSize = programSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VMBL_LoadExecutableFromFile(VMBL_State *vmblState, char* filePath) {
|
||||||
|
/*FILE *file = fopen(filePath, "rb");
|
||||||
|
|
||||||
|
if (file == NULL) {
|
||||||
|
perror("VMBL: Failed to open file");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
fseek(file, 0, SEEK_END);
|
||||||
|
long size = ftell(file);
|
||||||
|
rewind(file);
|
||||||
|
|
||||||
|
size_t programSize = size / sizeof(vmblState->program[0]);
|
||||||
|
VMBL_Instruction program[programSize];
|
||||||
|
fread(program, sizeof(program[0]), programSize, file);*/
|
||||||
|
|
||||||
|
VMBL_Instruction *program = (VMBL_Instruction*)readStringFromFile(filePath);
|
||||||
|
|
||||||
|
VMBL_LoadExecutable(vmblState, program, sizeof(program));
|
||||||
|
|
||||||
|
//fclose(file);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void VMBL_SaveExecutable(const char* filePath, VMBL_Instruction *program, size_t programSize) {
|
||||||
|
FILE *file = fopen(filePath, "wb");
|
||||||
|
|
||||||
|
if (file == NULL) {
|
||||||
|
perror("VMBL: Failed to open file");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
fwrite(program, sizeof(program), programSize, file);
|
||||||
|
fclose(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *instructionTypeToCStr(InstructionType type) {
|
||||||
|
printf("%x\n", type);
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
|
||||||
|
case INSTRUCTION_PUSH:
|
||||||
|
return "PUSH";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case INSTRUCTION_ADD:
|
||||||
|
return "ADD ";
|
||||||
|
break;
|
||||||
|
case INSTRUCTION_SUB:
|
||||||
|
return "SUB ";
|
||||||
|
break;
|
||||||
|
case INSTRUCTION_MUL:
|
||||||
|
return "MUL ";
|
||||||
|
break;
|
||||||
|
case INSTRUCTION_DIV:
|
||||||
|
return "DIV ";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case INSTRUCTION_DUPLICATE:
|
||||||
|
return "DUP ";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case INSTRUCTION_JUMP:
|
||||||
|
return "JMP ";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case INSTRUCTION_HALT:
|
||||||
|
return "HALT";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case INSTRUCTION_EQUAL:
|
||||||
|
return "EQ ";
|
||||||
|
break;
|
||||||
|
case INSTRUCTION_NOT_EQUAL:
|
||||||
|
return "NEQ ";
|
||||||
|
break;
|
||||||
|
case INSTRUCTION_GREATER_THAN:
|
||||||
|
return "GT ";
|
||||||
|
break;
|
||||||
|
case INSTRUCTION_GREATER_THAN_EQUAL:
|
||||||
|
return "GTE ";
|
||||||
|
break;
|
||||||
|
case INSTRUCTION_LESS_THAN:
|
||||||
|
return "LT ";
|
||||||
|
break;
|
||||||
|
case INSTRUCTION_LESS_THAN_EQUAL:
|
||||||
|
return "LTE ";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case INSTRUCTION_JUMP_CONDITIONAL:
|
||||||
|
return "JC ";
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return "??? ";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
87
src/vmbl/vmbl.h
Normal file
87
src/vmbl/vmbl.h
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
#ifndef VMBL_H
|
||||||
|
#define VMBL_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "exception.h"
|
||||||
|
|
||||||
|
#define VMBL_STACK_SIZE 1024
|
||||||
|
#define VMBL_PROGRAM_SIZE 1024
|
||||||
|
|
||||||
|
typedef int64_t Word;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
INSTRUCTION_NOP,
|
||||||
|
|
||||||
|
// stack operations
|
||||||
|
INSTRUCTION_PUSH,
|
||||||
|
INSTRUCTION_ADD,
|
||||||
|
INSTRUCTION_SUB,
|
||||||
|
INSTRUCTION_MUL,
|
||||||
|
INSTRUCTION_DIV,
|
||||||
|
INSTRUCTION_DUPLICATE,
|
||||||
|
INSTRUCTION_DROP,
|
||||||
|
|
||||||
|
// instruction pointer operations
|
||||||
|
INSTRUCTION_HALT,
|
||||||
|
INSTRUCTION_JUMP,
|
||||||
|
INSTRUCTION_JUMP_CONDITIONAL,
|
||||||
|
|
||||||
|
// conditional operations
|
||||||
|
INSTRUCTION_NOT_EQUAL,
|
||||||
|
INSTRUCTION_EQUAL,
|
||||||
|
INSTRUCTION_LESS_THAN,
|
||||||
|
INSTRUCTION_LESS_THAN_EQUAL,
|
||||||
|
INSTRUCTION_GREATER_THAN,
|
||||||
|
INSTRUCTION_GREATER_THAN_EQUAL
|
||||||
|
} InstructionType;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
InstructionType type;
|
||||||
|
Word opperands[3];
|
||||||
|
} VMBL_Instruction;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
Word stack[VMBL_STACK_SIZE];
|
||||||
|
size_t stackSize;
|
||||||
|
|
||||||
|
VMBL_Instruction program[VMBL_PROGRAM_SIZE];
|
||||||
|
size_t programSize;
|
||||||
|
|
||||||
|
long ip;
|
||||||
|
bool halted;
|
||||||
|
} VMBL_State;
|
||||||
|
|
||||||
|
#define MAKE_INST_PUSH(value) (VMBL_Instruction) { .type = INSTRUCTION_PUSH, .opperands[0] = (value) }
|
||||||
|
#define MAKE_INST_DROP (VMBL_Instruction) { .type = INSTRUCTION_POP }
|
||||||
|
#define MAKE_INST_ADD (VMBL_Instruction) { .type = INSTRUCTION_ADD }
|
||||||
|
#define MAKE_INST_SUB (VMBL_Instruction) { .type = INSTRUCTION_SUB }
|
||||||
|
#define MAKE_INST_MUL (VMBL_Instruction) { .type = INSTRUCTION_MUL }
|
||||||
|
#define MAKE_INST_DIV (VMBL_Instruction) { .type = INSTRUCTION_DIV }
|
||||||
|
#define MAKE_INST_DUP(value) (VMBL_Instruction) { .type = INSTRUCTION_DUPLICATE, .opperands[0] = (value) }
|
||||||
|
#define MAKE_INST_JMP(value) (VMBL_Instruction) { .type = INSTRUCTION_JUMP, .opperands[0] = (value) }
|
||||||
|
#define MAKE_INST_HALT (VMBL_Instruction) { .type = INSTRUCTION_HALT }
|
||||||
|
#define MAKE_INST_EQUAL (VMBL_Instruction) { .type = INSTRUCTION_EQUAL }
|
||||||
|
#define MAKE_INST_NOT_EQUAL (VMBL_Instruction) { .type = INSTRUCTION_NOT_EQUAL }
|
||||||
|
#define MAKE_INST_LESS (VMBL_Instruction) { .type = INSTRUCTION_LESS_THAN }
|
||||||
|
#define MAKE_INST_LESS_EQUAL (VMBL_Instruction) { .type = INSTRUCTION_LESS_THAN_EQUAL }
|
||||||
|
#define MAKE_INST_GREATER (VMBL_Instruction) { .type = INSTRUCTION_GREATER_THAN }
|
||||||
|
#define MAKE_INST_GREATER_EQUAL (VMBL_Instruction) { .type = INSTRUCTION_GREATER_THAN_EQUAL }
|
||||||
|
#define MAKE_INST_JUMP_CONDITIONAL(value) (VMBL_Instruction) { .type = INSTRUCTION_JUMP_CONDITIONAL, .opperands[0] = (value) }
|
||||||
|
|
||||||
|
VMBL_Exception VBML_ExecuteInstruction(VMBL_State *vmblState, VMBL_Instruction instruction);
|
||||||
|
void VMBL_Dump(VMBL_State vmblState, VMBL_Exception exception);
|
||||||
|
void VMBL_StartVM(VMBL_State *vmblState);
|
||||||
|
|
||||||
|
void VMBL_LoadExecutable(VMBL_State *vmblState, VMBL_Instruction *program, size_t programSize);
|
||||||
|
void VMBL_LoadExecutableFromFile(VMBL_State *vmblState, char* filePath);
|
||||||
|
void VMBL_SaveExecutable(const char* filePath, VMBL_Instruction *program, size_t programSize);
|
||||||
|
|
||||||
|
char *instructionTypeToCStr(InstructionType type);
|
||||||
|
|
||||||
|
#endif // !VMBL_H
|
||||||
Reference in New Issue
Block a user