Skip to content

Commit 3b47929

Browse files
committed
added new keyword type
working on docs removed a lot of the .uwnrap
1 parent 7073b4e commit 3b47929

File tree

10 files changed

+129
-71
lines changed

10 files changed

+129
-71
lines changed

README.md

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,67 @@ Too see the understand the keywords and their meaning, refer to [this file](http
1414
<br>
1515
There is semi working vscode extension for UMPL, you can find it [here](https://github.com/mendelsshop/UMPL_VSCode_Extension)
1616
<br>
17-
At UMPL to fix the null problem, we have invented a new type called hempty, which is the same as null, but it sounds better, and it adds to the long list of\ null like types across all the proggraming languages.
17+
At UMPL to fix the null problem, we have invented a new type called hempty, which is the same as null, but it sounds better, and it adds to the long list of null like types across all the proggraming languages.
1818
<br>
1919
All bug reports head straight to /dev/hempty
20+
21+
# language-documentation
22+
## Declarations
23+
| name | description | usage | special keywords | special variables | example(s) |
24+
|:---:|:---:|:---:|:---:|:---:|:---|
25+
| create | creates a variable | create var-name with literal or expression| N/A | N/A| ```create num-var with 5``` <br> ```create str-var with ((input `>> `))>``` ```create var with str-var```|
26+
| list | creates a list | list var-name with [literal or expression literal or expression]| N/A | N/A| ```list num-list with [1 3]``` <br> ```list str-list with [8, ((input `>> `))]```|
27+
| potato | declares a function | potato emoji-name num-of-args ⧼code⧽| return literal-or-expression| for each argument you get `$argument-number` ie `$1` for the first one etc | ```potato 😀 2 ⧼return ((plus $1 $2))>⧽```|
28+
29+
## Control Flow
30+
|name|description|usage|special keywords| example(s) |
31+
|:---:|:---:|:---:|:---:|:---|
32+
| if statement| if boolean is true do if code else do else code |if {boolean literal or expression} ⧼if code⧽ else ⧼else code⧽|N/A| ```if {true} ⧼(`true`)>⧽ else ⧼(`false`)>⧽``` <br> ```if {not((true))>} ⧼(`true`)>⧽ else ⧼(`false`)>⧽``` <br> ```if {boolean-var} ⧼if {true} ⧼(`true`)>⧽ else ⧼(`false`)>⧽ ⧽ else ⧼(`false`)>⧽```|
33+
| loop statement | loop until the code reaches break of continue |loop ⧼code⧽ |break, continue| ```loop ⧼ if {true} ⧼(`true`)> break ⧽ else ⧼(`false`)> continue ⧽⧽```
34+
35+
## Keywords
36+
### To call a keyword you first need create an expression so ()> or ()>> or ()< and in the expression you put another pair of parentheses and the keyeword and its arguments.
37+
| name | description| paremeters | returns | example(s) |
38+
| :-: | :-: | :-: | :-: | :- |
39+
| plus | if the first argument is a number, returns the sum of all the arguments, if its a string, each argument after is conctenated to the string, anything else wont work | any*1: argument | any |
40+
| minus| sets the first parameter to the original value each next argument is subtract to it unless there is one argument in which case it is negated returning the negative value of it | number*1: argument | number |
41+
|multiply| if the first arguments is string, multiplies the string by the next argument, if its a number, sets the first parameter to the original value each next argument is multiplied to it, any other thing does not work | any*1: argument | any |
42+
|divide| sets the first argument to the original value each next argument is divided by the previous divisor | number*1: argument | number |
43+
|not| returns true if the value is false, false otherwise | [boolean: value] | boolean |
44+
|or| comapares value1 and value2 and returns true if either is true | [boolean: value1, boolean: value2] | boolean |
45+
|and| comapares value1 and value2 and returns true if both are true | [boolean: value1, boolean: value2] | boolean |
46+
|eq| compare two values if they are equal | [boolean: value1, boolean: value2] | boolean |
47+
|ne | compare two values if not equal | [boolean: value1, boolean: value2] | boolean |
48+
|gt| checks if the number1 is greater than the number2 | [number: number1, number: number2] | boolean |
49+
|lt| check if the number1 is less than the number2 | [number: number1, number: number2] | boolean |
50+
|le| checks if the number1 is less than or equal to the right number2 | [number: number1, number: number2] | boolean |
51+
|ge| check if the number1 is greater than or equal to the number2 | [number: number1, number: number2] | boolean |
52+
|addwith| adds value to variable in place, if the variable is a string anything can added to it, but if its a number only number can, anything cannot be added to | [variable: variable, any: value] | number |
53+
|dividewith| divides value by variable in place | [variable: variable, number: value] | number |
54+
|subtractwith| subtracts value from variable in place | [variable: variable, number: value] | number |
55+
|multiplywith| multiplies value by variable in place, if variable is a string than the variable becomes the string value times, if the variable is a number we multiply the variable by the value, any other variable wont work | [variable: variable, number: value] | number |
56+
|input| input with message | [string: message] | string |
57+
|setwith| sets a variable to a value | [variable: variable , value*: any] | any |
58+
|exit| exits with number provided | [number: number] | hempty |
59+
|error| errors with error message provided | [string: message] | hempty |
60+
|strtonum| converts string to number | [string: string] | number |
61+
|strtobool| converts string to boolean | [string: string] | boolean |
62+
|strtohempty| converts string to hempty | [string: string] | hempty |
63+
|runcommand| runs os command | [string: command] | string |
64+
|open| opens file | [string: file] | file |
65+
|close| closes file | [file: file] | hempty |
66+
|write| writes message to file with mode | [file: file, string: message, string: mode] | hempty |
67+
|writeline| writes message to file at line with mode | [file: file, string: message, number: line, string: mode] | hempty |
68+
|read| reads from file | [file: file] | string |
69+
|readline| reads the line specified from the file | [file: file, number: line] | string |
70+
|delete| deletes variable | [variable: variable] | hempty |
71+
|deletefile | deletes file | [file: file] | hempty |
72+
|createfile| creates new file | [file: file] | file |
73+
|new| run custom function | function: name, arguments | whatever the function returns | ```((new 😀 3 5))>``` |
74+
|type | returns the type of the value | [any: value] | string | ```((type 1))>```|
75+
76+
`*`:
77+
sometimes you can set a variable to two values for making list in lists
78+
<br>
79+
`*1`:
80+
one or more arguments

keywords.md

Lines changed: 0 additions & 42 deletions
This file was deleted.

src/cli.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ pub fn get_dash_args(args: &[String], start_index: usize, args_struct: &mut Pars
7878
file if file.is_empty() => 0,
7979
file => file.len(),
8080
};
81-
unsafe { TOGGLE_CASE = num.try_into().unwrap() }
81+
unsafe { TOGGLE_CASE = num as i32 };
8282
} else if char_part_arg == 't' {
8383
let number: i32 = match arg.split_once('=') {
8484
Some(n) => match n.1.parse() {

src/eval.rs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,10 @@ impl Scope {
381381
}
382382
}
383383
pub fn drop_scope(&mut self) {
384-
let p_scope: Self = *self.parent_scope.take().unwrap();
384+
let p_scope: Self = match self.parent_scope.take(){
385+
Some(scope) => *scope,
386+
None => error(0, "no parent scope"),
387+
};
385388
*self = p_scope;
386389
}
387390

@@ -687,6 +690,17 @@ impl Eval {
687690
error(call.line, format!("Function {} is not defined", name));
688691
}
689692
}
693+
TokenType::Type => {
694+
arg_error(1, call.arguments.len() as u32, &call.keyword, false, call.line);
695+
match self.find_pointer_in_stuff(&call.arguments[0]) {
696+
LiteralOrFile::Literal(a) => {
697+
LiteralOrFile::Literal(LiteralType::String(a.get_type()))
698+
}
699+
LiteralOrFile::File(_) => {
700+
LiteralOrFile::Literal(LiteralType::String("file".to_string()))
701+
}
702+
}
703+
}
690704
TokenType::Delete => {
691705
if call.arguments.len() != 1 {
692706
error(call.line, "delete takes one argument");
@@ -1330,7 +1344,7 @@ impl Eval {
13301344

13311345
impl fmt::Debug for Eval {
13321346
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1333-
write!(f, "scope {:?}", self.scope).unwrap();
1347+
write!(f, "scope {:?}", self.scope)?;
13341348
Ok(())
13351349
}
13361350
}

src/keywords.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ impl Keyword {
6060
keywords.insert("writeline".to_string(), TokenType::WriteLine);
6161
keywords.insert("createfile".to_string(), TokenType::CreateFile);
6262
keywords.insert("deletefile".to_string(), TokenType::DeleteFile);
63+
keywords.insert("type".to_string(), TokenType::Type);
6364
if num != 0 {
6465
for (key, value) in &keywords.clone() {
6566
keywords.remove(key);

src/lexer.rs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ impl Lexer {
115115
false
116116
}
117117

118+
#[allow(clippy::too_many_lines)]
118119
fn string(&mut self) {
119120
while self.peek() != '`' && !self.is_at_end() {
120121
if self.peek() == '\n' {
@@ -168,17 +169,18 @@ impl Lexer {
168169
y if y.is_ascii_hexdigit() => {
169170
self.insert_text(
170171
self.current,
171-
u8::from_str_radix(format!("{x}{y}").as_str(), 16).unwrap()
172-
as char,
172+
u8::from_str_radix(format!("{x}{y}").as_str(), 16).unwrap_or_else(|_| {
173+
error::error(self.line, "invalid hex escape sequence");
174+
}) as char,
173175
);
174176
self.advance();
175177
}
176178
y => {
177179
self.insert_text(
178180
self.current,
179-
u8::from_str_radix(format!("{x}").as_str(), 16).unwrap()
180-
as char,
181-
);
181+
u8::from_str_radix(format!("{x}").as_str(), 16).unwrap_or_else(|_| {
182+
error::error(self.line, "invalid hex escape sequence");
183+
}) as char);
182184
self.insert_text(self.current + 1, y);
183185
self.advance();
184186
}
@@ -201,8 +203,11 @@ impl Lexer {
201203
}
202204
self.insert_text(
203205
self.current,
204-
char::from_u32(u32::from_str_radix(hex_string.as_str(), 16).unwrap())
205-
.unwrap(),
206+
char::from_u32(u32::from_str_radix(hex_string.as_str(), 16).unwrap_or_else(|_| {
207+
error::error(self.line, "invalid unicode escape sequence");
208+
} ) ).unwrap_or_else(|| {
209+
error::error(self.line, "invalid unicode escape sequence");
210+
})
206211
);
207212
self.current += 1;
208213
} else {

src/main.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ fn main() {
1616
cli::get_dash_args(&args, index, &mut parsed_args);
1717
}
1818
if parsed_args.log {
19-
log4rs::init_file("log.yaml", log4rs::config::Deserializers::default()).unwrap();
19+
log4rs::init_file("log.yaml", log4rs::config::Deserializers::default())
20+
.unwrap_or_else(|_| panic!("Failed to initialize log4rs"));
2021
info!("Starting up...");
2122
}
2223
let mut full_repl: Vec<String> = Vec::new(); // create a vector to hold the lines of the repl just in case we need to write it to a file
@@ -26,8 +27,8 @@ fn main() {
2627
'l: loop {
2728
let mut input = String::new();
2829
print!(">> "); // print the prompt
29-
io::stdout().flush().unwrap();
30-
io::stdin().read_line(&mut input).unwrap(); // read the input
30+
io::stdout().flush().unwrap_or_else(|_| panic!("Failed to flush stdout"));
31+
io::stdin().read_line(&mut input).unwrap_or_else(|_| panic!("Failed to read stdin"));
3132
if input.trim() == "exit" {
3233
// if the input is exit, then exit
3334
info!("Exiting...");
@@ -36,9 +37,9 @@ fn main() {
3637
if Path::new(&parsed_args.file).exists() && !parsed_args.force {
3738
// if the file exists and we are not forcing it to overwrite
3839
print!("Do you want to overwrite the {}? (y/n): ", parsed_args.file); // ask the user if they want to overwrite the file
39-
io::stdout().flush().unwrap();
40+
io::stdout().flush().unwrap_or_else(|_| panic!("Failed to flush stdout"));
4041
let mut y_or_n: String = String::new();
41-
io::stdin().read_line(&mut y_or_n).unwrap();
42+
io::stdin().read_line(&mut y_or_n).unwrap_or_else(|_| panic!("Failed to read stdin")); // read the input
4243
if y_or_n == "n" {
4344
// if the user does not want to overwrite the file exit
4445
exit(0);
@@ -62,7 +63,11 @@ fn main() {
6263
}
6364
} else {
6465
// if we are not in repl mode ie we are reading a file
65-
let mut file: File = File::open(&parsed_args.file).unwrap(); // open the file
66+
let mut file: File = File::open(&parsed_args.file).unwrap_or_else(
67+
|_| {
68+
error::error(0, "Error encountered while opening file!");
69+
},
70+
); // open the file
6671
let mut contents: String = String::new(); // create a string to hold the contents of the file
6772
match file.read_to_string(&mut contents) {
6873
Ok(contents) => contents,

src/parser/rules.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,15 @@ impl LiteralType {
147147
Self::Hempty => matches!(other, Self::Hempty),
148148
}
149149
}
150+
151+
pub fn get_type(&self) -> String {
152+
match self {
153+
Self::Number(_) => "number".to_string(),
154+
Self::String(_) => "string".to_string(),
155+
Self::Boolean(_) => "boolean".to_string(),
156+
Self::Hempty => "hempty".to_string(),
157+
}
158+
}
150159
}
151160

152161
impl Display for LiteralType {
@@ -238,8 +247,7 @@ impl Display for Call {
238247
} else {
239248
""
240249
}
241-
})
242-
.unwrap();
250+
})?
243251
}
244252
write!(f, "{:?}: [{}]", self.keyword, c)
245253
}

0 commit comments

Comments
 (0)