|
|
@ -1,7 +1,6 @@
|
|
|
|
use core::panic;
|
|
|
|
use core::panic;
|
|
|
|
use std::collections::HashMap;
|
|
|
|
use std::collections::HashMap;
|
|
|
|
use std::env;
|
|
|
|
use std::env;
|
|
|
|
use std::fmt::format;
|
|
|
|
|
|
|
|
use std::fs;
|
|
|
|
use std::fs;
|
|
|
|
use std::iter::Peekable;
|
|
|
|
use std::iter::Peekable;
|
|
|
|
use std::process::exit;
|
|
|
|
use std::process::exit;
|
|
|
@ -24,25 +23,25 @@ enum TokenizerState
|
|
|
|
Comment,
|
|
|
|
Comment,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Debug,Clone,Copy)]
|
|
|
|
#[derive(Debug,Clone,Copy, PartialEq)]
|
|
|
|
enum Datatype
|
|
|
|
enum Datatype
|
|
|
|
{
|
|
|
|
{
|
|
|
|
Int,
|
|
|
|
Int,
|
|
|
|
String,
|
|
|
|
String,
|
|
|
|
Bool,
|
|
|
|
Bool,
|
|
|
|
//Pointer,
|
|
|
|
//Pointer,
|
|
|
|
Any,
|
|
|
|
// Any,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl PartialEq for Datatype
|
|
|
|
// impl PartialEq for Datatype
|
|
|
|
{
|
|
|
|
// {
|
|
|
|
fn eq(&self, other: &Self) -> bool
|
|
|
|
// fn eq(&self, other: &Self) -> bool
|
|
|
|
{
|
|
|
|
// {
|
|
|
|
core::mem::discriminant(self) == core::mem::discriminant(&Datatype::Any) ||
|
|
|
|
// core::mem::discriminant(self) == core::mem::discriminant(&Datatype::Any) ||
|
|
|
|
core::mem::discriminant(other) == core::mem::discriminant(&Datatype::Any) ||
|
|
|
|
// core::mem::discriminant(other) == core::mem::discriminant(&Datatype::Any) ||
|
|
|
|
core::mem::discriminant(self) == core::mem::discriminant(other)
|
|
|
|
// core::mem::discriminant(self) == core::mem::discriminant(other)
|
|
|
|
}
|
|
|
|
// }
|
|
|
|
}
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
#[derive(Debug)]
|
|
|
|
struct Function
|
|
|
|
struct Function
|
|
|
@ -78,20 +77,23 @@ enum Operation
|
|
|
|
Apply(String, String, i32, i32),
|
|
|
|
Apply(String, String, i32, i32),
|
|
|
|
Depth(i32, i32),
|
|
|
|
Depth(i32, i32),
|
|
|
|
QueueDiagnostic(i32, i32),
|
|
|
|
QueueDiagnostic(i32, i32),
|
|
|
|
|
|
|
|
Interrupt(i32, i32),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn main()
|
|
|
|
fn main()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
let intrinsics: HashMap<&str, (Vec<Datatype>, Vec<Datatype>)> = HashMap::from(
|
|
|
|
let intrinsics: HashMap<&str, (Vec<Datatype>, Vec<Datatype>)> = HashMap::from(
|
|
|
|
[
|
|
|
|
[
|
|
|
|
("print", (Vec::from([Datatype::Any]), Vec::new())),
|
|
|
|
("print", (Vec::from([Datatype::String]), Vec::new())),
|
|
|
|
("println", (Vec::from([Datatype::Any]), Vec::new())),
|
|
|
|
("println", (Vec::from([Datatype::String]), Vec::new())),
|
|
|
|
|
|
|
|
("intToStr", (Vec::from([Datatype::Int]), Vec::from([Datatype::String]))),
|
|
|
|
("-", (Vec::from([Datatype::Int, Datatype::Int]), Vec::from([Datatype::Int]))),
|
|
|
|
("-", (Vec::from([Datatype::Int, Datatype::Int]), Vec::from([Datatype::Int]))),
|
|
|
|
("+", (Vec::from([Datatype::Int, Datatype::Int]), Vec::from([Datatype::Int]))),
|
|
|
|
("+", (Vec::from([Datatype::Int, Datatype::Int]), Vec::from([Datatype::Int]))),
|
|
|
|
("*", (Vec::from([Datatype::Int, Datatype::Int]), Vec::from([Datatype::Int]))),
|
|
|
|
("*", (Vec::from([Datatype::Int, Datatype::Int]), Vec::from([Datatype::Int]))),
|
|
|
|
("<", (Vec::from([Datatype::Int, Datatype::Int]), Vec::from([Datatype::Bool]))),
|
|
|
|
("<", (Vec::from([Datatype::Int, Datatype::Int]), Vec::from([Datatype::Bool]))),
|
|
|
|
(">", (Vec::from([Datatype::Int, Datatype::Int]), Vec::from([Datatype::Bool]))),
|
|
|
|
(">", (Vec::from([Datatype::Int, Datatype::Int]), Vec::from([Datatype::Bool]))),
|
|
|
|
(">=", (Vec::from([Datatype::Int, Datatype::Int]), Vec::from([Datatype::Bool]))),
|
|
|
|
(">=", (Vec::from([Datatype::Int, Datatype::Int]), Vec::from([Datatype::Bool]))),
|
|
|
|
|
|
|
|
("<=", (Vec::from([Datatype::Int, Datatype::Int]), Vec::from([Datatype::Bool]))),
|
|
|
|
("==", (Vec::from([Datatype::Int, Datatype::Int]), Vec::from([Datatype::Bool]))),
|
|
|
|
("==", (Vec::from([Datatype::Int, Datatype::Int]), Vec::from([Datatype::Bool]))),
|
|
|
|
("!=", (Vec::from([Datatype::Int, Datatype::Int]), Vec::from([Datatype::Bool]))),
|
|
|
|
("!=", (Vec::from([Datatype::Int, Datatype::Int]), Vec::from([Datatype::Bool]))),
|
|
|
|
("&&", (Vec::from([Datatype::Bool, Datatype::Bool]), Vec::from([Datatype::Bool]))),
|
|
|
|
("&&", (Vec::from([Datatype::Bool, Datatype::Bool]), Vec::from([Datatype::Bool]))),
|
|
|
@ -121,7 +123,7 @@ fn main()
|
|
|
|
for f in fs::read_dir(&args[2]).unwrap()
|
|
|
|
for f in fs::read_dir(&args[2]).unwrap()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
let f = f.unwrap();
|
|
|
|
let f = f.unwrap();
|
|
|
|
let file_content = fs::read_to_string(f.path()).unwrap();
|
|
|
|
let file_content = fs::read_to_string(f.path()).unwrap().replace("\r\n", "\n");
|
|
|
|
println!("========NOW TESTING {:?}========", f.path());
|
|
|
|
println!("========NOW TESTING {:?}========", f.path());
|
|
|
|
match compile(&file_content, &intrinsics, interpret, debug)
|
|
|
|
match compile(&file_content, &intrinsics, interpret, debug)
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -246,34 +248,70 @@ fn merge_assemblies(data: &mut AssemblyData, data2: AssemblyData)
|
|
|
|
|
|
|
|
|
|
|
|
const ASSEMBLY_LINUX_X64_QUEUE_LENGTH: u32 = 1024;
|
|
|
|
const ASSEMBLY_LINUX_X64_QUEUE_LENGTH: u32 = 1024;
|
|
|
|
const ASSEMBLY_LINUX_X64_HEADER: &str = "format ELF64 executable 3\n";
|
|
|
|
const ASSEMBLY_LINUX_X64_HEADER: &str = "format ELF64 executable 3\n";
|
|
|
|
const ASSEMBLY_LINUX_X64_TRY_RESET_QUEUE: &str = "\tcmp r8, r9\n\tcmove r8, r10\n\tcmove r9, r10\n";
|
|
|
|
const ASSEMBLY_LINUX_X64_TRY_RESET_QUEUE: &str = "\tcmp r12, r13\n\tcmove r12, r14\n\tcmove r13, r14\n";
|
|
|
|
const ASSEMBLY_LINUX_X64_EXIT: &str = "\tmov rax, 60\n\tmov rdi, 0\n\tsyscall\n";
|
|
|
|
const ASSEMBLY_LINUX_X64_EXIT: &str = "\tmov rax, 60\n\tmov rdi, 0\n\tsyscall\n";
|
|
|
|
|
|
|
|
const ASSEMBLY_LINUX_X64_DYNAMIC_DATA_LENGTH: u32 = 16384;
|
|
|
|
|
|
|
|
|
|
|
|
fn generate_assembly_linux_x64(operations: &Vec<Operation>, functions: &Vec<Function>, intrinsics: &HashMap<&str, (Vec<Datatype>, Vec<Datatype>)>, arrays: &Vec<Arr>, debug: bool) -> Result<(), std::io::Error>
|
|
|
|
fn generate_assembly_linux_x64(operations: &Vec<Operation>, functions: &Vec<Function>, intrinsics: &HashMap<&str, (Vec<Datatype>, Vec<Datatype>)>, arrays: &Vec<Arr>, debug: bool) -> Result<(), std::io::Error>
|
|
|
|
{
|
|
|
|
{
|
|
|
|
let mut data = AssemblyData
|
|
|
|
let mut data = AssemblyData
|
|
|
|
{
|
|
|
|
{
|
|
|
|
arrays: format!("segment readable writeable\n\tqueue: rq {}\n", ASSEMBLY_LINUX_X64_QUEUE_LENGTH),
|
|
|
|
arrays: format!("segment readable writeable\n\tqueue: rq {}\n\tdynamic: rb {}\n", ASSEMBLY_LINUX_X64_QUEUE_LENGTH, ASSEMBLY_LINUX_X64_DYNAMIC_DATA_LENGTH),
|
|
|
|
strings: String::from("segment readable\n"),
|
|
|
|
strings: String::from("segment readable\n\tnewline: db 10\n"),
|
|
|
|
code: String::from("segment executable\n"),
|
|
|
|
code: String::from("segment executable\n"),
|
|
|
|
};
|
|
|
|
};
|
|
|
|
for array in arrays
|
|
|
|
for array in arrays
|
|
|
|
{
|
|
|
|
{
|
|
|
|
data.arrays += format!("\tarr_{}: rq {}\n", array.name, array.length).as_str();
|
|
|
|
data.arrays += format!("\tarr_{}: rq {}\n", array.name, array.length).as_str();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
data.code += "_start:\n";
|
|
|
|
|
|
|
|
merge_assemblies(&mut data, generate_assembly_linux_x64_block(operations, functions, intrinsics, arrays, debug));
|
|
|
|
|
|
|
|
data.code += ASSEMBLY_LINUX_X64_EXIT;
|
|
|
|
for function in functions
|
|
|
|
for function in functions
|
|
|
|
{
|
|
|
|
{
|
|
|
|
merge_assemblies(&mut data, generate_assembly_linux_x64_function(function.name.as_str(), &function.content, functions, intrinsics, arrays, debug));
|
|
|
|
merge_assemblies(&mut data, generate_assembly_linux_x64_function(function.name.as_str(), &function.content, functions, intrinsics, arrays, debug));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
merge_assemblies(&mut data, generate_assembly_linux_x64_function("_start", operations, functions, intrinsics, arrays, debug));
|
|
|
|
|
|
|
|
data.code += ASSEMBLY_LINUX_X64_EXIT;
|
|
|
|
if data.code.contains("call intToStr")
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
data.code += "intToStr:\n";
|
|
|
|
|
|
|
|
data.code += "\tmov rax, rdi\n";
|
|
|
|
|
|
|
|
data.code += "\tmov rsi, 10\n";
|
|
|
|
|
|
|
|
data.code += "\txor rdi, rdi\n";
|
|
|
|
|
|
|
|
data.code += "\txor rdx, rdx\n";
|
|
|
|
|
|
|
|
data.code += "\tintToStringLoop:\n";
|
|
|
|
|
|
|
|
data.code += "\t\tdiv rsi\n";
|
|
|
|
|
|
|
|
data.code += "\t\tadd rdx, 48\n";
|
|
|
|
|
|
|
|
data.code += "\t\tpush rdx\n";
|
|
|
|
|
|
|
|
data.code += "\t\txor rdx, rdx\n";
|
|
|
|
|
|
|
|
data.code += "\t\tinc rdi\n";
|
|
|
|
|
|
|
|
data.code += "\t\tcmp rax, 0\n";
|
|
|
|
|
|
|
|
data.code += "\t\tjne intToStringLoop\n";
|
|
|
|
|
|
|
|
data.code += "\tmov rsi, r15\n";
|
|
|
|
|
|
|
|
data.code += "\tmov qword [dynamic+r15], rdi\n";
|
|
|
|
|
|
|
|
data.code += "\tadd r15, 8\n";
|
|
|
|
|
|
|
|
data.code += "\tintToStringBuildLoop:\n";
|
|
|
|
|
|
|
|
data.code += "\t\tcmp rdi, 0\n";
|
|
|
|
|
|
|
|
data.code += "\t\tje intToStringBuildLoopEnd\n";
|
|
|
|
|
|
|
|
data.code += "\t\tpop rax\n";
|
|
|
|
|
|
|
|
data.code += "\t\tmov byte [dynamic+r15], byte al\n";
|
|
|
|
|
|
|
|
data.code += "\t\tinc r15\n";
|
|
|
|
|
|
|
|
data.code += "\t\tdec rdi\n";
|
|
|
|
|
|
|
|
data.code += "\t\tjmp intToStringBuildLoop\n";
|
|
|
|
|
|
|
|
data.code += "\tintToStringBuildLoopEnd:\n";
|
|
|
|
|
|
|
|
data.code += "\tmov byte [dynamic+r15], 0\n";
|
|
|
|
|
|
|
|
data.code += "\tinc r15\n";
|
|
|
|
|
|
|
|
data.code += "\tlea rax, [dynamic+rsi]\n";
|
|
|
|
|
|
|
|
data.code += "\tret\n";
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return fs::write("out.asm", format!("{}{}{}{}", ASSEMBLY_LINUX_X64_HEADER, data.code, data.arrays, data.strings));
|
|
|
|
return fs::write("out.asm", format!("{}{}{}{}", ASSEMBLY_LINUX_X64_HEADER, data.code, data.arrays, data.strings));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// r8: head
|
|
|
|
// r12: head
|
|
|
|
// r9: tail
|
|
|
|
// r13: tail
|
|
|
|
// r10: base
|
|
|
|
// r14: base
|
|
|
|
|
|
|
|
// r15: dynamic end
|
|
|
|
|
|
|
|
|
|
|
|
fn generate_assembly_linux_x64_block(operations: &Vec<Operation>, functions: &Vec<Function>, intrinsics: &HashMap<&str, (Vec<Datatype>, Vec<Datatype>)>, arrays: &Vec<Arr>, debug: bool) -> AssemblyData
|
|
|
|
fn generate_assembly_linux_x64_block(operations: &Vec<Operation>, functions: &Vec<Function>, intrinsics: &HashMap<&str, (Vec<Datatype>, Vec<Datatype>)>, arrays: &Vec<Arr>, debug: bool) -> AssemblyData
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -290,7 +328,7 @@ fn generate_assembly_linux_x64_block(operations: &Vec<Operation>, functions: &Ve
|
|
|
|
Operation::Dequeue(line, col) =>
|
|
|
|
Operation::Dequeue(line, col) =>
|
|
|
|
{
|
|
|
|
{
|
|
|
|
data.code += format!("\t;;deq {}:{}\n", line, col).as_str();
|
|
|
|
data.code += format!("\t;;deq {}:{}\n", line, col).as_str();
|
|
|
|
data.code += "\tinc r8\n";
|
|
|
|
data.code += "\tinc r12\n";
|
|
|
|
data.code += ASSEMBLY_LINUX_X64_TRY_RESET_QUEUE;
|
|
|
|
data.code += ASSEMBLY_LINUX_X64_TRY_RESET_QUEUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Operation::Enqueue(datatype, value, line, col) =>
|
|
|
|
Operation::Enqueue(datatype, value, line, col) =>
|
|
|
@ -298,50 +336,321 @@ fn generate_assembly_linux_x64_block(operations: &Vec<Operation>, functions: &Ve
|
|
|
|
data.code += format!("\t;;enq {:?} {} {}:{}\n", datatype, value, line, col).as_str();
|
|
|
|
data.code += format!("\t;;enq {:?} {} {}:{}\n", datatype, value, line, col).as_str();
|
|
|
|
match datatype
|
|
|
|
match datatype
|
|
|
|
{
|
|
|
|
{
|
|
|
|
Datatype::Int | Datatype::Bool =>
|
|
|
|
Datatype::Int =>
|
|
|
|
{
|
|
|
|
{
|
|
|
|
data.code += format!("\tmov qword [queue+r9], {}\n", value).as_str();
|
|
|
|
data.code += format!("\tmov qword [queue+8*r13], {}\n", value).as_str();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
Datatype::Bool =>
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
data.code += format!("\tmov qword [queue+8*r13], {}\n", if value == "true" { 1 } else { 0 }).as_str();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
Datatype::String =>
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
data.strings += format!("\tstr_{}_{}: dq {}, \"{}\", 0\n", line, col, value.len(), value).as_str();
|
|
|
|
|
|
|
|
data.code += format!("\tlea rax, [str_{}_{}]\n", line, col).as_str();
|
|
|
|
|
|
|
|
data.code += "\tmov [queue+8*r13], rax\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => todo!("enq {:?}", datatype)
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
data.code += "\tinc r9\n";
|
|
|
|
data.code += "\tinc r13\n";
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
Operation::Requeue(line, col) =>
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
data.code += format!("\t;;req {}:{}\n", line, col).as_str();
|
|
|
|
|
|
|
|
data.code += "\tmov rax, [queue+8*r12]\n";
|
|
|
|
|
|
|
|
data.code += "\tmov [queue+8*r13], rax\n";
|
|
|
|
|
|
|
|
data.code += "\tinc r12\n";
|
|
|
|
|
|
|
|
data.code += "\tinc r13\n";
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
Operation::Swap(line, col) =>
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
data.code += format!("\t;;swp {}:{}\n", line, col).as_str();
|
|
|
|
|
|
|
|
data.code += "\tmov rax, [queue+8*r12]\n";
|
|
|
|
|
|
|
|
data.code += "\tmov rbx, [queue+8*r12+8]\n";
|
|
|
|
|
|
|
|
data.code += "\tadd r12, 2\n";
|
|
|
|
|
|
|
|
data.code += ASSEMBLY_LINUX_X64_TRY_RESET_QUEUE;
|
|
|
|
|
|
|
|
data.code += "\tmov [queue+8*r13], rbx\n";
|
|
|
|
|
|
|
|
data.code += "\tmov [queue+8*r13+8], rax\n";
|
|
|
|
|
|
|
|
data.code += "\tadd r13, 2\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Operation::While(while_operations, line, col) =>
|
|
|
|
Operation::While(while_operations, line, col) =>
|
|
|
|
{
|
|
|
|
{
|
|
|
|
data.code += format!("\t;;while {}:{}\n", line, col).as_str();
|
|
|
|
data.code += format!("\t;;while {}:{}\n", line, col).as_str();
|
|
|
|
data.code += format!("while_{}_{}:\n", line, col).as_str();
|
|
|
|
data.code += "\tcmp qword [queue+8*r12], 0\n";
|
|
|
|
data.code += "\tcmp qword [queue+r8], 0\n";
|
|
|
|
|
|
|
|
data.code += format!("\tje while_{}_{}_end\n", line, col).as_str();
|
|
|
|
data.code += format!("\tje while_{}_{}_end\n", line, col).as_str();
|
|
|
|
data.code += "\tinc r8\n";
|
|
|
|
data.code += format!("while_{}_{}:\n", line, col).as_str();
|
|
|
|
|
|
|
|
data.code += "\tinc r12\n";
|
|
|
|
data.code += ASSEMBLY_LINUX_X64_TRY_RESET_QUEUE;
|
|
|
|
data.code += ASSEMBLY_LINUX_X64_TRY_RESET_QUEUE;
|
|
|
|
merge_assemblies(&mut data, generate_assembly_linux_x64_block(while_operations, functions, intrinsics, arrays, debug));
|
|
|
|
merge_assemblies(&mut data, generate_assembly_linux_x64_block(while_operations, functions, intrinsics, arrays, debug));
|
|
|
|
data.code += format!("\tjmp while_{}_{}\n", line, col).as_str();
|
|
|
|
data.code += "\tcmp qword [queue+8*r12], 0\n";
|
|
|
|
|
|
|
|
data.code += format!("\tjne while_{}_{}\n", line, col).as_str();
|
|
|
|
data.code += format!("while_{}_{}_end:\n", line, col).as_str();
|
|
|
|
data.code += format!("while_{}_{}_end:\n", line, col).as_str();
|
|
|
|
data.code += "\tinc r8\n";
|
|
|
|
data.code += "\tinc r12\n";
|
|
|
|
data.code += ASSEMBLY_LINUX_X64_TRY_RESET_QUEUE;
|
|
|
|
data.code += ASSEMBLY_LINUX_X64_TRY_RESET_QUEUE;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
Operation::If(if_operations, maybe_else_operations, line, col) =>
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
data.code += format!("\t;;if {}:{}\n", line, col).as_str();
|
|
|
|
|
|
|
|
data.code += "\tcmp qword [queue+8*r12], 0\n";
|
|
|
|
|
|
|
|
data.code += format!("\tje else_{}_{}\n", line, col).as_str();
|
|
|
|
|
|
|
|
data.code += "\tinc r12\n";
|
|
|
|
|
|
|
|
data.code += ASSEMBLY_LINUX_X64_TRY_RESET_QUEUE;
|
|
|
|
|
|
|
|
merge_assemblies(&mut data, generate_assembly_linux_x64_block(if_operations, functions, intrinsics, arrays, debug));
|
|
|
|
|
|
|
|
data.code += format!("\tjmp if_{}_{}_end\n", line, col).as_str();
|
|
|
|
|
|
|
|
data.code += format!("else_{}_{}:\n", line, col).as_str();
|
|
|
|
|
|
|
|
data.code += "\tinc r12\n";
|
|
|
|
|
|
|
|
data.code += ASSEMBLY_LINUX_X64_TRY_RESET_QUEUE;
|
|
|
|
|
|
|
|
if let Some(else_operations) = maybe_else_operations
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
merge_assemblies(&mut data, generate_assembly_linux_x64_block(else_operations, functions, intrinsics, arrays, debug));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
data.code += format!("if_{}_{}_end:\n", line, col).as_str();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Operation::Dup(line, col) =>
|
|
|
|
Operation::Dup(line, col) =>
|
|
|
|
{
|
|
|
|
{
|
|
|
|
data.code += format!("\t;;dup {}:{}\n", line, col).as_str();
|
|
|
|
data.code += format!("\t;;dup {}:{}\n", line, col).as_str();
|
|
|
|
data.code += "\tmov qword [queue+r9], [queue+r8]\n";
|
|
|
|
data.code += "\tmov rax, [queue+8*r12]\n";
|
|
|
|
data.code += "\tinc r9\n";
|
|
|
|
data.code += "\tmov [queue+8*r13], rax\n";
|
|
|
|
|
|
|
|
data.code += "\tinc r13\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Operation::Intrinsic(name, line, col) =>
|
|
|
|
Operation::Intrinsic(name, line, col) =>
|
|
|
|
{
|
|
|
|
{
|
|
|
|
data.code += format!("\t;;intrinsic {} {}:{}", name, line, col).as_str();
|
|
|
|
data.code += format!("\t;;intrinsic {} {}:{}\n", name, line, col).as_str();
|
|
|
|
match name.as_str()
|
|
|
|
match name.as_str()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
"print" =>
|
|
|
|
"print" =>
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// For now printing numbers directly is unsupported
|
|
|
|
// For now printing numbers directly is unsupported
|
|
|
|
data.code += "\trax, 1\n";
|
|
|
|
data.code += "\tmov rax, 1\n";
|
|
|
|
data.code += "\trdi, 1\n";
|
|
|
|
data.code += "\tmov rdi, 1\n";
|
|
|
|
data.code += "\tmov rsi, [queue+r8]\n";
|
|
|
|
// load address
|
|
|
|
data.code += "\tmov "
|
|
|
|
data.code += "\tmov rsi, [queue+8*r12]\n";
|
|
|
|
|
|
|
|
// size
|
|
|
|
|
|
|
|
data.code += "\tmov rdx, [rsi]\n";
|
|
|
|
|
|
|
|
// data
|
|
|
|
|
|
|
|
data.code += "\tlea rsi, [rsi+8]\n";
|
|
|
|
|
|
|
|
// incorporate the null byte
|
|
|
|
|
|
|
|
data.code += "\tinc rdx\n";
|
|
|
|
|
|
|
|
data.code += "\tsyscall\n";
|
|
|
|
|
|
|
|
// TODO: factor this out
|
|
|
|
|
|
|
|
data.code += "\tinc r12\n";
|
|
|
|
|
|
|
|
data.code += ASSEMBLY_LINUX_X64_TRY_RESET_QUEUE;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
"println" =>
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
// For now printing numbers directly is unsupported
|
|
|
|
|
|
|
|
data.code += "\tmov rax, 1\n";
|
|
|
|
|
|
|
|
data.code += "\tmov rdi, 1\n";
|
|
|
|
|
|
|
|
// load address
|
|
|
|
|
|
|
|
data.code += "\tmov rsi, [queue+8*r12]\n";
|
|
|
|
|
|
|
|
// size
|
|
|
|
|
|
|
|
data.code += "\tmov rdx, [rsi]\n";
|
|
|
|
|
|
|
|
// data
|
|
|
|
|
|
|
|
data.code += "\tlea rsi, [rsi+8]\n";
|
|
|
|
|
|
|
|
// incorporate the null byte
|
|
|
|
|
|
|
|
data.code += "\tinc rdx\n";
|
|
|
|
|
|
|
|
data.code += "\tsyscall\n";
|
|
|
|
|
|
|
|
// TODO: factor this out
|
|
|
|
|
|
|
|
data.code += "\tinc r12\n";
|
|
|
|
|
|
|
|
data.code += ASSEMBLY_LINUX_X64_TRY_RESET_QUEUE;
|
|
|
|
|
|
|
|
// TODO: Don't syscall twice
|
|
|
|
|
|
|
|
data.code += "\tmov rax, 1\n";
|
|
|
|
|
|
|
|
data.code += "\tlea rsi, [newline]\n";
|
|
|
|
|
|
|
|
data.code += "\tmov rdx, 1\n";
|
|
|
|
|
|
|
|
data.code += "\tsyscall\n";
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
"intToStr" =>
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
data.code += "\tmov qword rdi, [queue+8*r12]\n";
|
|
|
|
|
|
|
|
data.code += "\tinc r12\n";
|
|
|
|
|
|
|
|
data.code += ASSEMBLY_LINUX_X64_TRY_RESET_QUEUE;
|
|
|
|
|
|
|
|
data.code += "\tcall intToStr\n";
|
|
|
|
|
|
|
|
data.code += "\tmov [queue+8*r13], rax\n";
|
|
|
|
|
|
|
|
data.code += "\tinc r13\n";
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
"-" =>
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
data.code += "\tmov qword rax, [queue+8*r12]\n";
|
|
|
|
|
|
|
|
data.code += "\tinc r12\n";
|
|
|
|
|
|
|
|
data.code += "\tmov qword rbx, [queue+8*r12]\n";
|
|
|
|
|
|
|
|
data.code += "\tinc r12\n";
|
|
|
|
|
|
|
|
data.code += ASSEMBLY_LINUX_X64_TRY_RESET_QUEUE;
|
|
|
|
|
|
|
|
data.code += "\tsub rax, rbx\n";
|
|
|
|
|
|
|
|
data.code += "\tmov [queue+8*r13], rax\n";
|
|
|
|
|
|
|
|
data.code += "\tinc r13\n";
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
"+" =>
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
data.code += "\tmov qword rax, [queue+8*r12]\n";
|
|
|
|
|
|
|
|
data.code += "\tinc r12\n";
|
|
|
|
|
|
|
|
data.code += "\tmov qword rbx, [queue+8*r12]\n";
|
|
|
|
|
|
|
|
data.code += "\tinc r12\n";
|
|
|
|
|
|
|
|
data.code += ASSEMBLY_LINUX_X64_TRY_RESET_QUEUE;
|
|
|
|
|
|
|
|
data.code += "\tadd rax, rbx\n";
|
|
|
|
|
|
|
|
data.code += "\tmov [queue+8*r13], rax\n";
|
|
|
|
|
|
|
|
data.code += "\tinc r13\n";
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
"*" =>
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
data.code += "\tmov qword rax, [queue+8*r12]\n";
|
|
|
|
|
|
|
|
data.code += "\tinc r12\n";
|
|
|
|
|
|
|
|
data.code += "\tmov qword rbx, [queue+8*r12]\n";
|
|
|
|
|
|
|
|
data.code += "\tinc r12\n";
|
|
|
|
|
|
|
|
data.code += ASSEMBLY_LINUX_X64_TRY_RESET_QUEUE;
|
|
|
|
|
|
|
|
data.code += "\tmul rbx\n";
|
|
|
|
|
|
|
|
data.code += "\tmov [queue+8*r13], rax\n";
|
|
|
|
|
|
|
|
data.code += "\tinc r13\n";
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
">" =>
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
data.code += "\tmov rbx, 0\n";
|
|
|
|
|
|
|
|
data.code += "\tmov rcx, 1\n";
|
|
|
|
|
|
|
|
data.code += "\tmov rax, [queue+8*r12]\n";
|
|
|
|
|
|
|
|
data.code += "\tcmp qword rax, [queue+8*r12+8]\n";
|
|
|
|
|
|
|
|
data.code += "\tcmovg rbx, rcx\n";
|
|
|
|
|
|
|
|
data.code += "\tadd r12, 2\n";
|
|
|
|
|
|
|
|
data.code += ASSEMBLY_LINUX_X64_TRY_RESET_QUEUE;
|
|
|
|
|
|
|
|
data.code += "\tmov qword [queue+8*r13], rbx\n";
|
|
|
|
|
|
|
|
data.code += "\tinc r13\n";
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
"<" =>
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
data.code += "\tmov rbx, 0\n";
|
|
|
|
|
|
|
|
data.code += "\tmov rcx, 1\n";
|
|
|
|
|
|
|
|
data.code += "\tmov rax, [queue+8*r12]\n";
|
|
|
|
|
|
|
|
data.code += "\tcmp qword rax, [queue+8*r12+8]\n";
|
|
|
|
|
|
|
|
data.code += "\tcmovl rbx, rcx\n";
|
|
|
|
|
|
|
|
data.code += "\tadd r12, 2\n";
|
|
|
|
|
|
|
|
data.code += ASSEMBLY_LINUX_X64_TRY_RESET_QUEUE;
|
|
|
|
|
|
|
|
data.code += "\tmov qword [queue+8*r13], rbx\n";
|
|
|
|
|
|
|
|
data.code += "\tinc r13\n";
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
">=" =>
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
data.code += "\tmov rbx, 0\n";
|
|
|
|
|
|
|
|
data.code += "\tmov rcx, 1\n";
|
|
|
|
|
|
|
|
data.code += "\tmov rax, [queue+8*r12]\n";
|
|
|
|
|
|
|
|
data.code += "\tcmp qword rax, [queue+8*r12+8]\n";
|
|
|
|
|
|
|
|
data.code += "\tcmovge rbx, rcx\n";
|
|
|
|
|
|
|
|
data.code += "\tadd r12, 2\n";
|
|
|
|
|
|
|
|
data.code += ASSEMBLY_LINUX_X64_TRY_RESET_QUEUE;
|
|
|
|
|
|
|
|
data.code += "\tmov qword [queue+8*r13], rbx\n";
|
|
|
|
|
|
|
|
data.code += "\tinc r13\n";
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
"<=" =>
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
data.code += "\tmov rbx, 0\n";
|
|
|
|
|
|
|
|
data.code += "\tmov rcx, 1\n";
|
|
|
|
|
|
|
|
data.code += "\tmov rax, [queue+8*r12]\n";
|
|
|
|
|
|
|
|
data.code += "\tcmp qword rax, [queue+8*r12+8]\n";
|
|
|
|
|
|
|
|
data.code += "\tcmovle rbx, rcx\n";
|
|
|
|
|
|
|
|
data.code += "\tadd r12, 2\n";
|
|
|
|
|
|
|
|
data.code += ASSEMBLY_LINUX_X64_TRY_RESET_QUEUE;
|
|
|
|
|
|
|
|
data.code += "\tmov qword [queue+8*r13], rbx\n";
|
|
|
|
|
|
|
|
data.code += "\tinc r13\n";
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
"==" =>
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
data.code += "\tmov rbx, 0\n";
|
|
|
|
|
|
|
|
data.code += "\tmov rcx, 1\n";
|
|
|
|
|
|
|
|
data.code += "\tmov rax, [queue+8*r12]\n";
|
|
|
|
|
|
|
|
data.code += "\tcmp qword rax, [queue+8*r12+8]\n";
|
|
|
|
|
|
|
|
data.code += "\tcmove rbx, rcx\n";
|
|
|
|
|
|
|
|
data.code += "\tadd r12, 2\n";
|
|
|
|
|
|
|
|
data.code += ASSEMBLY_LINUX_X64_TRY_RESET_QUEUE;
|
|
|
|
|
|
|
|
data.code += "\tmov qword [queue+8*r13], rbx\n";
|
|
|
|
|
|
|
|
data.code += "\tinc r13\n";
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
"&&" =>
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
data.code += "\tmov rax, [queue+8*r12]\n";
|
|
|
|
|
|
|
|
data.code += "\tmov rbx, [queue+8*r12+8]\n";
|
|
|
|
|
|
|
|
data.code += "\tand rax, rbx\n";
|
|
|
|
|
|
|
|
data.code += "\tadd r12, 2\n";
|
|
|
|
|
|
|
|
data.code += ASSEMBLY_LINUX_X64_TRY_RESET_QUEUE;
|
|
|
|
|
|
|
|
data.code += "\tmov [queue+8*r13], rax\n";
|
|
|
|
|
|
|
|
data.code += "\tinc r13\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => todo!("intrinsic {} {}:{}", name, line, col)
|
|
|
|
_ => todo!("intrinsic {} {}:{}", name, line, col)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Operation::Apply(name, word, line, col) =>
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
data.code += format!("\t;;apply {}.{} {}:{}\n", name, word, line, col).as_str();
|
|
|
|
|
|
|
|
match word.as_str()
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
"read" =>
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
data.code += "\tmov rax, [queue+8*r12]\n";
|
|
|
|
|
|
|
|
data.code += "\tinc r12\n";
|
|
|
|
|
|
|
|
data.code += ASSEMBLY_LINUX_X64_TRY_RESET_QUEUE;
|
|
|
|
|
|
|
|
data.code += format!("\tmov qword rbx, [arr_{}+8*rax]\n", name).as_str();
|
|
|
|
|
|
|
|
data.code += "\tmov qword [queue+8*r13], rbx\n";
|
|
|
|
|
|
|
|
data.code += "\tinc r13\n";
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
"write" =>
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
data.code += "\tmov rax, [queue+8*r12]\n";
|
|
|
|
|
|
|
|
data.code += "\tinc r12\n";
|
|
|
|
|
|
|
|
data.code += ASSEMBLY_LINUX_X64_TRY_RESET_QUEUE;
|
|
|
|
|
|
|
|
data.code += "\tmov qword rbx, [queue+8*r12]\n";
|
|
|
|
|
|
|
|
data.code += format!("\tmov qword [arr_{}+8*rax], rbx\n", name).as_str();
|
|
|
|
|
|
|
|
data.code += "\tinc r12\n";
|
|
|
|
|
|
|
|
data.code += ASSEMBLY_LINUX_X64_TRY_RESET_QUEUE;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
"length" =>
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
let array = arrays.iter().find(|x| &x.name == name).unwrap();
|
|
|
|
|
|
|
|
data.code += format!("\tmov qword [queue+8*r13], {}\n", array.length).as_str();
|
|
|
|
|
|
|
|
data.code += "\tinc r13\n";
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
_ => todo!("apply {}", word)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
Operation::FunctionCall(name, line, col) =>
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
data.code += format!("\t;;func call {} {}:{}\n", name, line, col).as_str();
|
|
|
|
|
|
|
|
let function = functions.iter().find(|x| &x.name == name).unwrap();
|
|
|
|
|
|
|
|
for _ in 0..function.ins.len()
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
data.code += "\tmov rax, [queue+8*r12]\n";
|
|
|
|
|
|
|
|
data.code += "\tmov [queue+8*r13], rax\n";
|
|
|
|
|
|
|
|
data.code += "\tinc r12\n";
|
|
|
|
|
|
|
|
data.code += "\tinc r13\n";
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
data.code += "\t;; move pointers\n";
|
|
|
|
|
|
|
|
// save the current base
|
|
|
|
|
|
|
|
data.code += "\tpush r14\n";
|
|
|
|
|
|
|
|
// save the current head
|
|
|
|
|
|
|
|
data.code += "\tpush r12\n";
|
|
|
|
|
|
|
|
// prepare the layout
|
|
|
|
|
|
|
|
data.code += "\tmov r14, r13\n";
|
|
|
|
|
|
|
|
data.code += format!("\tsub r14, {}\n", function.ins.len()).as_str();
|
|
|
|
|
|
|
|
data.code += "\tmov r12, r14\n";
|
|
|
|
|
|
|
|
// call
|
|
|
|
|
|
|
|
data.code += format!("\tcall {}\n", name).as_str();
|
|
|
|
|
|
|
|
// move the sub-queue back to the base
|
|
|
|
|
|
|
|
for _ in 0..function.outs.len()
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
data.code += "\tmov rax, [queue+8*r12]\n";
|
|
|
|
|
|
|
|
data.code += "\tmov [queue+8*r14], rax\n";
|
|
|
|
|
|
|
|
data.code += "\tinc r12\n";
|
|
|
|
|
|
|
|
data.code += "\tinc r14\n";
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// restore the tail
|
|
|
|
|
|
|
|
data.code += "\tmov r13, r14\n";
|
|
|
|
|
|
|
|
// restore the head
|
|
|
|
|
|
|
|
data.code += "\tpop r12\n";
|
|
|
|
|
|
|
|
// restore the base
|
|
|
|
|
|
|
|
data.code += "\tpop r14\n";
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
Operation::Interrupt(line, col) =>
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
data.code += format!("\t;;interrupt {}:{}\n", line, col).as_str();
|
|
|
|
|
|
|
|
data.code += "lea r8, [queue]\n";
|
|
|
|
|
|
|
|
data.code += format!("mov r9, {}\n", 1000*line + col).as_str();
|
|
|
|
|
|
|
|
data.code += "int3\n";
|
|
|
|
|
|
|
|
}
|
|
|
|
_ => todo!("{:?}", operation)
|
|
|
|
_ => todo!("{:?}", operation)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -357,6 +666,7 @@ fn generate_assembly_linux_x64_function(name: &str, operations: &Vec<Operation>,
|
|
|
|
strings: String::new(),
|
|
|
|
strings: String::new(),
|
|
|
|
};
|
|
|
|
};
|
|
|
|
merge_assemblies(&mut data, generate_assembly_linux_x64_block(operations, functions, intrinsics, arrays, debug));
|
|
|
|
merge_assemblies(&mut data, generate_assembly_linux_x64_block(operations, functions, intrinsics, arrays, debug));
|
|
|
|
|
|
|
|
data.code += "\tret\n";
|
|
|
|
return data;
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -455,17 +765,23 @@ fn interpret_program(operations: &Vec<Operation>, queue: &mut Vec<String>, funct
|
|
|
|
let second = queue.remove(0).parse::<i64>().unwrap();
|
|
|
|
let second = queue.remove(0).parse::<i64>().unwrap();
|
|
|
|
queue.push((first > second).to_string());
|
|
|
|
queue.push((first > second).to_string());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
"<" =>
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
let first = queue.remove(0).parse::<i64>().unwrap();
|
|
|
|
|
|
|
|
let second = queue.remove(0).parse::<i64>().unwrap();
|
|
|
|
|
|
|
|
queue.push((first < second).to_string());
|
|
|
|
|
|
|
|
}
|
|
|
|
">=" =>
|
|
|
|
">=" =>
|
|
|
|
{
|
|
|
|
{
|
|
|
|
let first = queue.remove(0).parse::<i64>().unwrap();
|
|
|
|
let first = queue.remove(0).parse::<i64>().unwrap();
|
|
|
|
let second = queue.remove(0).parse::<i64>().unwrap();
|
|
|
|
let second = queue.remove(0).parse::<i64>().unwrap();
|
|
|
|
queue.push((first >= second).to_string());
|
|
|
|
queue.push((first >= second).to_string());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"<" =>
|
|
|
|
"<=" =>
|
|
|
|
{
|
|
|
|
{
|
|
|
|
let first = queue.remove(0).parse::<i64>().unwrap();
|
|
|
|
let first = queue.remove(0).parse::<i64>().unwrap();
|
|
|
|
let second = queue.remove(0).parse::<i64>().unwrap();
|
|
|
|
let second = queue.remove(0).parse::<i64>().unwrap();
|
|
|
|
queue.push((first < second).to_string());
|
|
|
|
queue.push((first <= second).to_string());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"==" =>
|
|
|
|
"==" =>
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -494,6 +810,11 @@ fn interpret_program(operations: &Vec<Operation>, queue: &mut Vec<String>, funct
|
|
|
|
{
|
|
|
|
{
|
|
|
|
output += format!("{}\n", queue.remove(0)).as_str();
|
|
|
|
output += format!("{}\n", queue.remove(0)).as_str();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
"intToStr" =>
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
let val = queue.remove(0).clone();
|
|
|
|
|
|
|
|
queue.push(val);
|
|
|
|
|
|
|
|
}
|
|
|
|
_ =>
|
|
|
|
_ =>
|
|
|
|
{
|
|
|
|
{
|
|
|
|
return Err(format!("Unexpected intrinsic '{}' at {}:{}", intrinsic_name, line, col));
|
|
|
|
return Err(format!("Unexpected intrinsic '{}' at {}:{}", intrinsic_name, line, col));
|
|
|
@ -568,6 +889,7 @@ fn interpret_program(operations: &Vec<Operation>, queue: &mut Vec<String>, funct
|
|
|
|
{
|
|
|
|
{
|
|
|
|
println!("---Queue state at {}:{}---\nlength: {}\n{:?}\n------------------------------", line, col, queue.len(), queue);
|
|
|
|
println!("---Queue state at {}:{}---\nlength: {}\n{:?}\n------------------------------", line, col, queue.len(), queue);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Operation::Interrupt(_, _) => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if debug
|
|
|
|
if debug
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -614,6 +936,7 @@ fn typecheck_block(operations: &Vec<Operation>, ins: &Vec<Datatype>, outs: &Vec<
|
|
|
|
{
|
|
|
|
{
|
|
|
|
match operation
|
|
|
|
match operation
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
Operation::Interrupt(line, col) |
|
|
|
|
Operation::Enqueue(_, _, line, col) |
|
|
|
|
Operation::Enqueue(_, _, line, col) |
|
|
|
|
Operation::Dequeue(line, col) |
|
|
|
|
Operation::Dequeue(line, col) |
|
|
|
|
Operation::Requeue(line, col) |
|
|
|
|
Operation::Requeue(line, col) |
|
|
|
@ -792,6 +1115,7 @@ fn get_return_type(operations: &Vec<Operation>, ins: &Vec<Datatype>, functions:
|
|
|
|
{
|
|
|
|
{
|
|
|
|
println!("---Type queue state at {}:{}---\nlength: {}\n{:?}\n------------------------------", line, col, type_queue.len(), type_queue);
|
|
|
|
println!("---Type queue state at {}:{}---\nlength: {}\n{:?}\n------------------------------", line, col, type_queue.len(), type_queue);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Operation::Interrupt(_, _) => {}
|
|
|
|
Operation::Apply(name, word, line, col) =>
|
|
|
|
Operation::Apply(name, word, line, col) =>
|
|
|
|
{
|
|
|
|
{
|
|
|
|
match word.as_str()
|
|
|
|
match word.as_str()
|
|
|
@ -863,7 +1187,7 @@ fn validate_function_calls_in_block(block: &Vec<Operation>, functions: &Vec<Func
|
|
|
|
match operation
|
|
|
|
match operation
|
|
|
|
{
|
|
|
|
{
|
|
|
|
Operation::Depth(_, _) | Operation::QueueDiagnostic(_, _) | Operation::Intrinsic(_, _, _) | Operation::Enqueue(_, _, _, _) | Operation::Dequeue(_, _) |
|
|
|
|
Operation::Depth(_, _) | Operation::QueueDiagnostic(_, _) | Operation::Intrinsic(_, _, _) | Operation::Enqueue(_, _, _, _) | Operation::Dequeue(_, _) |
|
|
|
|
Operation::Requeue(_, _) | Operation::Dup(_, _) | Operation::Swap(_, _) | Operation::Apply(_, _, _, _) => {},
|
|
|
|
Operation::Requeue(_, _) | Operation::Dup(_, _) | Operation::Swap(_, _) | Operation::Apply(_, _, _, _) | Operation::Interrupt(_, _) => {},
|
|
|
|
Operation::FunctionCall(function_name, line, col) =>
|
|
|
|
Operation::FunctionCall(function_name, line, col) =>
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if !functions.iter().any(|x| &x.name == function_name)
|
|
|
|
if !functions.iter().any(|x| &x.name == function_name)
|
|
|
@ -948,7 +1272,7 @@ fn extract_arrays(tokens: &mut Vec<Token>, intrinsics: &HashMap<&str, (Vec<Datat
|
|
|
|
let mut data: Vec<String> = Vec::new();
|
|
|
|
let mut data: Vec<String> = Vec::new();
|
|
|
|
let default_val = match datatype
|
|
|
|
let default_val = match datatype
|
|
|
|
{
|
|
|
|
{
|
|
|
|
Datatype::Any | Datatype::String => String::new(),
|
|
|
|
Datatype::String => String::new(),
|
|
|
|
Datatype::Bool => String::from("false"),
|
|
|
|
Datatype::Bool => String::from("false"),
|
|
|
|
Datatype::Int => String::from("0"),
|
|
|
|
Datatype::Int => String::from("0"),
|
|
|
|
};
|
|
|
|
};
|
|
|
@ -956,7 +1280,7 @@ fn extract_arrays(tokens: &mut Vec<Token>, intrinsics: &HashMap<&str, (Vec<Datat
|
|
|
|
{
|
|
|
|
{
|
|
|
|
data.push(default_val.clone());
|
|
|
|
data.push(default_val.clone());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
arrays.push(Arr { name: name.clone(), datatype, length: size , data });
|
|
|
|
arrays.push(Arr { name: sanitize_name(name.clone()), datatype, length: size , data });
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
else
|
|
|
@ -984,11 +1308,16 @@ fn extract_arrays(tokens: &mut Vec<Token>, intrinsics: &HashMap<&str, (Vec<Datat
|
|
|
|
return Ok(arrays);
|
|
|
|
return Ok(arrays);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn sanitize_name(name: String) -> String
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return name.replace("-", "_").replace("+", "_");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn str_to_datatype(s: &str, line: i32, col: i32) -> Result<Datatype, String>
|
|
|
|
fn str_to_datatype(s: &str, line: i32, col: i32) -> Result<Datatype, String>
|
|
|
|
{
|
|
|
|
{
|
|
|
|
match s
|
|
|
|
match s
|
|
|
|
{
|
|
|
|
{
|
|
|
|
"any" => Ok(Datatype::Any),
|
|
|
|
//"any" => Ok(Datatype::Any),
|
|
|
|
"bool" => Ok(Datatype::Bool),
|
|
|
|
"bool" => Ok(Datatype::Bool),
|
|
|
|
"int" => Ok(Datatype::Int),
|
|
|
|
"int" => Ok(Datatype::Int),
|
|
|
|
"str" => Ok(Datatype::String),
|
|
|
|
"str" => Ok(Datatype::String),
|
|
|
@ -1034,7 +1363,7 @@ fn extract_functions(tokens: &mut Vec<Token>, intrinsics: &HashMap<&str, (Vec<Da
|
|
|
|
}
|
|
|
|
}
|
|
|
|
match word.as_str()
|
|
|
|
match word.as_str()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
"any" => ins.push(Datatype::Any),
|
|
|
|
//"any" => ins.push(Datatype::Any),
|
|
|
|
"str" => ins.push(Datatype::String),
|
|
|
|
"str" => ins.push(Datatype::String),
|
|
|
|
"int" => ins.push(Datatype::Int),
|
|
|
|
"int" => ins.push(Datatype::Int),
|
|
|
|
"bool" => ins.push(Datatype::Bool),
|
|
|
|
"bool" => ins.push(Datatype::Bool),
|
|
|
@ -1069,7 +1398,7 @@ fn extract_functions(tokens: &mut Vec<Token>, intrinsics: &HashMap<&str, (Vec<Da
|
|
|
|
{
|
|
|
|
{
|
|
|
|
match word.as_str()
|
|
|
|
match word.as_str()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
"any" => outs.push(Datatype::Any),
|
|
|
|
//"any" => outs.push(Datatype::Any),
|
|
|
|
"str" => outs.push(Datatype::String),
|
|
|
|
"str" => outs.push(Datatype::String),
|
|
|
|
"int" => outs.push(Datatype::Int),
|
|
|
|
"int" => outs.push(Datatype::Int),
|
|
|
|
"bool" => outs.push(Datatype::Bool),
|
|
|
|
"bool" => outs.push(Datatype::Bool),
|
|
|
@ -1087,9 +1416,9 @@ fn extract_functions(tokens: &mut Vec<Token>, intrinsics: &HashMap<&str, (Vec<Da
|
|
|
|
if debug
|
|
|
|
if debug
|
|
|
|
{
|
|
|
|
{
|
|
|
|
println!("outs: {:?}", outs);
|
|
|
|
println!("outs: {:?}", outs);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
let block = parse_block(&mut tokens_iter, intrinsics, debug)?;
|
|
|
|
let block = parse_block(&mut tokens_iter, intrinsics, debug)?;
|
|
|
|
functions.push(Function {name: word.clone(), ins, outs, content: block});
|
|
|
|
functions.push(Function {name: sanitize_name(word.clone()), ins, outs, content: block});
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -1157,7 +1486,7 @@ fn parse_until_delimiter(tokens_iter: &mut Peekable<std::slice::Iter<Token>>, in
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Token::Apply(name, word, line, col) =>
|
|
|
|
Token::Apply(name, word, line, col) =>
|
|
|
|
{
|
|
|
|
{
|
|
|
|
operations.push(Operation::Apply(name.clone(), word.clone(), *line, *col));
|
|
|
|
operations.push(Operation::Apply(sanitize_name(name.clone()), word.clone(), *line, *col));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Token::Keyword(word, line, col) =>
|
|
|
|
Token::Keyword(word, line, col) =>
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -1215,6 +1544,10 @@ fn parse_until_delimiter(tokens_iter: &mut Peekable<std::slice::Iter<Token>>, in
|
|
|
|
{
|
|
|
|
{
|
|
|
|
operations.push(Operation::QueueDiagnostic(*line, *col));
|
|
|
|
operations.push(Operation::QueueDiagnostic(*line, *col));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
else if word == "interrupt"
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
operations.push(Operation::Interrupt(*line, *col));
|
|
|
|
|
|
|
|
}
|
|
|
|
else if Some(word.as_str()) == delimiter
|
|
|
|
else if Some(word.as_str()) == delimiter
|
|
|
|
{
|
|
|
|
{
|
|
|
|
return Ok(operations);
|
|
|
|
return Ok(operations);
|
|
|
@ -1225,7 +1558,7 @@ fn parse_until_delimiter(tokens_iter: &mut Peekable<std::slice::Iter<Token>>, in
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
else
|
|
|
|
{
|
|
|
|
{
|
|
|
|
operations.push(Operation::FunctionCall(word.clone(), *line, *col));
|
|
|
|
operations.push(Operation::FunctionCall(sanitize_name(word.clone()), *line, *col));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -1329,7 +1662,7 @@ fn tokenize(text: &str) -> Result<Vec<Token>, String>
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
else
|
|
|
|
{
|
|
|
|
{
|
|
|
|
tokens.push(Token::Apply(application_name.clone(), word.clone(), line, col));
|
|
|
|
tokens.push(Token::Apply(sanitize_name(application_name.clone()), word.clone(), line, col));
|
|
|
|
application_name.clear();
|
|
|
|
application_name.clear();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
word.clear();
|
|
|
|
word.clear();
|
|
|
@ -1374,7 +1707,7 @@ fn tokenize(text: &str) -> Result<Vec<Token>, String>
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
else
|
|
|
|
{
|
|
|
|
{
|
|
|
|
tokens.push(Token::Apply(application_name.clone(), word.clone(), line, col));
|
|
|
|
tokens.push(Token::Apply(sanitize_name(application_name.clone()), word.clone(), line, col));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|