Skip to content

Commit cb5f3df

Browse files
committed
Feat: Implemented compiler
1 parent 35a1a27 commit cb5f3df

File tree

9 files changed

+323
-22
lines changed

9 files changed

+323
-22
lines changed

.vscode/launch.json

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
{
2+
// Use IntelliSense to learn about possible attributes.
3+
// Hover to view descriptions of existing attributes.
4+
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5+
"version": "0.2.0",
6+
"configurations": [
7+
{
8+
"type": "lldb",
9+
"request": "launch",
10+
"name": "Debug unit tests in library 'lucy'",
11+
"cargo": {
12+
"args": [
13+
"test",
14+
"--no-run",
15+
"--lib",
16+
"--package=lucy"
17+
],
18+
"filter": {
19+
"name": "lucy",
20+
"kind": "lib"
21+
}
22+
},
23+
"args": [],
24+
"cwd": "${workspaceFolder}"
25+
},
26+
{
27+
"type": "lldb",
28+
"request": "launch",
29+
"name": "Debug executable 'lucy-cli'",
30+
"cargo": {
31+
"args": [
32+
"build",
33+
"--bin=lucy-cli",
34+
"--package=lucy-cli"
35+
],
36+
"filter": {
37+
"name": "lucy-cli",
38+
"kind": "bin"
39+
}
40+
},
41+
"args": [],
42+
"cwd": "${workspaceFolder}"
43+
},
44+
{
45+
"type": "lldb",
46+
"request": "launch",
47+
"name": "Debug unit tests in executable 'lucy-cli'",
48+
"cargo": {
49+
"args": [
50+
"test",
51+
"--no-run",
52+
"--bin=lucy-cli",
53+
"--package=lucy-cli"
54+
],
55+
"filter": {
56+
"name": "lucy-cli",
57+
"kind": "bin"
58+
}
59+
},
60+
"args": [],
61+
"cwd": "${workspaceFolder}"
62+
}
63+
]
64+
}

lucy-cli/src/main.rs

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,32 @@
1+
use lucy::logger::log::{Log, Logger};
12
use lucy::parser::pretokenizer::PreTokenizer;
2-
use lucy::parser::tokenizer::{Tokenizer};
3+
use lucy::parser::tokenizer::Tokenizer;
4+
use lucy::compiler::compiler::LucyCompiler;
35

