Skip to content

Commit 652d155

Browse files
committed
Last lua state
1 parent 7310cce commit 652d155

15 files changed

+898
-309
lines changed

Cargo.toml

+3-2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ version = "0.1.0"
55
edition = "2021"
66
license = "GPL-3.0"
77
repository = "https://github.com/Aviosium/fdl"
8+
build = "build.rs"
89

910
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
1011
[features]
@@ -14,5 +15,5 @@ fixed_point = []
1415
lalrpop = "0.20.0"
1516

1617
[dependencies]
17-
lalrpop-util = {version = "0.20", features = ["lexer"]}
18-
thiserror = "1.0.40"
18+
lalrpop-util = { version = "0.20", features = ["lexer"] }
19+
thiserror = "1.0.40"

build.rs

+37
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,40 @@
1+
use std::{
2+
fs::{rename, File},
3+
io::{BufRead, BufReader, BufWriter, Write},
4+
path::PathBuf,
5+
};
6+
7+
const TARGET: &str = "#[allow(clippy::too_many_arguments";
8+
19
fn main() {
10+
println!("cargo::rerun-if-changed=src/parser/language.lalrpop");
211
lalrpop::process_root().unwrap();
12+
let base_path = PathBuf::from(std::env::var_os("OUT_DIR").expect("missing OUT_DIR variable"));
13+
let path = base_path.join("parser/language.rs");
14+
let out_path = base_path.join("parser/language_out.rs");
15+
let input_file = File::open(&path).expect("Unable to open input file");
16+
let reader = BufReader::new(input_file);
17+
let output_file = File::create(&out_path).expect("unable to create output file");
18+
let mut writer = BufWriter::new(output_file);
19+
for line_result in reader.lines() {
20+
let mut line = line_result.expect("invalid line");
21+
22+
// Check if the line matches the pattern
23+
if line.starts_with(TARGET) {
24+
// Modify the line as needed
25+
line.insert_str(TARGET.len(), ", clippy::type_complexity, clippy::vec_box")
26+
}
27+
28+
if line.starts_with("mod") {
29+
writeln!(
30+
writer,
31+
"#[allow(clippy::vec_box, clippy::mixed_attributes_style)]"
32+
)
33+
.expect("Unabel to write file");
34+
}
35+
36+
// Write the line to the output file
37+
writeln!(writer, "{}", line).expect("Unable to write file");
38+
}
39+
rename(out_path, path).expect("unable to rename file");
340
}

