Skip to content

Commit

Permalink
VM: remove I32 type
Browse files Browse the repository at this point in the history
  • Loading branch information
mrunix00 committed Jul 28, 2024
1 parent 5ef20f0 commit f51b5fa
Show file tree
Hide file tree
Showing 12 changed files with 72 additions and 333 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@ make -j`nproc`
## Syntax
### Variable declaration
```c
define x : i32 = 42;
define x : int = 42;
define y = 42;
```
### Function declaration
```c
define add : function(x : i32, y : i32) -> i32 = {
define add : function(x : int, y : int) -> int = {
return x + y;
};
```
Expand Down
30 changes: 0 additions & 30 deletions include/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,6 @@
: Instruction::InstructionType::OPERATION##GlobalObject; \
instruction.params.index = id; \
break; \
case VariableType::Type::Bool: \
case VariableType::Type::I32: \
instruction.type = isLocal ? Instruction::InstructionType::OPERATION##LocalI32 \
: Instruction::InstructionType::OPERATION##GlobalI32; \
instruction.params.index = id; \
break; \
case VariableType::Type::I64: \
instruction.type = isLocal ? Instruction::InstructionType::OPERATION##LocalI64 \
: Instruction::InstructionType::OPERATION##GlobalI64; \
Expand All @@ -55,30 +49,6 @@ inline uint32_t convert<uint32_t>(const std::string &value) {
return static_cast<uint32_t>(std::stoull(value));
}

#define DECLARE_VAR_CASE(TYPE, PARAM, CONVERT_TYPE) \
case TYPE: { \
if (!value.has_value()) { \
segment.instructions.push_back({ \
.type = Instruction::InstructionType::Load##TYPE, \
.params = {.PARAM = 0}, \
}); \
} else if (((Node *) value.value())->token.type == Number) { \
segment.instructions.push_back({ \
.type = Instruction::InstructionType::Load##TYPE, \
.params = {.PARAM = convert<CONVERT_TYPE>(((Node *) value.value())->token.value)}, \
}); \
} else { \
((Node *) value.value())->compile(program, segment); \
} \
segment.declare_variable(identifier.token.value, new VariableType(VariableType::Type::TYPE)); \
segment.instructions.push_back({ \
.type = segment.id == 0 \
? Instruction::InstructionType::StoreGlobal##TYPE \
: Instruction::InstructionType::StoreLocal##TYPE, \
.params = {.index = segment.find_local(identifier.token.value)}, \
}); \
} break;

