various fixes

This commit is contained in:
JOLIMAITRE Matthieu 2023-06-12 01:02:07 +02:00
parent c08c263f32
commit 28377bd3c2
11 changed files with 149 additions and 87 deletions

32
Cargo.lock generated
View file

@ -28,9 +28,9 @@ dependencies = [
[[package]]
name = "const-random"
version = "0.1.13"
version = "0.1.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f590d95d011aa80b063ffe3253422ed5aa462af4e9867d43ce8337562bac77c4"
checksum = "368a7a772ead6ce7e1de82bfb04c485f3db8ec744f72925af5735e29a22cc18e"
dependencies = [
"const-random-macro",
"proc-macro-hack",
@ -38,12 +38,12 @@ dependencies = [
[[package]]
name = "const-random-macro"
version = "0.1.13"
version = "0.1.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "615f6e27d000a2bffbc7f2f6a8669179378fa27ee4d0a509e985dfc0a7defb40"
checksum = "9d7d6ab3c3a2282db210df5f02c4dab6e0a7057af0fb7ebd4070f30fe05c0ddb"
dependencies = [
"getrandom",
"lazy_static",
"once_cell",
"proc-macro-hack",
"tiny-keccak",
]
@ -65,12 +65,6 @@ dependencies = [
"wasi",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.126"
@ -78,18 +72,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
[[package]]
name = "proc-macro-hack"
version = "0.5.19"
name = "once_cell"
version = "1.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
[[package]]
name = "prout"
version = "0.3.0"
name = "porte"
version = "0.4.0"
dependencies = [
"chumsky",
]
[[package]]
name = "proc-macro-hack"
version = "0.5.20+deprecated"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068"
[[package]]
name = "tiny-keccak"
version = "2.0.2"

View file

@ -1,11 +1,11 @@
[package]
name = "prout"
version = "0.3.0"
name = "porte"
version = "0.4.0"
edition = "2021"
authors = ["JOLIMAITRE Matthieu <matthieu@imagevo.fr>"]
description = "A minimal programming language providing tools to automate file management like backups, building process or unit testing."
license = "MIT"
repository = "https://github.com/MajorBarnulf/prout"
repository = "https://github.com/MajorBarnulf/porte"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

View file

@ -1,15 +1,15 @@
# PROUT
# PORTE
* Programmable
* Repeatable
* Opinionated
* Understandable
* Repeatable
* Tiny
* Extensible
## Description
PROUT is a minimal programming language providing tools to automate file management like backups, building process or unit testing.
PORTE is a minimal programming language providing tools to automate file management like backups, building process or unit testing.
## Usage
@ -17,7 +17,7 @@ PROUT is a minimal programming language providing tools to automate file managem
```sh
$ prout hello-world.pr
$ porte hello-world.pr
```

View file

@ -22,6 +22,13 @@ array_get: (self, index) => {
get(self, str(index))
};
foreach: (arr, f) => {
l: array_len(arr);
for(0, l, (i) => {
f(array_get(arr, i))
})
};
array_push: (self, e) => {
i: array_len(self);
self <- set(self, str(i), e);
@ -39,30 +46,72 @@ array_pop: (self) => {
e: array_get(self, i);
self <- set(self, str(i), false);
rest: array_new();
foreach(self, (item) => { if not(eq(item, false)) rest <- array_push(rest, item) });
r: obj();
r <- set(r, "tail", e);
r <- set(r, "rest", self);
r <- set(r, "rest", rest);
r
};
array_swap: (self, i, j) => {
i_value: array_get(self, i);
j_value: array_get(self, j);
self <- set(self, str(j), i_value);
self <- set(self, str(i), j_value);
self
};
array_sort: (self, cmp) => {
l: array_len(self);
for(0, sub(l, 1), (i) => {
i_min: i;
for(add(i, 1), l, (j) => {
e_j: array_get(self, j);
e_min: array_get(self, i_min);
if inf(cmp(e_j, e_min), 0) i_min <- j
});
self <- array_swap(self, i, i_min)
});
self
};
array_print: (self) => {
l: array_len(self);
r: "[ ";
for(0, l, (i) => {
r <- add(r, array_get(self, i));
r <- add(r, ", ")
if not(eq(i, sub(l, 1))) r <- add(r, ", ")
});
r <- add(r, " ]");
out(r)
};
main: () => {
a: array_new();
a <- array_push(a, 1);
a <- array_push(a, 2);
a <- array_push(a, 3);
a <- array_push(a, 4);
array_print(a)
};
"########################";
"# main #";
"########################";
main();
a: array_new();
out("new:");
array_print(a);
a <- array_push(a, 1);
a <- array_push(a, 4);
a <- array_push(a, 6);
a <- array_push(a, 3);
a <- array_push(a, 2);
out("");
out("pushed:");
array_print(a);
r: array_pop(a);
a <- get(r, "rest");
out("");
out("popped:");
array_print(a);
a <- array_sort(a, (a, b) => { if sup(a, b) 1 else -1 });
out("");
out("sorted:");
array_print(a);

View file

@ -1,10 +1,10 @@
hello: "hello";
prout: "prout";
porte: "porte";
line: hello;
line <- add(line, " ");
line <- add(line, prout);
line <- add(line, porte);
say-it: () => {
out(line)

View file

@ -73,7 +73,7 @@ impl Parser {
let parent_scope_id = parser_scope.get_parent_id();
let expressions = instructions
.into_iter()
.map(|expression| self.parse_expression(expression, &parser_scope))
.map(|expression| self.parse_expression(expression, parser_scope))
.collect();
let local_variables = parser_scope.local_variable_ids();
@ -218,7 +218,7 @@ impl Parser {
let variable_id = parser_scope
.get_variable_id(&name)
.expect(&format!("call of undeclared function '{name}'"));
.unwrap_or_else(|| panic!("call of undeclared function '{name}'"));
let parameters = arguments
.into_iter()
.map(|argument| self.parse_expression(argument, parser_scope))
@ -390,7 +390,7 @@ impl ParserScope {
next_id: self.next_id.clone(),
variables: Rc::new(Mutex::new(variables)),
current_id,
current_function_scope_id: Some(current_id.clone()),
current_function_scope_id: Some(current_id),
current_loop_scope_id: None,
}
}
@ -409,24 +409,24 @@ impl ParserScope {
variables: Rc::new(Mutex::new(variables)),
current_id,
current_function_scope_id: self.get_current_function_id(),
current_loop_scope_id: Some(current_id.clone()),
current_loop_scope_id: Some(current_id),
}
}
pub fn get_current_id(&self) -> Id {
self.current_id.clone()
self.current_id
}
pub fn get_current_function_id(&self) -> Option<Id> {
self.current_function_scope_id.clone()
self.current_function_scope_id
}
pub fn get_current_loop_id(&self) -> Option<Id> {
self.current_loop_scope_id.clone()
self.current_loop_scope_id
}
pub fn get_parent_id(&self) -> Option<Id> {
self.parent_id.clone()
self.parent_id
}
pub fn get_variable_id(&self, name: &str) -> Option<Id> {

View file

@ -1,20 +1,20 @@
use std::{env::args, fs};
pub mod demo;
pub mod execution_tree;
pub mod prelude;
pub mod runtime;
pub mod syntax_tree;
pub mod value;
pub mod demo;
fn main() {
use prelude::std_prelude;
let path = args().nth(1).expect("[error]: usage 'prout <path>'");
let path = args().nth(1).expect("[error]: usage 'porte <path>'");
let input = fs::read_to_string(path).expect("file not found");
let ast_parser = syntax_tree::parser::ParserWrapper::new();
let parsed = ast_parser.parse(&input).unwrap();
let executable = execution_tree::parser::Parser::parse(parsed, |b| std_prelude(b));
let executable = execution_tree::parser::Parser::parse(parsed, std_prelude);
let mut runtime = runtime::Runtime::new();
runtime.execute(&executable);
}
@ -40,11 +40,11 @@ fn it_works() {
]),
),
),
Expr::new_function_call("my_print", vec!["hello, PROUT".into()]),
Expr::new_function_call("my_print", vec!["hello, PORTE".into()]),
Expr::new_function_call("print", vec![Expr::new_variable_call("a")]),
]),
};
let exec = Parser::parse(ast, |builder| std_prelude(builder));
let exec = Parser::parse(ast, std_prelude);
println!("\n\n\n-- running: --");
let _result = Runtime::new().execute(&exec);
}

