Compare commits
5 Commits
e4a7bcccc0
...
53cfd52dcd
Author | SHA1 | Date | |
---|---|---|---|
|
53cfd52dcd | ||
|
8397d32756 | ||
|
bf4a08e484 | ||
|
0abc74f043 | ||
|
dedb601a9b |
2
LICENSE
2
LICENSE
@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) <year> <copyright holders>
|
||||
Copyright (c) 2022 0x4261756D
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
|
@ -1,3 +1,9 @@
|
||||
# kurz
|
||||
|
||||
Queue based language
|
||||
Queue based language
|
||||
|
||||
## Roadmap
|
||||
- [x] turing completeness
|
||||
- [ ] compiled
|
||||
- [ ] cross-plattform
|
||||
- [ ] self-hosted
|
||||
|
29
editor/micro.yaml
Normal file
29
editor/micro.yaml
Normal file
@ -0,0 +1,29 @@
|
||||
filetype: kurz
|
||||
|
||||
detect:
|
||||
filename: "\\.qbl$"
|
||||
|
||||
rules:
|
||||
- comment:
|
||||
start: "//"
|
||||
end: "$"
|
||||
rules:
|
||||
- todo: "(TODO|FIXME):?"
|
||||
- constant.string:
|
||||
start: "\""
|
||||
end: "\""
|
||||
skip: "\\\\."
|
||||
rules:
|
||||
- constant.specialChar: "\\\\."
|
||||
- constant.bool: "\\b(true|false)\\b"
|
||||
# ints
|
||||
- constant.number: "\\b([0-9]*)\\b"
|
||||
- symbol.brackets: "[{}]"
|
||||
# function
|
||||
- identifier: "function"
|
||||
- type: "\\b(bool|int|str|any)\\b"
|
||||
- symbol.operator: "([-+<>]|==|!=|=>|print(ln)?)"
|
||||
- identifier: "\\b(if|else|while)\\b"
|
||||
- special: "\\b(deq|swp|dup|req|depth|decrease)\\b"
|
||||
- special: "\\?\\?\\?"
|
||||
- statement: "arr"
|
44
src/main.rs
44
src/main.rs
@ -180,7 +180,6 @@ fn main()
|
||||
{
|
||||
Ok(maybe_msg) =>
|
||||
{
|
||||
println!("---Successfully parsed '{}'---", args[2]);
|
||||
if let Some(msg) = maybe_msg
|
||||
{
|
||||
print!("---Output---\n\n{}", msg);
|
||||
@ -210,7 +209,7 @@ fn compile(file_content: &String, intrinsics: &HashMap<&str, (Vec<Datatype>, Vec
|
||||
let output = if interpret
|
||||
{
|
||||
println!("---Starting to interpret the program---");
|
||||
Some(interpret_program(&operations, &mut Vec::new(), &functions, &mut arrays, &intrinsics, debug))
|
||||
Some(interpret_program(&operations, &mut Vec::new(), &functions, &mut arrays, &intrinsics, debug)?)
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -219,7 +218,7 @@ fn compile(file_content: &String, intrinsics: &HashMap<&str, (Vec<Datatype>, Vec
|
||||
return Ok(output);
|
||||
}
|
||||
|
||||
fn interpret_program(operations: &Vec<Operation>, queue: &mut Vec<String>, functions: &Vec<Function>, arrays: &mut Vec<Arr>, intrinsics: &HashMap<&str, (Vec<Datatype>, Vec<Datatype>)>, debug: bool) -> String
|
||||
fn interpret_program(operations: &Vec<Operation>, queue: &mut Vec<String>, functions: &Vec<Function>, arrays: &mut Vec<Arr>, intrinsics: &HashMap<&str, (Vec<Datatype>, Vec<Datatype>)>, debug: bool) -> Result<String,String>
|
||||
{
|
||||
let mut output = String::new();
|
||||
for operation in operations
|
||||
@ -264,7 +263,7 @@ fn interpret_program(operations: &Vec<Operation>, queue: &mut Vec<String>, funct
|
||||
let val = queue.remove(0);
|
||||
function_context.push(val);
|
||||
}
|
||||
output += interpret_program(&function.content, function_context, functions, arrays, intrinsics, debug).as_str();
|
||||
output += interpret_program(&function.content, function_context, functions, arrays, intrinsics, debug)?.as_str();
|
||||
for val in function_context
|
||||
{
|
||||
queue.push(val.to_string());
|
||||
@ -275,11 +274,11 @@ fn interpret_program(operations: &Vec<Operation>, queue: &mut Vec<String>, funct
|
||||
let val = queue.remove(0);
|
||||
if val == "true"
|
||||
{
|
||||
output += interpret_program(if_block, queue, functions, arrays, intrinsics, debug).as_str();
|
||||
output += interpret_program(if_block, queue, functions, arrays, intrinsics, debug)?.as_str();
|
||||
}
|
||||
else if let Some(else_block) = maybe_else_block
|
||||
{
|
||||
output += interpret_program(else_block, queue, functions, arrays, intrinsics, debug).as_str();
|
||||
output += interpret_program(else_block, queue, functions, arrays, intrinsics, debug)?.as_str();
|
||||
}
|
||||
}
|
||||
Operation::Intrinsic(intrinsic_name, line, col) =>
|
||||
@ -337,7 +336,7 @@ fn interpret_program(operations: &Vec<Operation>, queue: &mut Vec<String>, funct
|
||||
}
|
||||
_ =>
|
||||
{
|
||||
panic!("Unexpected intrinsic '{}' at {}:{}", intrinsic_name, line, col);
|
||||
return Err(format!("Unexpected intrinsic '{}' at {}:{}", intrinsic_name, line, col));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -351,7 +350,11 @@ fn interpret_program(operations: &Vec<Operation>, queue: &mut Vec<String>, funct
|
||||
let position: i64 = queue.remove(0).parse::<i64>().unwrap();
|
||||
if position >= arr.length
|
||||
{
|
||||
panic!("Attempted an out of bounds write for array {} ({} >= {}) at {}:{}", arr.name, position, arr.length, line, col);
|
||||
return Err(format!("Attempted an out of bounds write for array {} ({} >= {}) at {}:{}", arr.name, position, arr.length, line, col));
|
||||
}
|
||||
if position < 0
|
||||
{
|
||||
return Err(format!("Attempted an out of bounds write for array {} ({} < 0) at {}:{}", arr.name, position, line, col));
|
||||
}
|
||||
arr.data[position as usize] = queue.remove(0);
|
||||
}
|
||||
@ -360,7 +363,11 @@ fn interpret_program(operations: &Vec<Operation>, queue: &mut Vec<String>, funct
|
||||
let position: i64 = queue.remove(0).parse::<i64>().unwrap();
|
||||
if position >= arr.length
|
||||
{
|
||||
panic!("Attempted an out of bounds read for array {} ({} >= {}) at {}:{}", arr.name, position, arr.length, line, col);
|
||||
return Err(format!("Attempted an out of bounds read for array {} ({} >= {}) at {}:{}", arr.name, position, arr.length, line, col));
|
||||
}
|
||||
if position < 0
|
||||
{
|
||||
return Err(format!("Attempted an out of bounds read for array {} ({} < 0) at {}:{}", arr.name, position, line, col));
|
||||
}
|
||||
queue.push(arr.data[position as usize].clone());
|
||||
}
|
||||
@ -368,7 +375,7 @@ fn interpret_program(operations: &Vec<Operation>, queue: &mut Vec<String>, funct
|
||||
{
|
||||
queue.push(arr.length.to_string());
|
||||
}
|
||||
_ => panic!("Unexpected application '{}' at {}:{}", word, line, col)
|
||||
_ => return Err(format!("Unexpected application '{}' at {}:{}", word, line, col))
|
||||
}
|
||||
}
|
||||
Operation::While(while_block, _, _) =>
|
||||
@ -380,7 +387,7 @@ fn interpret_program(operations: &Vec<Operation>, queue: &mut Vec<String>, funct
|
||||
{
|
||||
break;
|
||||
}
|
||||
output += interpret_program(while_block, queue, functions, arrays, intrinsics, debug).as_str();
|
||||
output += interpret_program(while_block, queue, functions, arrays, intrinsics, debug)?.as_str();
|
||||
}
|
||||
}
|
||||
Operation::Depth(_, _) =>
|
||||
@ -398,7 +405,7 @@ fn interpret_program(operations: &Vec<Operation>, queue: &mut Vec<String>, funct
|
||||
println!("after: {:?}: {:?}, '{}'", operation, queue, output);
|
||||
}
|
||||
}
|
||||
return output;
|
||||
return Ok(output);
|
||||
}
|
||||
|
||||
fn typecheck(operations: &Vec<Operation>, functions: &Vec<Function>, intrinsics: &HashMap<&str, (Vec<Datatype>, Vec<Datatype>)>, arrays: &Vec<Arr>, debug: bool) -> Result<(), String>
|
||||
@ -627,6 +634,10 @@ fn get_return_type(operations: &Vec<Operation>, ins: &Vec<Datatype>, functions:
|
||||
return Err(format!("Expected a position for a write application at {}:{}", line, col));
|
||||
}
|
||||
let expected_type = arrays.iter().find(|x| &x.name == name).unwrap().datatype;
|
||||
if type_queue.is_empty()
|
||||
{
|
||||
return Err(format!("Expected data for a write application at {}:{}", line, col));
|
||||
}
|
||||
let actual_type = type_queue.remove(0);
|
||||
if actual_type != expected_type
|
||||
{
|
||||
@ -1188,7 +1199,14 @@ fn tokenize(text: &str) -> Result<Vec<Token>, String>
|
||||
TokenizerState::Whitespace | TokenizerState::Comment => {},
|
||||
TokenizerState::Keyword =>
|
||||
{
|
||||
tokens.push(Token::Keyword(word.clone(), line, col));
|
||||
if application_name.is_empty()
|
||||
{
|
||||
tokens.push(Token::Keyword(word.clone(), line, col));
|
||||
}
|
||||
else
|
||||
{
|
||||
tokens.push(Token::Apply(application_name.clone(), word.clone(), line, col));
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(tokens)
|
||||
|
5
tests/array_oob_high_read.qbl
Normal file
5
tests/array_oob_high_read.qbl
Normal file
@ -0,0 +1,5 @@
|
||||
//invalid,Attempted an out of bounds read for array test (5 >= 4) at 5:12:END:
|
||||
|
||||
arr test { bool 4 }
|
||||
|
||||
5 test.read deq
|
5
tests/array_oob_high_write.qbl
Normal file
5
tests/array_oob_high_write.qbl
Normal file
@ -0,0 +1,5 @@
|
||||
//invalid,Attempted an out of bounds write for array test (5 >= 4) at 5:19:END:
|
||||
|
||||
arr test { bool 4 }
|
||||
|
||||
5 false test.write
|
5
tests/array_oob_low_read.qbl
Normal file
5
tests/array_oob_low_read.qbl
Normal file
@ -0,0 +1,5 @@
|
||||
//invalid,Attempted an out of bounds read for array test (-1 < 0) at 5:13:END:
|
||||
|
||||
arr test { bool 4 }
|
||||
|
||||
-1 test.read deq
|
5
tests/array_oob_low_write.qbl
Normal file
5
tests/array_oob_low_write.qbl
Normal file
@ -0,0 +1,5 @@
|
||||
//invalid,Attempted an out of bounds write for array test (-1 < 0) at 5:19:END:
|
||||
|
||||
arr test { bool 4 }
|
||||
|
||||
-1 true test.write
|
25
tests/array_tests.qbl
Normal file
25
tests/array_tests.qbl
Normal file
@ -0,0 +1,25 @@
|
||||
//valid,0000
|
||||
//0100
|
||||
//2100
|
||||
//2103
|
||||
//:END:
|
||||
arr test { int 4 }
|
||||
|
||||
function => dump
|
||||
{
|
||||
true 0
|
||||
while
|
||||
{
|
||||
dup test.read req print
|
||||
1 + test.length dup < req
|
||||
}
|
||||
deq "" println
|
||||
}
|
||||
|
||||
dump
|
||||
1 1 test.write
|
||||
dump
|
||||
0 2 test.write
|
||||
dump
|
||||
3 3 test.write
|
||||
dump
|
@ -1,14 +1,38 @@
|
||||
//valid,00000000000000110000000000000000
|
||||
//00000000000001110000000000000000
|
||||
//00000000000011010000000000000000
|
||||
//00000000000111110000000000000000
|
||||
//00000000001100010000000000000000
|
||||
//00000000011100110000000000000000
|
||||
//00000000110101110000000000000000
|
||||
//00000001111111010000000000000000
|
||||
//00000011000001110000000000000000
|
||||
//00000111000011010000000000000000
|
||||
//00001101000111110000000000000000
|
||||
//valid,---------------------------------#
|
||||
//--------------------------------##
|
||||
//-------------------------------###
|
||||
//------------------------------##-#
|
||||
//-----------------------------#####
|
||||
//----------------------------##---#
|
||||
//---------------------------###--##
|
||||
//--------------------------##-#-###
|
||||
//-------------------------#######-#
|
||||
//------------------------##-----###
|
||||
//-----------------------###----##-#
|
||||
//----------------------##-#---#####
|
||||
//---------------------#####--##---#
|
||||
//--------------------##---#-###--##
|
||||
//-------------------###--####-#-###
|
||||
//------------------##-#-##--#####-#
|
||||
//-----------------########-##---###
|
||||
//----------------##------####--##-#
|
||||
//---------------###-----##--#-#####
|
||||
//--------------##-#----###-####---#
|
||||
//-------------#####---##-###--#--##
|
||||
//------------##---#--#####-#-##-###
|
||||
//-----------###--##-##---########-#
|
||||
//----------##-#-######--##------###
|
||||
//---------#######----#-###-----##-#
|
||||
//--------##-----#---####-#----#####
|
||||
//-------###----##--##--###---##---#
|
||||
//------##-#---###-###-##-#--###--##
|
||||
//-----#####--##-###-######-##-#-###
|
||||
//----##---#-#####-###----########-#
|
||||
//---###--####---###-#---##------###
|
||||
//--##-#-##--#--##-###--###-----##-#
|
||||
//-########-##-#####-#-##-#----#####
|
||||
//##------######---########---##---#
|
||||
//##-----##----#--##------#--###--##
|
||||
//:END:
|
||||
function bool bool bool => bool rule110
|
||||
{
|
||||
@ -35,9 +59,10 @@ function bool bool bool => bool rule110
|
||||
}
|
||||
}
|
||||
|
||||
arr val { bool 32 }
|
||||
arr val { bool 34 }
|
||||
|
||||
15 true val.write
|
||||
33 true val.write
|
||||
printArrays
|
||||
|
||||
function int => bool int check
|
||||
{
|
||||
@ -46,7 +71,13 @@ function int => bool int check
|
||||
|
||||
function => fullApply
|
||||
{
|
||||
0 false val2.write
|
||||
// 0 b c
|
||||
0 1 false val.read val.read
|
||||
0 rule110 val2.write
|
||||
val.length 1 - 1 dup - req
|
||||
val.read val.read false
|
||||
rule110 val.length 1
|
||||
req - req val2.write
|
||||
true 1
|
||||
while
|
||||
{
|
||||
@ -62,7 +93,7 @@ function => fullApply
|
||||
dup val2.write
|
||||
checkUp-1
|
||||
}
|
||||
1 - false val2.write
|
||||
deq
|
||||
}
|
||||
|
||||
function int => bool int checkUp
|
||||
@ -79,7 +110,7 @@ function int => bool int checkUp-1
|
||||
< req
|
||||
}
|
||||
|
||||
arr val2 { bool 32 }
|
||||
arr val2 { bool 34 }
|
||||
|
||||
function => copyArrays
|
||||
{
|
||||
@ -93,15 +124,15 @@ function => copyArrays
|
||||
deq
|
||||
}
|
||||
|
||||
function bool => int boolToInt
|
||||
function bool => str boolToSym
|
||||
{
|
||||
if
|
||||
{
|
||||
1
|
||||
"#"
|
||||
}
|
||||
else
|
||||
{
|
||||
0
|
||||
"-"
|
||||
}
|
||||
}
|
||||
|
||||
@ -110,14 +141,14 @@ function => printArrays
|
||||
true 0
|
||||
while
|
||||
{
|
||||
dup val.read req boolToInt req print
|
||||
dup val.read req boolToSym req print
|
||||
checkUp
|
||||
}
|
||||
deq
|
||||
"" println
|
||||
}
|
||||
|
||||
true 10
|
||||
true 33
|
||||
while
|
||||
{
|
||||
fullApply
|
||||
@ -125,4 +156,4 @@ while
|
||||
printArrays
|
||||
check
|
||||
}
|
||||
deq
|
||||
deq
|
||||
|
Reference in New Issue
Block a user