#define VAR_CASE(OP, TYPE) \
case VariableType::Type::TYPE: \
segment.instructions.push_back(Instruction{.type = Instruction::InstructionType::OP##TYPE}); \
Expand Down
29 changes: 0 additions & 29 deletions include/vm.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,48 +12,29 @@
struct Instruction {
enum InstructionType : uint8_t {
Invalid = 0,
AddI32,
AddI64,
SubI32,
SubI64,
MulI32,
MulI64,
DivI32,
DivI64,
ModI32,
ModI64,
GreaterI32,
GreaterI64,
LessI32,
LessI64,
GreaterEqualI32,
GreaterEqualI64,
LessEqualI32,
LessEqualI64,
EqualI32,
EqualI64,
NotEqualI32,
NotEqualI64,
IncrementI32,
IncrementI64,
DecrementI32,
DecrementI64,
StoreGlobalI32,
StoreGlobalI64,
StoreGlobalObject,
StoreLocalI32,
StoreLocalI64,
StoreLocalObject,
LoadI32,
LoadI64,
LoadObject,
LoadGlobalI32,
LoadGlobalI64,
LoadGlobalObject,
LoadLocalI32,
LoadLocalI64,
LoadLocalObject,
ConvertI32toI64,
Return,
Call,
JumpIfFalse,
Expand All @@ -62,24 +43,14 @@ struct Instruction {
union {
void *ptr;
size_t index;
int32_t i32;
int64_t i64;
struct {
size_t index;
int32_t i32;
} ri32;
struct {
size_t index;
int64_t i64;
} ri64;
} params{};
};

struct VariableType {
enum Type : uint32_t {
Invalid = 0,
Bool,
I32,
I64,
Object,
Function
Expand Down
5 changes: 1 addition & 4 deletions main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,8 @@ void printTopStack(const VM &vm, const Program &program) {
case VariableType::Bool:
std::cout << (vm.topStack() == 0 ? "false" : "true") << std::endl;
break;
case VariableType::I32:
std::cout << (int32_t) vm.topStack() << std::endl;
break;
case VariableType::I64: {
std::cout << vm.topStack() << std::endl;
std::cout << (int64_t) vm.topStack() << std::endl;
} break;
case VariableType::Object: {
auto obj = std::bit_cast<Object *>(vm.topStack());
Expand Down
28 changes: 22 additions & 6 deletions src/ast.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ void Node::compile(Program &program, Segment &segment) const {
case True:
return segment.instructions.push_back(
Instruction{
.type = Instruction::InstructionType::LoadI32,
.params = {.i32 = token.value == "true"},
.type = Instruction::InstructionType::LoadI64,
.params = {.i64 = token.value == "true"},
});
default:
throw std::runtime_error("[Node::compile] This should not be accessed!");
Expand Down Expand Up @@ -151,8 +151,26 @@ void Declaration::compile(Program &program, Segment &segment) const {
emitStore(program, segment, identifier.token.value);
} break;
case Bool:
DECLARE_VAR_CASE(I32, i32, int32_t)
DECLARE_VAR_CASE(I64, i64, int64_t)
case Int: {
if (!value.has_value()) {
segment.instructions.push_back({
.type = Instruction::InstructionType::LoadI64,
.params = {.i64 = 0},
});
} else if (((Node *) value.value())->token.type == Number) {
segment.instructions.push_back({
.type = Instruction::InstructionType::LoadI64,
.params = {.i64 = convert<int64_t>(((Node *) value.value())->token.value)},
});
} else {
((Node *) value.value())->compile(program, segment);
}
segment.declare_variable(identifier.token.value, new VariableType(VariableType::Type::I64));
segment.instructions.push_back({
.type = segment.id == 0 ? Instruction::InstructionType::StoreGlobalI64 : Instruction::InstructionType::StoreLocalI64,
.params = {.index = segment.find_local(identifier.token.value)},
});
} break;
default:
throw std::runtime_error("[Declaration::compile] Unimplemented type handler!");
}
Expand Down Expand Up @@ -393,15 +411,13 @@ void UnaryExpression::compile(Program &program, Segment &segment) const {
switch (op.type) {
case Increment:
switch (varType->type) {
VAR_CASE(Increment, I32)
VAR_CASE(Increment, I64)
default:
throw std::runtime_error("[UnaryExpression::compile] Invalid varType!");
}
break;
case Decrement:
switch (varType->type) {
VAR_CASE(Decrement, I32)
VAR_CASE(Decrement, I64)
default:
throw std::runtime_error("[UnaryExpression::compile] Invalid varType!");
Expand Down
11 changes: 2 additions & 9 deletions src/lexer.l
Original file line number Diff line number Diff line change
Expand Up @@ -50,15 +50,8 @@
"while" { return While; }
"for" { return For; }
"return" { return Return; }
"u8" { return U8; }
"u16" { return U16; }
"u32" { return U32; }
"u64" { return U64; }
"i8" { return I8; }
"i16" { return I16; }
"i32" { return I32; }
"i64" { return I64; }
"f32" { return F32; }
"uint" { return UInt; }
"int" { return Int; }
"f64" { return F64; }
"bool" { return Bool; }
"str" { return Str; }
Expand Down
17 changes: 5 additions & 12 deletions src/parser.y
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
%token Increment Decrement IncrementAssign DecrementAssign
%token Equal NotEqual Less Greater LessEqual GreaterEqual And Or Not
%token Define Function If Else While For Return
%token U8 U16 U32 U64 I8 I16 I32 I64 F32 F64 Bool True False Str
%token Int UInt F64 Bool True False Str
%token Colon Comma Semicolon Arrow Newline
%token LParen RParen LBrace RBrace LBracket RBracket

Expand Down Expand Up @@ -67,19 +67,10 @@ ForLoop:
;

VarType:
U8 { $$ = new Node({U8, "u8"}); }
| U16 { $$ = new Node({U16, "u16"}); }
| U32 { $$ = new Node({U32, "u32"}); }
| U64 { $$ = new Node({U64, "u64"}); }
| I8 { $$ = new Node({I8, "i8"}); }
| I16 { $$ = new Node({I16, "i16"}); }
| I32 { $$ = new Node({I32, "i32"}); }
| I64 { $$ = new Node({I64, "i64"}); }
| F32 { $$ = new Node({F32, "f32"}); }
Int { $$ = new Node({Int, "int"}); }
| UInt { $$ = new Node({UInt, "uint"}); }
| F64 { $$ = new Node({F64, "f64"}); }
| Bool { $$ = new Node({Bool, "bool"}); }
| True { $$ = new Node({True, "true"}); }
| False { $$ = new Node({False, "false"}); }
| Str { $$ = new Node({Str, "str"}); }
;

Expand Down Expand Up @@ -170,6 +161,8 @@ UnaryExpression:

Expression:
Identifier { $$ = new Node({Identifier, $1}); }
| False { $$ = new Node({False, "false"}); }
| True { $$ = new Node({True, "true"}); }
| Number { $$ = new Node({Number, $1}); }
| String { $$ = new Node({String, $1}); }
| FunctionDeclaration { $$ = $1; }
Expand Down
62 changes: 1 addition & 61 deletions src/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@ VariableType::Type varTypeConvert(AbstractSyntaxTree *ast) {
auto token = dynamic_cast<Node *>(ast)->token;
static std::unordered_map<int, VariableType::Type> types = {
{Bool, VariableType::Bool},
{I32, VariableType::I32},
{I64, VariableType::I64},
{Int, VariableType::I64},
{Str, VariableType::Object},
};
if (types.find(token.type) == types.end())
Expand All @@ -22,18 +21,8 @@ VariableType::Type varTypeConvert(AbstractSyntaxTree *ast) {

VariableType::Type biggestType(VariableType::Type first, VariableType::Type second) {
switch (first) {
case VariableType::I32:
switch (second) {
case VariableType::I32:
return first;
case VariableType::I64:
return second;
default:
throw std::runtime_error("This should not be accessed!");
}
case VariableType::I64:
switch (second) {
case VariableType::I32:
case VariableType::I64:
return first;
default:
Expand All @@ -55,13 +44,6 @@ VariableType::Type deduceType(Program &program, Segment &segment, AbstractSyntax
case False:
return VariableType::Bool;
case Number: {
try {
std::stoi(token.value);
return VariableType::I32;
} catch (std::out_of_range &) {
goto long64;
}
long64:
try {
std::stol(token.value);
return VariableType::I64;
Expand Down Expand Up @@ -112,9 +94,6 @@ VariableType::Type deduceType(Program &program, Segment &segment, AbstractSyntax
#define TYPE_CASE(INS) \
case GenericInstruction::INS: { \
switch (type) { \
case VariableType::Bool: \
case VariableType::I32: \
return {Instruction::InstructionType::INS##I32}; \
case VariableType::I64: \
return {Instruction::InstructionType::INS##I64}; \
default: \
Expand All @@ -140,11 +119,6 @@ Instruction getInstructionWithType(GenericInstruction instruction, VariableType:
Instruction emitLoad(VariableType::Type type, const Token &token) {
switch (type) {
case VariableType::Bool:
case VariableType::I32:
return Instruction{
.type = Instruction::InstructionType::LoadI32,
.params = {.i32 = std::stoi(token.value)},
};
case VariableType::I64:
return Instruction{
.type = Instruction::InstructionType::LoadI64,
Expand All @@ -159,53 +133,20 @@ void typeCast(std::vector<Instruction> &instructions, VariableType::Type from, V
if (from == to)
return;
switch (from) {
case VariableType::I32:
switch (to) {
case VariableType::I64: {
if (instructions.back().type == Instruction::InstructionType::LoadI32) {
instructions.back().type = Instruction::InstructionType::LoadI64;
auto oldVal = instructions.back().params.i32;
instructions.back().params.i64 = oldVal;
return;
}
return instructions.push_back({.type = Instruction::InstructionType::ConvertI32toI64});
}
default:
throw std::runtime_error("Invalid type cast");
}
default:
throw std::runtime_error("Invalid type cast");
}
}

VariableType::Type getInstructionType(const Program &program, const Instruction &instruction) {
switch (instruction.type) {
case Instruction::InstructionType::EqualI32:
case Instruction::InstructionType::LessI32:
case Instruction::InstructionType::GreaterI32:
case Instruction::InstructionType::GreaterEqualI32:
case Instruction::InstructionType::LessEqualI32:
case Instruction::InstructionType::NotEqualI32:
case Instruction::InstructionType::EqualI64:
case Instruction::InstructionType::LessI64:
case Instruction::InstructionType::GreaterI64:
case Instruction::InstructionType::GreaterEqualI64:
case Instruction::InstructionType::LessEqualI64:
case Instruction::InstructionType::NotEqualI64:
return VariableType::Bool;
case Instruction::InstructionType::LoadI32:
case Instruction::InstructionType::AddI32:
case Instruction::InstructionType::SubI32:
case Instruction::InstructionType::MulI32:
case Instruction::InstructionType::DivI32:
case Instruction::InstructionType::ModI32:
case Instruction::InstructionType::IncrementI32:
case Instruction::InstructionType::DecrementI32:
case Instruction::InstructionType::StoreLocalI32:
case Instruction::InstructionType::LoadLocalI32:
case Instruction::InstructionType::StoreGlobalI32:
case Instruction::InstructionType::LoadGlobalI32:
return VariableType::I32;
case Instruction::InstructionType::LoadI64:
case Instruction::InstructionType::AddI64:
case Instruction::InstructionType::SubI64:
Expand All @@ -218,7 +159,6 @@ VariableType::Type getInstructionType(const Program &program, const Instruction
case Instruction::InstructionType::LoadLocalI64:
case Instruction::InstructionType::StoreGlobalI64:
case Instruction::InstructionType::LoadGlobalI64:
case Instruction::InstructionType::ConvertI32toI64:
return VariableType::I64;
case Instruction::InstructionType::LoadObject:
case Instruction::InstructionType::StoreLocalObject:
Expand Down
Loading

0 comments on commit f51b5fa

Please sign in to comment.