|
|
|
@ -102,24 +102,72 @@ fn main()
|
|
|
|
|
{
|
|
|
|
|
"-t" | "--test" =>
|
|
|
|
|
{
|
|
|
|
|
let mut count = 0;
|
|
|
|
|
for f in fs::read_dir(&args[2]).unwrap()
|
|
|
|
|
{
|
|
|
|
|
let f = f.unwrap();
|
|
|
|
|
let file_content = fs::read_to_string(f.path()).unwrap();
|
|
|
|
|
println!("========NOW TESTING '{:?}'========", f.path());
|
|
|
|
|
match compile(file_content, &intrinsics, interpret, debug)
|
|
|
|
|
match compile(&file_content, &intrinsics, interpret, debug)
|
|
|
|
|
{
|
|
|
|
|
Ok(()) => println!("\n\n\n---Successfully parsed '{:?}'---", f.path()),
|
|
|
|
|
Err(msg) => println!("ERROR: {}", msg),
|
|
|
|
|
Ok(maybe_msg) =>
|
|
|
|
|
{
|
|
|
|
|
println!("---Successfully parsed '{:?}'---", f.path());
|
|
|
|
|
if let Some(msg) = &maybe_msg
|
|
|
|
|
{
|
|
|
|
|
print!("---Output---\n'{}'\n", msg);
|
|
|
|
|
}
|
|
|
|
|
let expected = &format!("//valid,{}:END:", maybe_msg.unwrap_or(String::new()).replace("\n", "\n//"));
|
|
|
|
|
if file_content.starts_with(expected)
|
|
|
|
|
{
|
|
|
|
|
println!("===PASSED===");
|
|
|
|
|
count += 1;
|
|
|
|
|
}
|
|
|
|
|
else if let Some(index) = file_content.find("//:END:")
|
|
|
|
|
{
|
|
|
|
|
let expected_output = file_content[8..index].replace("\n//", "\n");
|
|
|
|
|
println!("\n===FAILED===\nExpected the output to be\n'{}'\n({})", expected_output, expected);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
panic!("Could not find an ending marker (:END:) for the expected output in {:?}", f.file_name());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Err(msg) =>
|
|
|
|
|
{
|
|
|
|
|
println!("ERROR: {}", msg);
|
|
|
|
|
if file_content.starts_with(&format!("//invalid,{}:END:", msg.replace("\n", "\n//")))
|
|
|
|
|
{
|
|
|
|
|
println!("===PASSED===");
|
|
|
|
|
count += 1;
|
|
|
|
|
}
|
|
|
|
|
else if let Some(index) = file_content.find(":END:")
|
|
|
|
|
{
|
|
|
|
|
let expected_output = file_content[10..index].replace("\n//", "\n");
|
|
|
|
|
println!("\n\n===FAILED===\nExpected the output to be {}", expected_output);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
panic!("Could not find an ending marker (//:END:) for the expected output in {:?}", f.file_name());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
println!("\n\n=========RESULT=========\n{}/{}", count, fs::read_dir(&args[2]).unwrap().count());
|
|
|
|
|
}
|
|
|
|
|
"-c" | "--compile" =>
|
|
|
|
|
{
|
|
|
|
|
let file_content = fs::read_to_string(&args[2]).expect("Could not read the source file");
|
|
|
|
|
match compile(file_content, &intrinsics, interpret, debug)
|
|
|
|
|
match compile(&file_content, &intrinsics, interpret, debug)
|
|
|
|
|
{
|
|
|
|
|
Ok(()) => println!("\n\n\n---Successfully parsed '{}'---", args[2]),
|
|
|
|
|
Ok(maybe_msg) =>
|
|
|
|
|
{
|
|
|
|
|
println!("---Successfully parsed '{}'---", args[2]);
|
|
|
|
|
if let Some(msg) = maybe_msg
|
|
|
|
|
{
|
|
|
|
|
print!("---Output---\n\n{}", msg);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Err(msg) => println!("ERROR: {}", msg),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -127,7 +175,7 @@ fn main()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn compile(file_content: String, intrinsics: &HashMap<&str, (Vec<Datatype>, Vec<Datatype>)>, interpret: bool, debug: bool) -> Result<(), String>
|
|
|
|
|
fn compile(file_content: &String, intrinsics: &HashMap<&str, (Vec<Datatype>, Vec<Datatype>)>, interpret: bool, debug: bool) -> Result<Option<String>, String>
|
|
|
|
|
{
|
|
|
|
|
let mut tokens: Vec<Token> = tokenize(&file_content)?;
|
|
|
|
|
println!("---Done tokenizing, got {} tokens---", tokens.len());
|
|
|
|
@ -139,21 +187,26 @@ fn compile(file_content: String, intrinsics: &HashMap<&str, (Vec<Datatype>, Vec<
|
|
|
|
|
println!("---Done validating function calls---");
|
|
|
|
|
typecheck(&operations, &functions, &intrinsics, debug)?;
|
|
|
|
|
println!("---Done typechecking---");
|
|
|
|
|
if interpret
|
|
|
|
|
let output = if interpret
|
|
|
|
|
{
|
|
|
|
|
println!("---Starting to interpret the program---\n\n");
|
|
|
|
|
interpret_program(&operations, &mut Vec::new(), &functions, &intrinsics, debug);
|
|
|
|
|
println!("---Starting to interpret the program---");
|
|
|
|
|
Some(interpret_program(&operations, &mut Vec::new(), &functions, &intrinsics, debug))
|
|
|
|
|
}
|
|
|
|
|
return Ok(());
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
None
|
|
|
|
|
};
|
|
|
|
|
return Ok(output);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn interpret_program(operations: &Vec<Operation>, queue: &mut Vec<String>, functions: &Vec<Function>, intrinsics: &HashMap<&str, (Vec<Datatype>, Vec<Datatype>)>, debug: bool)
|
|
|
|
|
fn interpret_program(operations: &Vec<Operation>, queue: &mut Vec<String>, functions: &Vec<Function>, intrinsics: &HashMap<&str, (Vec<Datatype>, Vec<Datatype>)>, debug: bool) -> String
|
|
|
|
|
{
|
|
|
|
|
let mut output = String::new();
|
|
|
|
|
for operation in operations
|
|
|
|
|
{
|
|
|
|
|
if debug
|
|
|
|
|
{
|
|
|
|
|
println!("before: {:?}: {:?}", operation, queue);
|
|
|
|
|
println!("before: {:?}: {:?}, '{}'", operation, queue, output);
|
|
|
|
|
}
|
|
|
|
|
match operation
|
|
|
|
|
{
|
|
|
|
@ -191,7 +244,7 @@ fn interpret_program(operations: &Vec<Operation>, queue: &mut Vec<String>, funct
|
|
|
|
|
let val = queue.remove(0);
|
|
|
|
|
function_context.push(val);
|
|
|
|
|
}
|
|
|
|
|
interpret_program(&function.content, function_context, functions, intrinsics, debug);
|
|
|
|
|
output += interpret_program(&function.content, function_context, functions, intrinsics, debug).as_str();
|
|
|
|
|
for val in function_context
|
|
|
|
|
{
|
|
|
|
|
queue.push(val.to_string());
|
|
|
|
@ -202,11 +255,11 @@ fn interpret_program(operations: &Vec<Operation>, queue: &mut Vec<String>, funct
|
|
|
|
|
let val = queue.remove(0);
|
|
|
|
|
if val == "true"
|
|
|
|
|
{
|
|
|
|
|
interpret_program(if_block, queue, functions, intrinsics, debug);
|
|
|
|
|
output += interpret_program(if_block, queue, functions, intrinsics, debug).as_str();
|
|
|
|
|
}
|
|
|
|
|
else if let Some(else_block) = maybe_else_block
|
|
|
|
|
{
|
|
|
|
|
interpret_program(else_block, queue, functions, intrinsics, debug);
|
|
|
|
|
output += interpret_program(else_block, queue, functions, intrinsics, debug).as_str();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Operation::Intrinsic(intrinsic_name, line, col) =>
|
|
|
|
@ -215,7 +268,7 @@ fn interpret_program(operations: &Vec<Operation>, queue: &mut Vec<String>, funct
|
|
|
|
|
{
|
|
|
|
|
"print" =>
|
|
|
|
|
{
|
|
|
|
|
print!("{}", queue.remove(0));
|
|
|
|
|
output += format!("{}", queue.remove(0)).as_str();
|
|
|
|
|
}
|
|
|
|
|
"-" =>
|
|
|
|
|
{
|
|
|
|
@ -260,7 +313,7 @@ fn interpret_program(operations: &Vec<Operation>, queue: &mut Vec<String>, funct
|
|
|
|
|
}
|
|
|
|
|
"println" =>
|
|
|
|
|
{
|
|
|
|
|
println!("{}", queue.remove(0));
|
|
|
|
|
output += format!("{}\n", queue.remove(0)).as_str();
|
|
|
|
|
}
|
|
|
|
|
_ =>
|
|
|
|
|
{
|
|
|
|
@ -277,7 +330,7 @@ fn interpret_program(operations: &Vec<Operation>, queue: &mut Vec<String>, funct
|
|
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
interpret_program(while_block, queue, functions, intrinsics, debug);
|
|
|
|
|
output += interpret_program(while_block, queue, functions, intrinsics, debug).as_str();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Operation::Depth(_, _) =>
|
|
|
|
@ -292,9 +345,10 @@ fn interpret_program(operations: &Vec<Operation>, queue: &mut Vec<String>, funct
|
|
|
|
|
}
|
|
|
|
|
if debug
|
|
|
|
|
{
|
|
|
|
|
println!("after: {:?}: {:?}", operation, queue);
|
|
|
|
|
println!("after: {:?}: {:?}, '{}'", operation, queue, output);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return output;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn typecheck(operations: &Vec<Operation>, functions: &Vec<Function>, intrinsics: &HashMap<&str, (Vec<Datatype>, Vec<Datatype>)>, debug: bool) -> Result<(), String>
|
|
|
|
|