1 /* JitterLisp: AST header.
2 
3    Copyright (C) 2017, 2018 Luca Saiu
4    Written by Luca Saiu
5 
6    This file is part of the JitterLisp language implementation, distributed as
7    an example along with Jitter under the same license.
8 
9    Jitter is free software: you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation, either version 3 of the License, or
12    (at your option) any later version.
13 
14    Jitter is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with Jitter.  If not, see <http://www.gnu.org/licenses/>. */
21 
22 
23 #ifndef JITTERLISP_AST_H_
24 #define JITTERLISP_AST_H_
25 
26 
27 
28 #include "jitterlisp.h"
29 #include "jitterlisp-sexpression.h"
30 
31 
32 
33 
34 /* AST data structure.
35  * ************************************************************************** */
36 
37 /* The AST case as an expression case identifier. */
38 enum jitterlisp_ast_case
39   {
40     /* Literal constant.  Exactly one sub, any s-expression. */
41     jitterlisp_ast_case_literal,
42 
43     /* Variable.  Exactly one sub, a symbol. */
44     jitterlisp_ast_case_variable,
45 
46     /* Global definition.  Exactly two subs, a symbol and an AST. */
47     jitterlisp_ast_case_define,
48 
49     /* Two-way conditional.  Exactly three subs, ASTs. */
50     jitterlisp_ast_case_if,
51 
52     /* Variable assignment.  Exactly two subs, a symbol and an AST. */
53     jitterlisp_ast_case_setb,
54 
55     /* While loop.  Exactly two subs, a guard AST and a body AST. */
56     jitterlisp_ast_case_while,
57 
58     /* Primitive call.  At least one sub, the primitive object, then one AST per
59        actual. */
60     jitterlisp_ast_case_primitive,
61 
62     /* Procedure call.  At least one sub, the operator as an AST, then one AST
63        per actual operand. */
64     jitterlisp_ast_case_call,
65 
66     /* Procedure abstraction.  Exactly two subs, one list of symbols for the
67        formals and one AST for the body.  This AST shape having a list as a sub
68        is different from the other cases, but allows the list of formals to be
69        reused as a shared read-only datum, making closure initialization
70        faster. */
71     jitterlisp_ast_case_lambda,
72 
73     /* One-binding let.  Exactly three subs: one symbol for the variable, one
74        AST for the bound expression, one AST for the body. */
75     jitterlisp_ast_case_let,
76 
77     /* Sequence.  Exactly two AST subs. */
78     jitterlisp_ast_case_sequence
79   };
80 
81 /* An AST data structure.  The structure definition itself seems lax, but
82    operations on ASTs are designed to only build syntactically valid ASTs, and
83    fail otherwise.  This eliminates the need for safety checks at interpretation
84    or VM code generation time.  Sub-structures are all tagged. */
85 struct jitterlisp_ast
86 {
87   /* What case this AST represents. */
88   enum jitterlisp_ast_case case_;
89 
90   /* How many sub-components this AST has.  This is kept correct even for cases
91      with a fixed number of subs. */
92   jitter_uint sub_no;
93 
94   /* A flexible array member holding this AST's sub-components, which are
95      exactly sub_no.  Some sub-components may be other ASTs and others may be
96      different Lisp object, according to the case.  All are tagged, and checked
97      for compatibility with the case at construction time. */
98   jitterlisp_object subs [];
99 };
100 
101 
102 
103 
104 /* AST high-level allocation.
105  * ************************************************************************** */
106 
107 /* Return a fresh encoded AST of the appropriate case, completely initialized
108    with the given subs.  When multiple ASTs or multiple symbols are required
109    (such as in the case of primitive or lambda) the arguments are s-expression
110    lists with ASTs or symbols as elements; in such case the formal arguments
111    have a plural name ending in _asts or _symbols .
112 
113    The functions in this section all check their argument types, and error out
114    cleanly in case of mismatch. */
115 jitterlisp_object
116 jitterlisp_ast_make_literal (jitterlisp_object value);
117 jitterlisp_object
118 jitterlisp_ast_make_variable (jitterlisp_object symbol);
119 jitterlisp_object
120 jitterlisp_ast_make_define (jitterlisp_object symbol, jitterlisp_object ast);
121 jitterlisp_object
122 jitterlisp_ast_make_if (jitterlisp_object condition_ast,
123                         jitterlisp_object then_ast,
124                         jitterlisp_object else_ast);
125 jitterlisp_object
126 jitterlisp_ast_make_setb (jitterlisp_object symbol, jitterlisp_object ast);
127 jitterlisp_object
128 jitterlisp_ast_make_while (jitterlisp_object condition_ast,
129                            jitterlisp_object body_ast);
130 jitterlisp_object
131 jitterlisp_ast_make_primitive (jitterlisp_object primitive_object,
132                                jitterlisp_object actual_asts);
133 jitterlisp_object
134 jitterlisp_ast_make_call (jitterlisp_object operator_ast,
135                           jitterlisp_object actual_asts);
136 jitterlisp_object
137 jitterlisp_ast_make_lambda (jitterlisp_object formal_symbols,
138                             jitterlisp_object body_ast);
139 jitterlisp_object
140 jitterlisp_ast_make_let (jitterlisp_object bound_symbol,
141                          jitterlisp_object bound_ast,
142                          jitterlisp_object body_ast);
143 jitterlisp_object
144 jitterlisp_ast_make_sequence (jitterlisp_object ast_0,
145                               jitterlisp_object ast_1);
146 
147 
148 
149 
150 /* AST accessors.
151  * ************************************************************************** */
152 
153 /* Return a freshly allocated list containing the operands of the given AST,
154    whose case must be either primitive or call. */
155 jitterlisp_object
156 jitterlisp_ast_operands (jitterlisp_object ast);
157 
158 #endif // #ifndef JITTERLISP_AST_H_
159