46
fn main() {
57
let input =
68
"
7-
mov eax, 10
8-
mov ebx, 20
9-
mov edx, 0b0010101
10-
mov ecx, 0x10 ;should be 16
11-
add eax, ebx
12-
inc ebx
13-
add eax, ebx
14-
dmp eax
15-
dmp 'c'
16-
ret
17-
mov ebx, \"Hello World\" ; This is a comment!
9+
jmp main
10+
dmp \"Hello world!\"
11+
:main
12+
mov edi, 0
13+
:loop
14+
1815
";
1916

2017
let mut pretokenizer = PreTokenizer::new(String::from(input));
2118
let _ = pretokenizer.parse();
2219
let mut tokenizer = Tokenizer::new(pretokenizer);
20+
let tokens = tokenizer.tokenize();
2321

24-
for string in tokenizer.tokenize() {
25-
println!("{}", string);
22+
// for tkn in tokens {
23+
// Log::info(format!("{}", tkn));
24+
// }
25+
26+
let compiled = LucyCompiler::compile(tokens);
27+
28+
for c in compiled {
29+
Log::info(format!("{:?} {:?}", c.instruction, c.arguments[0].typ));
2630
}
31+
2732
}

lucy/src/compiler.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pub mod compiler;

lucy/src/compiler/compiler.rs

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
use std::{collections::HashMap, collections::VecDeque};
2+
use crate::{core::{data::{AnyData, DataType}, instructions::Operations}, logger::log::{Log, Logger}, parser::token::TokenType};
3+
4+
type Program = Vec<LucyInstruction>;
5+
6+
pub struct OperationParameter {
7+
pub typ: DataType,
8+
pub data: AnyData
9+
}
10+
11+
pub struct LucyInstruction {
12+
pub instruction: Operations,
13+
pub arguments: Vec<OperationParameter>
14+
}
15+
16+
pub struct LucyCompiler {}
17+
18+
impl LucyCompiler {
19+
pub fn compile(tokens: &Vec<TokenType>) -> Program {
20+
21+
let checkpoints = LucyCompiler::index_checkpoints(tokens);
22+
let mut program: Program = Program::new();
23+
let mut args: VecDeque<OperationParameter> = VecDeque::new();
24+
let mut queued_instruction: Operations = Operations::COUNT;
25+
26+
for token in tokens {
27+
match token {
28+
TokenType::CHECKPOINT(_) => continue,
29+
TokenType::COMMENT(_) => continue,
30+
TokenType::GOTO(checkpoint) => {
31+
match checkpoints.get(checkpoint) {
32+
Some(i) => {
33+
args.push_back(
34+
OperationParameter { typ: DataType::Int64, data: AnyData::from(*i as i64) }
35+
);
36+
37+
},
38+
None => {},
39+
}
40+
},
41+
TokenType::DATA(typ, data) => {
42+
unsafe {
43+
match typ {
44+
DataType::Uint32 => args.push_back(
45+
OperationParameter { typ: DataType::Uint32, data: AnyData::from(data.uint32) }
46+
),
47+
DataType::Uint64 => args.push_back(
48+
OperationParameter { typ: DataType::Uint64, data: AnyData::from(data.uint64) }
49+
),
50+
DataType::Int32 => args.push_back(
51+
OperationParameter { typ: DataType::Int32, data: AnyData::from(data.int32) }
52+
),
53+
DataType::Int64 => args.push_back(
54+
OperationParameter { typ: DataType::Int64, data: AnyData::from(data.int64) }
55+
),
56+
DataType::Float => args.push_back(
57+
OperationParameter { typ: DataType::Float, data: AnyData::from(data.float) }
58+
),
59+
DataType::Double => args.push_back(
60+
OperationParameter { typ: DataType::Double, data: AnyData::from(data.double) }
61+
),
62+
DataType::String => args.push_back(
63+
OperationParameter { typ: DataType::String, data: AnyData::from(&data.string.to_string()) }
64+
),
65+
DataType::Char => args.push_back(
66+
OperationParameter { typ: DataType::Char, data: AnyData::from(data.char) }
67+
),
68+
DataType::Register => args.push_back(
69+
OperationParameter { typ: DataType::Register, data: AnyData::from(data.register) }
70+
),
71+
}
72+
}
73+
},
74+
TokenType::REGISTER(reg) => args.push_back(
75+
OperationParameter { typ: DataType::Register, data: AnyData::from(*reg) }
76+
),
77+
TokenType::INSTRUCTION(ins) => {
78+
if queued_instruction != Operations::COUNT {
79+
let mut vec: Vec<OperationParameter> = Vec::with_capacity(args.len());
80+
81+
while args.len() > 0 {
82+
vec.push(args.pop_front().unwrap());
83+
}
84+
85+
program.push(
86+
LucyInstruction { instruction: queued_instruction, arguments: vec }
87+
);
88+
}
89+
queued_instruction = *ins;
90+
},
91+
}
92+
}
93+
94+
if args.len() > 0 {
95+
let mut vec: Vec<OperationParameter> = Vec::with_capacity(args.len());
96+
97+
while args.len() > 0 {
98+
vec.push(args.pop_front().unwrap());
99+
}
100+
101+
program.push(
102+
LucyInstruction { instruction: queued_instruction, arguments: vec }
103+
);
104+
105+
queued_instruction = Operations::COUNT;
106+
}
107+
108+
program
109+
}
110+
111+
fn index_checkpoints(tokens: &Vec<TokenType>) -> HashMap<String, usize> {
112+
let mut idx: usize = 0;
113+
let mut checkpoints: HashMap<String, usize> = HashMap::new();
114+
115+
for tkn in tokens {
116+
match tkn {
117+
TokenType::CHECKPOINT(cp) => {
118+
let mut chars= cp.chars();
119+
chars.next();
120+
121+
checkpoints.insert(String::from(chars.as_str()), idx);
122+
},
123+
TokenType::INSTRUCTION(_) => {
124+
idx += 1;
125+
continue;
126+
},
127+
_ => continue
128+
}
129+
}
130+
131+
checkpoints
132+
}
133+
}

lucy/src/core/data.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,22 @@ impl From<u32> for AnyData {
3535
}
3636
}
3737