examples/test.fdl

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
function $test(b: bounded<0..10>, c: nonzero<2..2>) -> bounded<0..5>
2+
let b: [[bounded<0..10>; 5]; 2] = [[b;5];2];
3+
b[0][8//2]//c
4+
end;
5+
6+
function $gen_obj(val: int) -> {name: {first: int, second: int?}, other: _}
7+
{
8+
name = {
9+
first = val,
10+
second = nil,
11+
},
12+
other = val,
13+
}
14+
end;
15+
16+
function $tast(a: bounded<1..>, b: bounded<..-1>) -> bounded<..0>
17+
a // b
18+
end;
19+
20+
function $abc(a: float) -> float
21+
let b: float = a;
22+
b
23+
end;
24+
25+
function $use_obj() -> int
26+
let {name: {first: int}, other} = $gen_obj(1);
27+
name.first
28+
end;
29+
30+
function $test_len(a: _) -> bounded<0..6>
31+
let b = [nil;6];
32+
#b
33+
end;
34+
35+
function $testt() -> int?
36+
end;
37+
38+
function $main() -> int
39+
$test(1, 2)
40+
end

src/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
mod error;
22
mod parser;
33
mod type_checker;
4+
5+
pub use parser::Parser;
6+
pub use type_checker::typecheck::TypeckState;

src/main.rs

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
use std::time::Instant;
2+
3+
use fdl::{Parser, TypeckState};
4+
5+
pub fn main() {
6+
let start = Instant::now();
7+
let mut parser = Parser::new();
8+
let path = std::env::args().nth(1).expect("Please provide a path");
9+
let content = std::fs::read_to_string(path).expect("Unable to read file");
10+
let result = match parser.parse(&content) {
11+
Ok(ast) => ast,
12+
Err(error) => {
13+
print!("{}", error.print(parser.get_manager()));
14+
return;
15+
}
16+
};
17+
let mut typecheck = TypeckState::new();
18+
match typecheck.check_script(&[result]) {
19+
Ok(_) => {}
20+
Err(error) => {
21+
print!("{}", error.print(parser.get_manager()));
22+
return;
23+
}
24+
}
25+
println!(
26+
"Sucessfully checked file in {:0.3}s",
27+
start.elapsed().as_secs_f64()
28+
);
29+
}

src/parser/ast.rs

+27-14
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,12 @@ pub enum UnOp {
4141
BitNot,
4242
}
4343

44+
type SpannedType = Spanned<Box<TypeExpr>>;
45+
4446
#[derive(Debug, Clone)]
4547
pub enum LetPattern {
46-
Var(String), // TODO
47-
Record(Vec<(Spanned<String>, Box<LetPattern>)>), // TODO
48+
Var((String, Option<Spanned<Readability>>, Option<SpannedType>)),
49+
Record(Vec<(Spanned<String>, Option<SpannedType>, Box<LetPattern>)>),
4850
}
4951

5052
#[derive(Debug, Clone)]
@@ -54,6 +56,7 @@ pub enum MatchPattern {
5456
}
5557

5658
#[derive(Debug, Clone)]
59+
#[allow(clippy::vec_box)]
5760
pub enum Expr {
5861
BinOp(Spanned<Box<Expr>>, Spanned<Box<Expr>>, Op, Span),
5962
UnOp(Spanned<Box<Expr>>, UnOp, Span),
@@ -84,35 +87,45 @@ pub enum TypeExpr {
8487
Vec<(Spanned<String>, Box<TypeExpr>)>,
8588
Span,
8689
), // TODO
87-
Func(Spanned<(Box<TypeExpr>, Box<TypeExpr>)>), // TODO
88-
Ident(Spanned<String>), // TODO
89-
Nullable(Box<TypeExpr>, Span), // TODO
90+
Ident(Spanned<String>), // TODO
91+
Nullable(Box<TypeExpr>, Span), // TODO
9092
Record(
9193
Option<Box<TypeExpr>>,
9294
Vec<(Spanned<String>, Box<TypeExpr>)>,
9395
Span,
9496
), // TODO
95-
Ref(Box<TypeExpr>, Spanned<Readability>), // TODO
96-
TypeVar(Spanned<String>), // TODO
97+
Ref(Box<TypeExpr>, Spanned<Readability>), // TODO
98+
TypeVar(Spanned<String>), // TODO
9799
Alias(Box<TypeExpr>, Spanned<String>),
100+
BoundedInt(
101+
Vec<(Option<Spanned<String>>, Option<Spanned<String>>)>,
102+
Span,
103+
),
104+
NonZero(SpannedType),
105+
Array(Box<TypeExpr>, String, Span),
98106
}
99107

100108
#[derive(Debug, Clone)]
101109
pub enum TopLevel {
102110
Expr(Box<Expr>),
103111
Block(Vec<TopLevel>, Option<Spanned<Box<Expr>>>),
104-
LetDef(
105-
String,
106-
Option<Spanned<Readability>>,
107-
Option<Spanned<Box<TypeExpr>>>,
108-
Box<Expr>,
109-
),
112+
LetDef(LetPattern, Box<Expr>),
110113
Assign(Spanned<String>, Spanned<Box<Expr>>),
111114
FuncDef(
112115
Spanned<(
113116
String,
114-
Vec<Spanned<(String, Option<Box<TypeExpr>>)>>,
117+
Vec<Spanned<(String, Box<TypeExpr>)>>,
118+
SpannedType,
115119
Box<TopLevel>,
116120
)>,
117121
),
118122
}
123+
124+
impl Default for TopLevel {
125+
fn default() -> Self {
126+
TopLevel::Expr(Box::new(Expr::Literal(
127+
Literal::Nil,
128+
("nil".to_string(), Span(0)),
129+
)))
130+
}
131+
}

src/parser/language.lalrpop

+47-6
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,20 @@ grammar(ctx: &mut spans::SpanMaker<'input>);
66

77
Ident: String = <r"[a-z_]\w*"> => String::from(<>);
88

9+
910
IntLiteral: String = {
10-
r"(?:0|[1-9][0-9]*)" => String::from(<>),
11+
r"0|[1-9][0-9]*" => String::from(<>),
12+
};
13+
SignedIntLiteral: String = {
14+
<IntLiteral>,
15+
r"-(?:0|[1-9][0-9]*)" => String::from(<>),
1116
};
17+
1218
FloatLiteral: String =
13-
r"(?:0|[1-9][0-9]*)\.[0-9]*(?:[eE]-?[0-9]+)?" => String::from(<>);
19+
<mut i:IntLiteral><f:r"\.[0-9]*(?:[eE]-?[0-9]+)?"> => {
20+
i.push_str(f);
21+
i
22+
};
1423

1524
Readability: ast::Readability = {
1625
"<readonly>" => ast::Readability::ReadOnly,
@@ -172,8 +181,26 @@ Expr = {
172181
If,
173182
};
174183

184+
TypeKeyPair: (spans::Spanned<String>, Box<ast::TypeExpr>) = {
185+
<Spanned<Ident>> ":" <TypeExpr>,
186+
};
187+
188+
Range: (Option<spans::Spanned<String>>, Option<spans::Spanned<String>>) = {
189+
<Spanned<SignedIntLiteral>?> ".." <Spanned<SignedIntLiteral>?>
190+
};
191+
192+
BoundedInt: Vec<(Option<spans::Spanned<String>>, Option<spans::Spanned<String>>)> = {
193+
SepList<Range, ",">
194+
};
195+
175196
TypeExpr: Box<ast::TypeExpr> = {
197+
"(" <TypeExpr> ")",
198+
<t:Spanned<("[" <TypeExpr> ";" <IntLiteral> "]")>> => Box::new(ast::TypeExpr::Array(t.0.0, t.0.1, t.1)),
199+
<t:Spanned<(<TypeExpr> "?")>> => Box::new(ast::TypeExpr::Nullable(t.0, t.1)),
200+
<s:Spanned<("bounded" "<" <BoundedInt> ">")>> => Box::new(ast::TypeExpr::BoundedInt(s.0, s.1)),
201+
<s:Spanned<("nonzero" "<" <Spanned<BoundedInt>> ">")>> => Box::new(ast::TypeExpr::NonZero((Box::new(ast::TypeExpr::BoundedInt(s.0.0, s.0.1)), s.1))),
176202
Spanned<Ident> => Box::new(ast::TypeExpr::Ident(<>)),
203+
<t:Spanned<("{" <SepList<TypeKeyPair, ",">> "}")>> => Box::new(ast::TypeExpr::Record(None, t.0, t.1)),
177204
};
178205

179206
CoreIf: Box<ast::Expr> = {
@@ -185,8 +212,22 @@ If: Box<ast::Expr> = {
185212
"if" <CoreIf>
186213
};
187214

215+
ReadableType: (Option<spans::Spanned<ast::Readability>>, Option<spans::Spanned<Box<ast::TypeExpr>>>) = {
216+
<Spanned<Readability>?> <(":" <Spanned<TypeExpr>>)?>
217+
}
218+
219+
KeyPairPattern: (spans::Spanned<String>, Option<spans::Spanned<Box<ast::TypeExpr>>>, Box<ast::LetPattern>) = {
220+
<name: Spanned<Ident>> "=" <pat: LetPattern> => (name, None, Box::new(pat)),
221+
<name: Spanned<Ident>> <type_: ReadableType> => (name.clone(), None, Box::new(ast::LetPattern::Var((name.0, type_.0, type_.1)))),
222+
}
223+
224+
LetPattern: ast::LetPattern = {
225+
<name: Ident> <type_: ReadableType> => ast::LetPattern::Var((name, type_.0, type_.1)),
226+
"{" <SepList<KeyPairPattern, ",">> "}" => ast::LetPattern::Record(<>),
227+
}
228+
188229
LetStatement: ast::TopLevel = {
189-
"let" <Ident> <Spanned<Readability>?> <(":" <Spanned<TypeExpr>>)?> "=" <Expr> => ast::TopLevel::LetDef(<>),
230+
"let" <LetPattern> "=" <Expr> => ast::TopLevel::LetDef(<>),
190231
};
191232

192233
Assignment: ast::TopLevel = {
@@ -205,9 +246,9 @@ ColonType = {
205246
}
206247

207248
FuncDef: ast::TopLevel = {
208-
Spanned<("function" "$" <Ident> "(" <SepList<Spanned<(Ident ColonType?)>, ",">> ")" <Block> "end")> => {
209-
let ((name, arguments, block), span) = <>;
210-
ast::TopLevel::FuncDef(((name, arguments, Box::new(block)), span))
249+
Spanned<("function" "$" <Ident> "(" <SepList<Spanned<(Ident ColonType)>, ",">> ")" "->" <Spanned<TypeExpr>> <Block> "end")> => {
250+
let ((name, arguments, retype, block), span) = <>;
251+
ast::TopLevel::FuncDef(((name, arguments, retype, Box::new(block)), span))
211252
}
212253
};
213254

src/parser/mod.rs

+14-9
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ fn convert_parse_error<T: Display>(
3636
ParseError::ExtraToken { token } => {
3737
SpannedError::new1("SyntaxError: Unexpected extra token", sm.span(token.0, token.2))
3838
}
39-
ParseError::User { error: msg } => unreachable!(),
39+
ParseError::User { error: _msg } => unreachable!(),
4040
}
4141
}
4242

@@ -53,23 +53,28 @@ impl Parser {
5353
}
5454
}
5555

56-
pub fn parse(
57-
&mut self,
58-
source_path: &str,
59-
content: &str,
60-
) -> Result<ast::TopLevel, SpannedError> {
61-
let mut span_maker = self.spans.add_source(source_path.to_string());
56+
pub fn parse(&mut self, content: &str) -> Result<ast::TopLevel, SpannedError> {
57+
let mut span_maker = self.spans.add_source(content.to_string());
6258

6359
self.parser
6460
.parse(&mut span_maker, content)
6561
.map_err(|e| convert_parse_error(span_maker, e))
6662
}
63+
64+
pub fn get_manager(&self) -> &SpanManager {
65+
&self.spans
66+
}
67+
}
68+
69+
impl Default for Parser {
70+
fn default() -> Self {
71+
Self::new()
72+
}
6773
}
6874

6975
#[cfg(test)]
7076
mod tests {
7177
use super::*;
72-
use crate::parser::spans::SpanManager;
7378

7479
#[test]
7580
fn test_basic_script() {
@@ -93,6 +98,6 @@ mod tests {
9398
c
9499
end;";
95100
let mut parser = Parser::new();
96-
let ast = parser.parse("temp", script).unwrap();
101+
let _ast = parser.parse(script).unwrap();
97102
}
98103
}

0 commit comments

Comments
 (0)