Introduce boolean types

This commit is contained in:
0x4261756D 2022-12-14 20:39:51 +01:00
parent 2a560cfcef
commit d1883ff3ab
3 changed files with 73 additions and 29 deletions

View File

@ -10,6 +10,7 @@ enum Token
{ {
StringLit(String, i32, i32), StringLit(String, i32, i32),
IntLit(String, i32, i32), IntLit(String, i32, i32),
BoolLit(String, i32, i32),
Keyword(String, i32, i32), Keyword(String, i32, i32),
} }
@ -26,6 +27,7 @@ enum Datatype
{ {
Int, Int,
String, String,
Bool,
//Pointer, //Pointer,
Any, Any,
} }
@ -71,6 +73,10 @@ fn main()
("print", (Vec::from([Datatype::Any]), Vec::new())), ("print", (Vec::from([Datatype::Any]), Vec::new())),
("-", (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]))),
]); ]);
let args: Vec<String> = env::args().collect(); let args: Vec<String> = env::args().collect();
if args.len() < 2 if args.len() < 2
@ -156,7 +162,7 @@ fn interpret_program(operations: &Vec<Operation>, queue: &mut Vec<String>, funct
{ {
let val = queue.remove(0); let val = queue.remove(0);
// TODO: Add bool type // TODO: Add bool type
if val == "0" if val == "true"
{ {
interpret_program(if_block, queue, functions, intrinsics, debug); interpret_program(if_block, queue, functions, intrinsics, debug);
} }
@ -185,6 +191,30 @@ fn interpret_program(operations: &Vec<Operation>, queue: &mut Vec<String>, funct
let addend2 = queue.remove(0).parse::<i64>().unwrap(); let addend2 = queue.remove(0).parse::<i64>().unwrap();
queue.push((addend1 + addend2).to_string()); queue.push((addend1 + addend2).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 second = queue.remove(0).parse::<i64>().unwrap();
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 second = queue.remove(0).parse::<i64>().unwrap();
queue.push((first != second).to_string());
}
_ => _ =>
{ {
panic!("Unexpected intrinsic '{}' at {}:{}", intrinsic_name, line, col); panic!("Unexpected intrinsic '{}' at {}:{}", intrinsic_name, line, col);
@ -196,7 +226,7 @@ fn interpret_program(operations: &Vec<Operation>, queue: &mut Vec<String>, funct
loop loop
{ {
let val = queue.remove(0); let val = queue.remove(0);
if val == "0" if val == "false"
{ {
break; break;
} }
@ -348,9 +378,9 @@ fn get_return_type(operations: &Vec<Operation>, ins: &Vec<Datatype>, functions:
panic!("Encountered if block with an empty queue at {}:{}", line, col); panic!("Encountered if block with an empty queue at {}:{}", line, col);
} }
let comparison_type = type_queue.remove(0); let comparison_type = type_queue.remove(0);
if comparison_type != Datatype::Int if comparison_type != Datatype::Bool
{ {
panic!("Expected an int as an if condition but got {:?} instead at {}:{}", comparison_type, line, col); panic!("Expected a Bool as an if condition but got {:?} instead at {}:{}", comparison_type, line, col);
} }
if debug if debug
{ {
@ -401,16 +431,16 @@ fn get_return_type(operations: &Vec<Operation>, ins: &Vec<Datatype>, functions:
panic!("Encountered while block with an empty queue at {}:{}", line, col); panic!("Encountered while block with an empty queue at {}:{}", line, col);
} }
let comparison_type = type_queue.remove(0); let comparison_type = type_queue.remove(0);
if comparison_type != Datatype::Int if comparison_type != Datatype::Bool
{ {
panic!("Expected an int as a while condition but got {:?} instead at {}:{}", comparison_type, line, col); panic!("Expected a Bool as a while condition but got {:?} instead at {}:{}", comparison_type, line, col);
} }
if debug if debug
{ {
println!("Starting to typecheck while block"); println!("Starting to typecheck while block");
} }
let mut outs = type_queue.clone(); let mut outs = type_queue.clone();
outs.insert(0, Datatype::Int); outs.insert(0, Datatype::Bool);
typecheck_block(while_block, type_queue, &outs, functions, intrinsics, debug); typecheck_block(while_block, type_queue, &outs, functions, intrinsics, debug);
} }
} }
@ -494,7 +524,7 @@ fn extract_functions(tokens: &mut Vec<Token>, intrinsics: &HashMap<&str, (Vec<Da
{ {
match token match token
{ {
Token::IntLit(_, line, col) | Token::StringLit(_, line, col) => Token::IntLit(_, line, col) | Token::StringLit(_, line, col) | Token::BoolLit(_, line, col) =>
{ {
panic!("Expected input parameters for a function but got {:?} instead at {}:{}", token, line, col); panic!("Expected input parameters for a function but got {:?} instead at {}:{}", token, line, col);
} }
@ -509,6 +539,7 @@ fn extract_functions(tokens: &mut Vec<Token>, intrinsics: &HashMap<&str, (Vec<Da
"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),
_ => panic!("Expected input parameters for a function but got {} instead at {}:{}", word, line, col) _ => panic!("Expected input parameters for a function but got {} instead at {}:{}", word, line, col)
} }
} }
@ -531,7 +562,7 @@ fn extract_functions(tokens: &mut Vec<Token>, intrinsics: &HashMap<&str, (Vec<Da
{ {
match token match token
{ {
Token::IntLit(_, line, col) | Token::StringLit(_, line, col) => Token::IntLit(_, line, col) | Token::StringLit(_, line, col) | Token::BoolLit(_, line, col) =>
{ {
panic!("Expected input parameters for a function but got {:?} instead at {}:{}", token, line, col); panic!("Expected input parameters for a function but got {:?} instead at {}:{}", token, line, col);
} }
@ -542,7 +573,8 @@ fn extract_functions(tokens: &mut Vec<Token>, intrinsics: &HashMap<&str, (Vec<Da
"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),
"{" | "}" | "deq" | "req" | "dup" | "swp" => panic!("Expected function name but got {} at {}:{}", word, line, col), "bool" => ins.push(Datatype::Bool),
"{" | "}" | "deq" | "req" | "dup" | "swp" | "true" | "false" => panic!("Expected function name but got {} at {}:{}", word, line, col),
_ => _ =>
{ {
if functions.iter().any(|x| &x.name == word) if functions.iter().any(|x| &x.name == word)
@ -620,6 +652,10 @@ fn parse_until_delimiter(tokens_iter: &mut Peekable<std::slice::Iter<Token>>, in
{ {
operations.push(Operation::Enqueue(Datatype::String, value.clone(), *line, *col)); operations.push(Operation::Enqueue(Datatype::String, value.clone(), *line, *col));
} }
Token::BoolLit(value, line, col) =>
{
operations.push(Operation::Enqueue(Datatype::Bool, value.clone(), *line, *col));
}
Token::Keyword(word, line, col) => Token::Keyword(word, line, col) =>
{ {
if intrinsics.contains_key(word.as_str()) if intrinsics.contains_key(word.as_str())
@ -751,7 +787,7 @@ fn tokenize(text: &str) -> Vec<Token>
if ch == '"' if ch == '"'
{ {
state = TokenizerState::Whitespace; state = TokenizerState::Whitespace;
tokens.push(Token::StringLit(word.clone(), line, col)); tokens.push(Token::StringLit(word.clone().replace("\\n", "\n"), line, col));
word.clear(); word.clear();
} }
else else
@ -768,6 +804,10 @@ fn tokenize(text: &str) -> Vec<Token>
{ {
tokens.push(Token::IntLit(word.clone(), line, col)); tokens.push(Token::IntLit(word.clone(), line, col));
} }
else if word == "true" || word == "false"
{
tokens.push(Token::BoolLit(word.clone(), line, col));
}
else else
{ {
tokens.push(Token::Keyword(word.clone(), line, col)); tokens.push(Token::Keyword(word.clone(), line, col));

View File

@ -1,5 +1,6 @@
//valid //valid
//output: Hello, World!\n4242test2Falsetesttesttest //output: Hello, World!
//4242test2Falsetesttesttest
"Hello, World!\n" print 43 foo foo deq "Hello, World!\n" print 43 foo foo deq
@ -10,12 +11,12 @@ function any => int foo
deq 42 17 print deq 42 17 print
} }
"test2" print 1 "test2" print false
check check
print print
function int => str check function bool => str check
{ {
if if
{ {
@ -27,20 +28,14 @@ function int => str check
} }
} }
// 3
// 3 3
// 3
// 3 1
// 2
// 2 "test"
// "test" 2
function int => whileFunction function int => whileFunction
{ {
dup dup
while 0 req >
req while
{ {
1 - "test" req print dup 1 - 0 dup >
"test" req req print req
} }
deq deq
} }

View File

@ -1,12 +1,21 @@
//valid,output:10987654321 //valid,output:10987654321
12 while true while
{ {
0 false
} }
10 dup while 10 0 dup > req
while
{ {
dup print 1 - dup dup print
1 - 0 dup > req
} }
deq deq
true true true while
{
false
}
print print