This is an old revision of the document!
The purpose of the homework is to write the semantic analysis, the intermediate language for the Alfy language.
You will receive an AST from the parser that parses correctly a Alfy language source and have to write:
The program will receive two parameters from the command line:
node main.js source.alfy source.alfy.json
The format of the output file is the following
{ symbol_table: [...], // the symbol_table ast: {...}, // the ast with the type for very node that returns a value error_list [] // the error list }
The symbol table is an array of context objects.
[ // context object id 0 - the context of the main script { ... }, // context object id 1 - the context object of a function { ... }, ... ]
While determining the symbol table, add to each AST node a parameter symbol with the value of the its context id.
The context object stores
The object looks like
{ "variables": { // a dictionary of variables "variable": { "type": // type of the variable "line": // the line where the variable was declared "value": // the expression that the variable initially has (optional, if the define was with an assignment) } }, "functions": { // a dictionary of functions "function": { "type": // the return type of the function "parameters": [] // the list of parameters the function takes (the parameters node from the AST) "line": // the line where the function was declared "symbol": // the context object id that the function creates } }, "types": { // a dictionary of types "type": { "type": // the type of the new type struct or array "line": // the line where the type was declared // for array "elements_type": // the type of each array element "from": // the first index "to": // the last index // for struct "elements": [ // a list of array elements (the node form the AST) { "type": "id": "line": }, ... ] } }, "parent": 0, // the parent context position in the symbol_table (except of the main script that has no parent), usually 0, "type": // the type of the "fn": // the function name if this is a function context "return_value": // the return type of the function if this is a function context }
{ "variables": { "s": { "type": "school", "line": 8 } }, "functions": {}, "types": { "school": { "type": "struct", "line": 6, "elements": [ { "type": "int", "id": "type", "line": 5 }, { "type": "logic", "id": "private", "line": 4 }, { "type": "string", "id": "name", "line": 3 } ] } } }
For each of the following nodes, determine the return type
Set type the by adding a parameter t in the node.
{ "type": "expression", "op": "=", "left": { "type": "expression", "op": "mod", "left": { "type": "id", "value": "n", "line": 8, "symbol": 1, "t": "int" }, "right": { "type": "id", "value": "i", "line": 8, "symbol": 1, "t": "int" }, "line": 8, "symbol": 1, "t": "int" }, "right": { "type": "value", "t": "int", "value": 0, "line": 8, "symbol": 1 }, "line": 8, "symbol": 1, "t": "logic" }
For all the AST nodes, verify that the types match:
The error list is an array that contains error objects. The order in which these errors are in the list is up to you.
Each error has the following format:
{ type: // string with the error type line: // the line number in the source (starting at 1) elements: // items for the error, each type of error has different items text: // the error text message }
The error type is a string with one of the following titles
The error occurs when a variable definition is repeated.
{ variable: // variable name }
The error occurs when a function definition is repeated.
{ function: // function name }
The error occurs when a type definition is repeated (array or struct).
{ type: // type name }
The error occurs when a struct element definition is repeated.
{
struct: // struct type name element: // element name
}
The error occurs when the array lower index is higher than the higher index
{ array: // array type name low_index: // the lower index value high_index: // the higher index value }
The error occurs when the type of a variable is not determinable (bonus only).
// variable { variable: // the name of the variable with the unresolved type } // struct element { struct: // name of struct type element: // name of struct element with the unresolved type }
The error occurs when a function call is made to a function that is not defned.
{ id: // function name }
The error occurs when a variable that is not defined is used.
{ variable: // variable name }
The error occurs when a type that is not defined is used.
{
variable: // the variable that has that type type: // the type that is undefined
}
The error occurs when an element is not part of that struct.
{ struct: // struct name element: // element name }
The error occurs when an element is requested for a variable that is not a struct type
{ type: // actual type that the variable is (instead of a struct type) }
The error occurs when an index is requested for a variable that is not an array
{ type: // actual type that the variable is (instead of an array type) }
The error occurs when an index for an array is not a number or symbol
{ array: // array type index: // supplied index type }
The error occurs when a value statement (value_of_function node) is used outside a function
{ // empty }
The error occurs when an expression has incompatible types
// left op right { left: right: op: } // op value { value: op: } // if, while or repeat - aslongas { expression: // expression type op: // if, while, repeat } // for { expression: // expression type op: "for" element: // variable, from, to or step } // value_of_function { op: "value" to: // return type from: // provided type } // is { op: "is" to: // to type from: // from type } // struct element type is undefined { struct: // struct type, element: // name of struct element } // variable type is undefined { variable: // name of the variable }
This is a lexical error
This is a syntax error