kb/
ast.rs

1use super::ArgSpec;
2use super::Binop;
3use super::RcStr;
4use super::Unop;
5use super::VarScope;
6use std::fmt;
7use std::fmt::Write;
8use std::rc::Rc;
9
10pub struct Source {
11    pub name: RcStr,
12    pub data: RcStr,
13}
14
15impl fmt::Debug for Source {
16    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
17        write!(f, "Source({})", self.name)
18    }
19}
20
21#[derive(Debug, Clone)]
22pub struct Mark {
23    pub source: Rc<Source>,
24    pub pos: usize,
25}
26
27impl Mark {
28    pub fn format(&self) -> String {
29        let mut ret = String::new();
30        let out = &mut ret;
31        writeln!(out, "in {:?} on line {}", self.source.name, self.lineno()).unwrap();
32        let start = self.source.data[..self.pos]
33            .rfind('\n')
34            .map(|x| x + 1)
35            .unwrap_or(0);
36        let end = self.source.data[self.pos..]
37            .find('\n')
38            .map(|x| x + self.pos)
39            .unwrap_or(self.source.data.len());
40        writeln!(out, "{}", &self.source.data[start..end]).unwrap();
41        for _ in start..self.pos {
42            write!(out, " ").unwrap();
43        }
44        writeln!(out, "*").unwrap();
45        ret
46    }
47    pub fn lineno(&self) -> usize {
48        self.source.data[..self.pos].matches('\n').count() + 1
49    }
50}
51
52pub struct File {
53    pub source: Rc<Source>,
54    pub imports: Vec<Import>,
55    pub funcs: Vec<FuncDisplay>,
56    pub body: Stmt,
57
58    // annotated data
59    pub vars: Vec<Var>,
60}
61
62impl File {
63    pub fn name(&self) -> &RcStr {
64        &self.source.name
65    }
66}
67
68#[derive(Debug, Clone)]
69pub struct Var {
70    pub mark: Mark,
71    pub name: RcStr, // unique in the scope it is declared
72    pub vscope: VarScope,
73    pub index: u32,
74}
75
76#[derive(Debug, Clone)]
77pub struct Import {
78    pub mark: Mark,
79    pub module_name: RcStr,
80    pub alias: RcStr,
81
82    // annotated data
83    pub unique_name: RcStr,
84}
85
86pub struct FuncDisplay {
87    pub mark: Mark,
88    pub generator: bool,
89    pub test: bool,
90    pub short_name: RcStr,
91    pub argspec: ArgSpec,
92    pub body: Stmt,
93
94    // annotated data
95    pub vars: Vec<Var>,
96    pub as_var: Option<Var>,
97}
98
99impl FuncDisplay {
100    pub fn full_name(&self) -> &RcStr {
101        &self.as_var.as_ref().unwrap().name
102    }
103}
104
105pub struct Stmt {
106    pub mark: Mark,
107    pub desc: StmtDesc,
108}
109
110pub enum StmtDesc {
111    Block(Vec<Stmt>),
112    Return(Option<Expr>),
113    Assign(AssignTarget, Vec<AssignTarget>, Expr),
114    Expr(Expr),
115    Print(Expr),
116    Assert(Expr),
117
118    // Control flow
119    Label(RcStr),
120    Goto(RcStr),
121    If(Vec<(Expr, Stmt)>, Option<Box<Stmt>>),
122    While(Expr, Box<Stmt>),
123    ForIn(AssignTarget, Expr, Box<Stmt>),
124    ForClassic(AssignTarget, Expr, Expr, bool, f64, Box<Stmt>),
125}
126
127pub struct AssignTarget {
128    pub mark: Mark,
129    pub desc: AssignTargetDesc,
130}
131
132pub enum AssignTargetDesc {
133    Name(RcStr),
134    List(Vec<AssignTarget>),
135}
136
137#[derive(Debug)]
138pub struct Expr {
139    pub mark: Mark,
140    pub desc: ExprDesc,
141}
142
143#[derive(Debug)]
144pub enum ExprDesc {
145    Nil,
146    Bool(bool),
147    Number(f64),
148    String(RcStr),
149    List(Vec<Expr>),
150
151    GetVar(RcStr),
152    GetAttr(Box<Expr>, RcStr),
153
154    CallFunc(Box<Expr>, Vec<Expr>),
155
156    Binop(Binop, Box<Expr>, Box<Expr>),
157    Unop(Unop, Box<Expr>),
158
159    Yield(Box<Expr>),
160    Next(Box<Expr>), // gets [next-or-nil, has_next] from a generator
161
162    // Gets the disassembly of a function as a string
163    Disasm(Box<Expr>),
164}