Skip to content

Commit 943b905

Browse files
committed
basics on return statements, and start on math package
1 parent 73ecb28 commit 943b905

File tree

10 files changed

+465
-71
lines changed

10 files changed

+465
-71
lines changed

lang/examples/advanced_math.modu

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// Todo: implement more stuff
2+
3+
import "math" as math;
4+
5+
print(math.div(1, 3));
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
fn add_five(a) {
2+
let b = a + 5;
3+
return b;
4+
print("oh nyo")
5+
}
6+
7+
let a = add_five(5);
8+
print(a);

lang/src/ast.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
use std::{collections::HashMap, fmt::write};
2+
use std::collections::HashMap;
33

44
#[derive(Debug, PartialEq, Clone)]
55
pub enum AST {
@@ -52,6 +52,11 @@ pub enum AST {
5252
line: usize,
5353
},
5454

55+
Return {
56+
value: Box<AST>,
57+
line: usize,
58+
},
59+
5560
InternalFunction {
5661
name: String,
5762
args: Vec<String>,

lang/src/eval.rs

Lines changed: 49 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use crate::ast::AST;
22

33
use std::{collections::HashMap, path::PathBuf};
44
use crate::utils;
5+
use crate::packages::get_package;
56

67
pub fn eval(expr: AST, context: &mut HashMap<String, AST>) -> Result<AST, String> {
78
let mut depth = 0;
@@ -22,6 +23,10 @@ pub fn eval(expr: AST, context: &mut HashMap<String, AST>) -> Result<AST, String
2223
}
2324

2425
for expr in body {
26+
if let AST::Return { value, line: _ } = expr {
27+
return eval(*value.clone(), &mut new_context);
28+
}
29+
2530
eval(expr.clone(), &mut new_context)?;
2631
}
2732
} else {
@@ -93,39 +98,50 @@ pub fn eval(expr: AST, context: &mut HashMap<String, AST>) -> Result<AST, String
9398
let path: PathBuf;
9499

95100
if args.len() > 2 {
96-
path = std::path::Path::new(&args[2]).parent().unwrap().join(file.unwrap().replace("\"", ""));
101+
path = std::path::Path::new(&args[2]).parent().unwrap().join(file.clone().unwrap().replace("\"", ""));
97102
} else {
98-
path = file.unwrap().replace("\"", "").into();
103+
path = file.clone().unwrap().replace("\"", "").into();
99104
}
100105

101-
match std::fs::read_to_string(&path) {
102-
Ok(file) => {
103-
let mut new_context = context.clone();
104-
105-
match crate::parser::parse(&file, &mut new_context) {
106-
Ok(_) => {
107-
let mut properties = crate::utils::create_context();
108-
109-
for (name, value) in new_context {
110-
properties.insert(name, value);
106+
if path.ends_with(".modu") {
107+
match std::fs::read_to_string(&path) {
108+
Ok(file) => {
109+
let mut new_context = context.clone();
110+
111+
match crate::parser::parse(&file, &mut new_context) {
112+
Ok(_) => {
113+
let mut properties = crate::utils::create_context();
114+
115+
for (name, value) in new_context {
116+
properties.insert(name, value);
117+
}
118+
119+
context.insert(as_.unwrap(), AST::Object { properties, line });
120+
}
121+
122+
Err(e) => {
123+
return Err(e.0);
111124
}
112-
113-
context.insert(as_.unwrap(), AST::Object { properties, line });
114-
}
115-
116-
Err(e) => {
117-
return Err(e.0);
118125
}
119126
}
127+
128+
Err(e) => {
129+
dbg!(path);
130+
131+
return Err(e.to_string());
132+
}
120133
}
134+
} else {
135+
let package = get_package(&file.clone().unwrap().replace("\"", ""));
121136

122-
Err(e) => {
123-
dbg!(path);
124-
125-
return Err(e.to_string());
137+
if let Some(package) = package {
138+
if let AST::Object { properties, line } = package {
139+
context.insert(as_.unwrap(), AST::Object { properties, line });
140+
}
141+
} else {
142+
return Err(format!("Package {} not found", file.unwrap().replace("\"", "")));
126143
}
127144
}
128-
129145
}
130146

131147
AST::PropertyCall { object, property, args, line } => {
@@ -154,8 +170,16 @@ pub fn eval(expr: AST, context: &mut HashMap<String, AST>) -> Result<AST, String
154170
}
155171
}
156172

173+
AST::InternalFunction { name, args: f_args, call_fn } => {
174+
if args.len() == f_args.len() {
175+
return call_fn(args, context);
176+
} else {
177+
return Err(format!("{} takes {} arguments", name, f_args.len()));
178+
}
179+
}
180+
157181
_ => {
158-
return Err(format!("{} of {} is not a function", property.as_ref().unwrap(), name));
182+
return Err(format!("{} on object {} is not a function", property.as_ref().unwrap(), name));
159183
}
160184
}
161185
}
@@ -390,9 +414,7 @@ pub fn eval(expr: AST, context: &mut HashMap<String, AST>) -> Result<AST, String
390414
}
391415
}
392416

393-
unsafe {
394-
depth -= 1;
395-
}
417+
depth -= 1;
396418

397419
Ok(AST::Null)
398420
}

lang/src/internal.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ use std::collections::HashMap;
55
use crate::ast::AST;
66
use crate::eval::eval;
77

8-
pub fn print(ast: Vec<AST>, context: &mut HashMap<String, AST>) -> Result<AST, String> {
9-
match eval(ast[0].clone(), context) {
8+
pub fn print(args: Vec<AST>, context: &mut HashMap<String, AST>) -> Result<AST, String> {
9+
match eval(args[0].clone(), context) {
1010
Ok(ast) => {
1111
println!("{}", ast);
1212
return Ok(ast);

lang/src/lexer.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ pub enum Token {
2323
#[token("import")]
2424
Import,
2525

26+
#[token("return")]
27+
Return,
28+
2629
#[token("as")]
2730
As,
2831

lang/src/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ mod eval;
77
mod utils;
88
mod internal;
99
mod cli;
10+
mod packages;
1011

1112

1213
fn main() {

lang/src/packages/math.rs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
use std::collections::HashMap;
2+
3+
use crate::ast::AST;
4+
use crate::eval::eval;
5+
6+
pub fn div(args: Vec<AST>, _: &mut HashMap<String, AST>) -> Result<AST, String> {
7+
match (eval(args[0].clone(), &mut HashMap::new()), eval(args[1].clone(), &mut HashMap::new())) {
8+
(Ok(AST::Number(a)), Ok(AST::Number(b))) => {
9+
if b == 0 {
10+
return Err("cannot divide by zero".to_string());
11+
}
12+
13+
let result = a as f64 / b as f64;
14+
15+
if result.fract() == 0.0 {
16+
return Ok(AST::Number(result as i64));
17+
}
18+
19+
return Ok(AST::Float(result));
20+
}
21+
22+
(Ok(AST::Float(a)), Ok(AST::Float(b))) => {
23+
if b == 0.0 {
24+
return Err("cannot divide by zero".to_string());
25+
}
26+
27+
return Ok(AST::Float(a / b));
28+
}
29+
30+
(Ok(AST::Float(a)), Ok(AST::Number(b))) => {
31+
if b == 0 {
32+
return Err("cannot divide by zero".to_string());
33+
}
34+
35+
return Ok(AST::Float(a / b as f64));
36+
}
37+
38+
(Ok(AST::Number(a)), Ok(AST::Float(b))) => {
39+
if b == 0.0 {
40+
return Err("cannot divide by zero".to_string());
41+
}
42+
43+
return Ok(AST::Float(a as f64 / b));
44+
}
45+
46+
_ => {
47+
return Err("div requires 2 numbers".to_string());
48+
}
49+
}
50+
}
51+
52+
pub fn get_object() -> HashMap<String, AST> {
53+
let mut objects = HashMap::new();
54+
55+
objects.insert(
56+
"div".to_string(),
57+
AST::InternalFunction {
58+
name: "div".to_string(),
59+
args: vec!["a".to_string(), "b".to_string()],
60+
call_fn: div,
61+
}
62+
);
63+
64+
objects
65+
}

lang/src/packages/mod.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
mod math;
2+
3+
use crate::ast::AST;
4+
5+
pub fn get_package(name: &str) -> Option<AST> {
6+
match name {
7+
"math" => {
8+
Some(AST::Object {
9+
properties: math::get_object(),
10+
line: 0,
11+
})
12+
}
13+
_ => None
14+
}
15+
}

0 commit comments

Comments
 (0)