View file

@ -6,7 +6,8 @@ use crate::{
};
pub fn std_prelude(builder: &mut ParserBuilder) {
let functions: Vec<(_, _, fn(Vec<Value>) -> Value)> = vec![
type FunctOper = fn(Vec<Value>) -> Value;
let functions: Vec<(_, _, FunctOper)> = vec![
("out", 1, out),
("add", 2, add),
("sub", 2, sub),
@ -42,7 +43,7 @@ fn add(args: Vec<Value>) -> Value {
(Value::String(l), Value::String(r)) => format!("{l}{r}").into(),
(Value::Number(l), Value::String(r)) => format!("{l}{r}").into(),
(Value::String(l), Value::Number(r)) => format!("{l}{r}").into(),
_ => unreachable!(),
_ => panic!("adding incompatible types"),
}
}
@ -62,7 +63,7 @@ fn eq(args: Vec<Value>) -> Value {
(Value::Bool(l), Value::Bool(r)) => (l == r).into(),
(Value::Number(l), Value::Number(r)) => (l == r).into(),
(Value::String(l), Value::String(r)) => (l == r).into(),
_ => panic!("comparing different types"),
_ => false.into(),
}
}
@ -143,8 +144,5 @@ fn set(args: Vec<Value>) -> Value {
fn get(args: Vec<Value>) -> Value {
let object = args.get(0).unwrap().as_object().unwrap();
let name = args.get(1).unwrap().as_string().unwrap();
object
.get(name)
.map(|value| value.clone())
.unwrap_or_else(|| false.into())
object.get(name).cloned().unwrap_or_else(|| false.into())
}

View file

@ -24,7 +24,7 @@ impl FrameBuilder {
}
pub fn variable(&mut self, variable_id: &Id, default: Value) {
self.variables.insert(variable_id.clone(), default);
self.variables.insert(*variable_id, default);
}
}
@ -52,7 +52,7 @@ impl Frame {
builder(&mut frame_builder);
let FrameBuilder { variables } = frame_builder;
let scope_id = scope_id.clone();
let scope_id = *scope_id;
Self {
_scope_id: scope_id,
variables,
@ -99,6 +99,12 @@ impl Stack {
}
}
impl Default for Stack {
fn default() -> Self {
Self::new()
}
}
pub struct ShortCircuit {
value: Value,
destination_scope_id: Id,
@ -138,9 +144,9 @@ impl ExecReturn {
}
}
impl Into<ExecReturn> for Value {
fn into(self) -> ExecReturn {
ExecReturn::new_value(self)
impl From<Value> for ExecReturn {
fn from(val: Value) -> Self {
ExecReturn::new_value(val)
}
}
@ -169,7 +175,7 @@ impl Runtime {
where
F: FnOnce(&mut FrameBuilder),
{
let scope = program.scopes.get(&scope_id).unwrap();
let scope = program.scopes.get(scope_id).unwrap();
let Scope {
parent_scope_id: _,
expressions,
@ -210,9 +216,7 @@ impl Runtime {
ExprInner::FnDef(function_definition) => {
self.execute_function_definition(function_definition)
}
ExprInner::FnCall(function_call) => {
self.execute_function_call(function_call, program).into()
}
ExprInner::FnCall(function_call) => self.execute_function_call(function_call, program),
ExprInner::FnRet(function_return) => {
self.execute_function_return(function_return, program)
}
@ -272,7 +276,7 @@ impl Runtime {
parameter_ids: argument_ids,
body_scope_id,
} = function_definition;
let value = Function::new_constructed(argument_ids.clone(), body_scope_id.clone());
let value = Function::new_constructed(argument_ids.clone(), *body_scope_id);
let value = Value::Function(value);
value.into()
}
@ -367,7 +371,7 @@ impl Runtime {
}) => value,
};
ExecReturn::new_short_circuit(value, function_scope_id.clone())
ExecReturn::new_short_circuit(value, *function_scope_id)
}
pub fn execute_loop(&mut self, loop_: &Loop, program: &Program) -> ExecReturn {
@ -401,7 +405,7 @@ impl Runtime {
}
};
ExecReturn::new_short_circuit(value, loop_scope_id.clone())
ExecReturn::new_short_circuit(value, *loop_scope_id)
}
pub fn execute_condition(&mut self, condition: &Cond, program: &Program) -> ExecReturn {
@ -432,3 +436,9 @@ impl Runtime {
}
}
}
impl Default for Runtime {
fn default() -> Self {
Self::new()
}
}

View file

@ -52,8 +52,7 @@ pub fn literal_value() -> impl AbstractParser<Value> {
.unwrapped()
.map(|n: f64| n.into());
let literal = bool.or(none).or(string).or(number);
literal
bool.or(none).or(string).or(number)
}
#[test]
@ -66,11 +65,11 @@ fn test_literal_value() {
pub fn name() -> impl AbstractParser<String> + Clone {
let first = one_of("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
let rest = first.clone().or(one_of("1234567890-_+/*"));
let name = first.then(rest.repeated()).map(|(f, v)| {
first.then(rest.repeated()).map(|(f, v)| {
let rest = String::from_iter(&v);
format!("{f}{rest}")
});
name
})
}
pub fn variable_definition_parser(
@ -205,7 +204,7 @@ pub fn condition_parser(
just("if ")
.ignore_then(expression.clone())
.then(expression.clone())
.then(just("else ").ignore_then(expression.clone()).or_not())
.then(just("else ").ignore_then(expression).or_not())
.map(|((condition, arm_true), arm_false)| Cond {
condition,
arm_true,
@ -296,7 +295,7 @@ fn _sugar_parser(expression: impl AbstractParser<Expr> + Clone) -> impl Abstract
let and = expression
.clone()
.then_ignore(just(" && "))
.then(expression.clone())
.then(expression)
.map(|(l, r)| {
FnCall {
name: "and".into(),
@ -317,7 +316,7 @@ pub fn expression_parser() -> impl AbstractParser<Expr> {
let loop_ = loop_parser(expression.clone()).map(|i| i.into());
let loop_break = loop_break_parser(expression.clone()).map(|i| i.into());
let scope = scope_parser(expression.clone()).map(|i| i.into());
let litteral = literal_value().map(|v| Expr::new_literal(v));
let litteral = literal_value().map(Expr::new_literal);
let variable_definition = variable_definition_parser(expression.clone()).map(|i| i.into());
let variable_assignment = variable_assignement_parser(expression.clone()).map(|i| i.into());
let function_call = function_call_parser(expression.clone()).map(|i| i.into());
@ -354,11 +353,11 @@ fn parser() -> impl AbstractParser<Program> {
.separated_by(just(';').padded())
.then_ignore(just(';').padded().or_not())
.then_ignore(end());
let program = scope.map(|instructions| {
scope.map(|instructions| {
let body = Scope { instructions };
Program { body }
});
program
})
}
#[test]
@ -390,11 +389,17 @@ impl ParserWrapper {
ParserWrapper { inner }
}
pub fn parse<'i>(&self, input: &'i str) -> Result<Program, Vec<Simple<char>>> {
pub fn parse(&self, input: &str) -> Result<Program, Vec<Simple<char>>> {
self.inner.parse(input)
}
}
impl Default for ParserWrapper {
fn default() -> Self {
Self::new()
}
}
/*
// example

View file

@ -55,9 +55,9 @@ pub mod function {
}
}
impl Into<Value> for Function {
fn into(self) -> Value {
Value::Function(self)
impl From<Function> for Value {
fn from(val: Function) -> Self {
Value::Function(val)
}
}
}