1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
use std::rc::Rc;
use bobascript_parser::{
grammar::{ExprParser, StmtsParser},
Parser, SyntaxError,
};
use thiserror::Error;
use self::compiler::Compiler;
use crate::{
chunk::{Chunk, Upvalue},
value::Function,
};
mod compiler;
mod expressions;
mod statements;
pub type CompileResult<T> = Result<T, CompileError>;
#[derive(Debug, Error, Clone)]
pub enum CompileError {
#[error("Undefined behavior: {0}")]
UndefinedBehavior(String),
#[error("Syntax error: {0}")]
SyntaxError(#[from] SyntaxError),
#[error("Unexpected character '{1}' on line {0}.")]
UnexpectedCharacter(usize, char),
#[error("Unterminated string on line {0}.")]
UnterminatedString(usize),
#[error("Expected {0}.")]
Expected(&'static str),
#[error("Invalid assignment target.")]
InvalidAssignmentTarget,
#[error("A variable with the name \"{0}\" already exists in this scope.")]
VariableAlreadyExists(String),
#[error("A variable with the name \"{0}\" does not exist in scope.")]
VariableDoesNotExist(String),
#[error("Functions and function calls can only have a maximum of 255 arguments. Why do you need that many?")]
TooManyArguments,
#[error("Cannot return from top-level code.")]
TopLevelReturn,
}
pub struct Local {
name: String,
depth: i32,
is_captured: bool,
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum FunctionType {
TopLevel,
Block,
Function,
}
pub struct CompileContext {
function: Function,
fn_type: FunctionType,
locals: Vec<Local>,
upvalues: Vec<Upvalue>,
scope_depth: i32,
}
impl CompileContext {
pub fn new(fn_type: FunctionType) -> Self {
Self {
function: Function::default(),
fn_type,
locals: vec![Local {
name: "".to_string(),
depth: 0,
is_captured: false,
}],
upvalues: Vec::new(),
scope_depth: 0,
}
}
fn chunk_mut(&mut self) -> &mut Chunk {
&mut self.function.chunk
}
fn resolve_local(&self, name: &str) -> CompileResult<Option<usize>> {
for i in (0..self.locals.len()).rev() {
if name == self.locals[i].name {
return if self.locals[i].depth == -1 {
Err(CompileError::VariableDoesNotExist(
self.locals[i].name.clone(),
))
} else {
Ok(Some(i))
};
}
}
Ok(None)
}
}
pub fn compile<S>(source: S) -> CompileResult<Rc<Function>>
where
S: Into<String>,
{
let ast = StmtsParser::parse_ast(&source.into())?;
let mut compiler = Compiler::new();
compiler.compile(&ast)
}
pub fn compile_expr<S>(source: S) -> CompileResult<Rc<Function>>
where
S: Into<String>,
{
let ast = ExprParser::parse_ast(&source.into())?;
let mut compiler = Compiler::new();
compiler.compile_expr(&ast)
}