Compare commits

...

5 Commits

Author SHA1 Message Date
0x4261756D 53cfd52dcd Improve rule110 2022-12-22 00:48:24 +01:00
0x4261756D 8397d32756 Add array tests 2022-12-22 00:48:02 +01:00
0x4261756D bf4a08e484 Make interpret fallible, fix applications at end of file, add more checks 2022-12-22 00:47:41 +01:00
0x4261756D 0abc74f043 Add editor syntax file 2022-12-22 00:45:59 +01:00
0x4261756D dedb601a9b Small updates to celebrate turing-completeness 2022-12-22 00:08:13 +01:00
10 changed files with 166 additions and 37 deletions

View File

@ -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:

View File

@ -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
View 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"

View File

@ -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)

View 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

View 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

View 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

View 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
View 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

View File

@ -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