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