whiley_file/
ast.rs

1use std::fmt;
2use std::convert::From;
3use syntactic_heap::SyntacticHeap;
4use syntactic_heap::Ref;
5pub use crate::nodes::*;
6
7// =============================================================================
8// Abstract Syntax Tree
9// =============================================================================
10
11pub type AbstractSyntaxTree = SyntacticHeap<Node>;
12
13// =============================================================================
14// Terms
15// =============================================================================
16
17#[derive(Clone,Debug,PartialEq)]
18pub enum Node {
19    // Base
20    Utf8(String),
21    // Declarations
22    TypeDecl(TypeDecl),
23    FunctionDecl(FunctionDecl),
24    MethodDecl(MethodDecl),
25    // Statements
26    AssertStmt(AssertStmt),
27    BlockStmt(BlockStmt),
28    SkipStmt(SkipStmt),
29    // Expressions
30    BoolExpr(BoolExpr),
31    EqualsExpr(EqualsExpr),
32    NotEqualsExpr(NotEqualsExpr),
33    LessThanExpr(LessThanExpr),
34    IntExpr(IntExpr),
35    VarExpr(VarExpr),
36    // Types
37    ArrayType(ArrayType),
38    BoolType(BoolType),
39    IntType(IntType),
40    NullType(NullType),
41    RecordType(RecordType),
42    ReferenceType(ReferenceType),
43    VoidType(VoidType)
44}
45
46// =============================================================================
47// Declarations
48// =============================================================================
49
50#[derive(Clone,Copy,Debug,PartialEq)]
51pub struct Decl { pub index: usize }
52
53/// Represents a parameter declaration in the source of a given method.
54#[derive(Clone,Debug,PartialEq)]
55pub struct Parameter {
56    pub declared : Type,
57    pub name : Name
58}
59
60impl Decl {
61    pub fn new(ast: &mut AbstractSyntaxTree, t : Node) -> Self {
62        // Sanity check is declaration
63        assert!(Decl::is(&t));
64        // Create new node
65        let index = ast.push(t).raw_index();
66        // Done
67        Decl{index}
68    }
69
70    /// Determine whether a given term is a declaration or not.
71    pub fn is(t: &Node) -> bool {
72        match t {
73	    Node::FunctionDecl(_) => true,
74	    Node::MethodDecl(_) => true,
75            Node::TypeDecl(_) => true,
76            _ => false
77        }
78    }
79}
80
81impl Into<usize> for Decl {
82    fn into(self) -> usize { self.index }
83}
84
85impl From<FunctionDecl> for Node {
86    fn from(d: FunctionDecl) -> Self { Node::FunctionDecl(d) }
87}
88
89impl From<MethodDecl> for Node {
90    fn from(d: MethodDecl) -> Self { Node::MethodDecl(d) }
91}
92
93impl From<TypeDecl> for Node {
94    fn from(d: TypeDecl) -> Self { Node::TypeDecl(d) }
95}
96
97// =============================================================================
98// Statements
99// =============================================================================
100
101#[derive(Clone,Copy,Debug,PartialEq)]
102pub struct Stmt(pub usize);
103
104impl Stmt {
105    pub fn new(ast: &mut AbstractSyntaxTree, t : Node) -> Self {
106        // Sanity check is declaration
107        assert!(Stmt::is(&t));
108        // Create new node
109        let index = ast.push(t).raw_index();
110        // Done
111        Stmt(index)
112    }
113
114    /// Determine whether a given term is a declaration or not.
115    pub fn is(t: &Node) -> bool {
116        match t {
117	    Node::AssertStmt(_) => true,
118	    Node::BlockStmt(_) => true,
119	    Node::SkipStmt(_) => true,
120            _ => false
121        }
122    }
123}
124
125impl Into<usize> for Stmt {
126    fn into(self) -> usize { self.0 }
127}
128
129impl From<AssertStmt> for Node {
130    fn from(s: AssertStmt) -> Self { Node::AssertStmt(s) }
131}
132
133impl From<BlockStmt> for Node {
134    fn from(s: BlockStmt) -> Self { Node::BlockStmt(s) }
135}
136
137impl From<SkipStmt> for Node {
138    fn from(s: SkipStmt) -> Self { Node::SkipStmt(s) }
139}
140
141// =============================================================================
142// Expressions
143// =============================================================================
144
145#[derive(Clone,Copy,Debug,PartialEq)]
146pub struct Expr(pub usize);
147
148impl Expr {
149    pub fn new(ast: &mut AbstractSyntaxTree, t : Node) -> Self {
150        // Sanity check is declaration
151        assert!(Expr::is(&t));
152        // Create new node
153        let index = ast.push(t).raw_index();
154        // Done
155        Expr(index)
156    }
157
158    /// Determine whether a given term is a declaration or not.
159    pub fn is(t: &Node) -> bool {
160        match t {
161	    Node::BoolExpr(_) => true,
162	    Node::EqualsExpr(_) => true,
163	    Node::LessThanExpr(_) => true,
164	    Node::NotEqualsExpr(_) => true,
165	    Node::IntExpr(_) => true,
166	    Node::VarExpr(_) => true,
167            _ => false
168        }
169    }
170}
171
172impl Into<usize> for Expr {
173    fn into(self) -> usize { self.0 }
174}
175
176impl From<BoolExpr> for Node {
177    fn from(s: BoolExpr) -> Self { Node::BoolExpr(s) }
178}
179
180impl From<EqualsExpr> for Node {
181    fn from(s: EqualsExpr) -> Self { Node::EqualsExpr(s) }
182}
183
184impl From<NotEqualsExpr> for Node {
185    fn from(s: NotEqualsExpr) -> Self { Node::NotEqualsExpr(s) }
186}
187
188impl From<LessThanExpr> for Node {
189    fn from(s: LessThanExpr) -> Self { Node::LessThanExpr(s) }
190}
191
192impl From<IntExpr> for Node {
193    fn from(s: IntExpr) -> Self { Node::IntExpr(s) }
194}
195
196impl From<VarExpr> for Node {
197    fn from(s: VarExpr) -> Self { Node::VarExpr(s) }
198}
199
200// =============================================================================
201// Types
202// =============================================================================
203
204#[derive(Clone,Copy,Debug,PartialEq)]
205pub struct Type(pub usize);
206
207impl Type {
208    pub fn new(ast: &mut AbstractSyntaxTree, t : Node) -> Self {
209        // Sanity check is declaration
210        assert!(Type::is(ast,&t));
211        // Create new node
212        let index = ast.push(t).raw_index();
213        // Done
214        Type(index)
215    }
216
217    /// Determine whether a given term is a type (or not).
218    pub fn is(ast: &AbstractSyntaxTree, t: &Node) -> bool {
219        match t {
220            Node::BoolType(_) => true,
221            Node::IntType(_) => true,
222            Node::NullType(_) => true,
223            Node::VoidType(_) => true,
224            Node::ArrayType(_) => true,
225            Node::ReferenceType(_) => true,
226            Node::RecordType(_) => true,
227            _ => false
228        }
229    }
230}
231
232impl Into<usize> for Type {
233    fn into(self) -> usize { self.0 }
234}
235
236impl From<ArrayType> for Node {
237    fn from(s: ArrayType) -> Self { Node::ArrayType(s) }
238}
239
240impl From<BoolType> for Node {
241    fn from(s: BoolType) -> Self { Node::BoolType(s) }
242}
243
244impl From<IntType> for Node {
245    fn from(s: IntType) -> Self { Node::IntType(s) }
246}
247
248impl From<NullType> for Node {
249    fn from(s: NullType) -> Self { Node::NullType(s) }
250}
251
252impl From<RecordType> for Node {
253    fn from(s: RecordType) -> Self { Node::RecordType(s) }
254}
255
256impl From<ReferenceType> for Node {
257    fn from(s: ReferenceType) -> Self { Node::ReferenceType(s) }
258}
259
260impl From<VoidType> for Node {
261    fn from(s: VoidType) -> Self { Node::VoidType(s) }
262}
263
264// =============================================================================
265// Names
266// =============================================================================
267
268#[derive(Clone,Copy,Debug,Hash,PartialEq,Eq)]
269pub struct Name(pub usize);
270
271impl Name {
272    pub fn new(ast: &mut AbstractSyntaxTree, s : &str) -> Self {
273	let node = Node::Utf8(s.to_string());
274        // Create new node
275        let index = ast.push(node).raw_index();
276        // Done
277        Name(index)
278    }
279}
280
281// =============================================================================
282// Conversions
283// =============================================================================
284
285impl From<Ref<'_,Node>> for Decl {
286    fn from(r: Ref<'_,Node>) -> Decl {
287	Decl{index:r.raw_index()}
288    }
289}
290
291impl From<Ref<'_,Node>> for Stmt {
292    fn from(r: Ref<'_,Node>) -> Stmt {
293	Stmt(r.raw_index())
294    }
295}
296
297impl From<Ref<'_,Node>> for Type {
298    fn from(r: Ref<'_,Node>) -> Type {
299	Type(r.raw_index())
300    }
301}
302
303impl From<Ref<'_,Node>> for Name {
304    fn from(r: Ref<'_,Node>) -> Name {
305	Name(r.raw_index())
306    }
307}
308
309// =============================================================================
310// Debug
311// =============================================================================
312
313impl fmt::Display for Node {
314    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
315        match self {
316            Node::TypeDecl(d) => {
317                write!(f,"TypeDecl({:?})",d)
318            }
319            Node::ArrayType(t) => {
320                write!(f,"ArrayType({:?})",t.0)
321            }
322            // Default for those without children
323            _ => write!(f,"{:?}",self)
324        }
325    }
326}
327
328fn to_string<T:fmt::Display>(items : &[T]) -> String {
329    let mut s = String::new();
330    let mut f = true;
331    s.push('[');
332    for item in items {
333	if !f { s.push(','); }
334	f = false;
335	s.push_str(&item.to_string());
336    }
337    s.push(']');
338    return s;
339}