38+
impl From<u64> for AnyData {
39+
fn from(val: u64) -> Self {
40+
AnyData {
41+
uint64: val
42+
}
43+
}
44+
}
45+
46+
impl From<i32> for AnyData {
47+
fn from(val: i32) -> Self {
48+
AnyData {
49+
int32: val
50+
}
51+
}
52+
}
53+
3854
impl From<i64> for AnyData {
3955
fn from(val: i64) -> Self {
4056
AnyData {
@@ -43,6 +59,22 @@ impl From<i64> for AnyData {
4359
}
4460
}
4561

62+
impl From<f32> for AnyData {
63+
fn from(val: f32) -> Self {
64+
AnyData {
65+
float: val
66+
}
67+
}
68+
}
69+
70+
impl From<f64> for AnyData {
71+
fn from(val: f64) -> Self {
72+
AnyData {
73+
double: val
74+
}
75+
}
76+
}
77+
4678
impl From<&String> for AnyData {
4779
fn from(val: &String) -> Self {
4880
let str = String::from(val);
@@ -53,6 +85,22 @@ impl From<&String> for AnyData {
5385
}
5486
}
5587

88+
impl From<char> for AnyData {
89+
fn from(val: char) -> Self {
90+
AnyData {
91+
char: val
92+
}
93+
}
94+
}
95+
96+
impl From<Register> for AnyData {
97+
fn from(val: Register) -> Self {
98+
AnyData {
99+
register: val
100+
}
101+
}
102+
}
103+
56104
pub union Address {
57105
pub uint64: i64,
58106
pub register: Register

lucy/src/core/instructions.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use num_traits::FromPrimitive;
55

66
pub type Any = AnyData;
77

8-
#[derive(Debug, FromPrimitive)]
8+
#[derive(Debug, FromPrimitive, Clone, Copy, PartialEq)]
99
pub enum Operations {
1010
MOV,
1111
PUSH,
@@ -49,6 +49,24 @@ impl Operations {
4949

5050
instruction.contains(&primitive)
5151
}
52+
53+
pub fn from_string(name: &String) -> Option<Operations> {
54+
let mut instruction: Vec<String> = Vec::with_capacity(Operations::COUNT as usize);
55+
56+
for inst in 0..(Operations::COUNT as i32) {
57+
let op: Operations = FromPrimitive::from_i32(inst).unwrap();
58+
59+
instruction.push(format!("{:?}", op))
60+
}
61+
62+
let primitive = name.to_uppercase();
63+
64+
let i = instruction.iter().position(|ins| &primitive == ins);
65+
match i {
66+
Some(idx) => FromPrimitive::from_usize(idx),
67+
None => None,
68+
}
69+
}
5270
}
5371

5472
pub trait OperationImpl {

lucy/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
pub mod parser;
22
pub mod core;
3-
pub mod logger;
3+
pub mod logger;
4+
pub mod compiler;

lucy/src/logger/log.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
trait Logger {
1+
pub trait Logger {
22
fn debug(message: String);
33
fn info(message: String);
44
fn warn(message: String);

0 commit comments

Comments
 (0)