├── unicode.h ├── CMakeLists.txt ├── lexer.h ├── README ├── error.h ├── main.c ├── tokenizer.h ├── error.c ├── lexer.c ├── tokenizer.c ├── interpreter.h ├── parser.h └── interpreter.c /unicode.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Data and functions for converting from Unicode normative names to Unicode 3 | * code points. 4 | * 5 | * \file unicode.h 6 | * 7 | * \author Justin J. Meza 8 | * 9 | * \date 2010-2012 10 | */ 11 | 12 | #ifndef __UNICODE_H__ 13 | #define __UNICODE_H__ 14 | 15 | #include 16 | #include 17 | 18 | int binarySearch(const char **, int, int, const char *); 19 | long convertNormativeNameToCodePoint(const char *); 20 | size_t convertCodePointToUTF8(unsigned long, char *); 21 | 22 | #endif /* __UNICODE_H_ */ 23 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | project(doge) 3 | 4 | ENABLE_TESTING() 5 | SET(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake ) 6 | 7 | SET(HDRS 8 | interpreter.h 9 | lexer.h 10 | parser.h 11 | tokenizer.h 12 | unicode.h 13 | error.h 14 | ) 15 | 16 | SET(SRCS 17 | interpreter.c 18 | lexer.c 19 | main.c 20 | parser.c 21 | tokenizer.c 22 | unicode.c 23 | error.c 24 | ) 25 | 26 | add_executable(doge ${SRCS} ${HDRS}) 27 | target_link_libraries(doge m) 28 | install( 29 | TARGETS doge 30 | RUNTIME DESTINATION bin 31 | ) 32 | -------------------------------------------------------------------------------- /lexer.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Structures and functions for separating a character buffer into lexemes -- 3 | * groups of characters. The lexer reads through a buffer of characters 4 | * (themselves typically read from standard input), strips whitespace, and 5 | * breaks them up into logical atoms of character strings which, in turn, may be 6 | * passed on to later processes (such as a tokenizer). 7 | * 8 | * \file lexer.h 9 | * 10 | * \author Justin J. Meza 11 | * 12 | * \date 2010-2012 13 | */ 14 | 15 | #ifndef __LEXER_H__ 16 | #define __LEXER_H__ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include "error.h" 24 | 25 | #undef DEBUG 26 | 27 | /** 28 | * Stores a lexeme. A lexeme is a group of contiguous characters, stripped of 29 | * surrounding whitespace or other lexemes. 30 | */ 31 | typedef struct { 32 | char *image; /**< The string that identifies the lexeme. */ 33 | const char *fname; /**< The name of the file containing the lexeme. */ 34 | unsigned int line; /**< The line number the lexeme occurred on. */ 35 | } Lexeme; 36 | 37 | /** 38 | * Stores a list of lexemes. 39 | */ 40 | typedef struct { 41 | unsigned int num; /**< The number of lexemes stored. */ 42 | Lexeme **lexemes; /**< The array of stored lexemes. */ 43 | } LexemeList; 44 | 45 | /** 46 | * \name Lexeme modifiers 47 | * 48 | * Functions for performing helper tasks. 49 | */ 50 | /**@{*/ 51 | Lexeme *createLexeme(char *, const char *, unsigned int); 52 | void deleteLexeme(Lexeme *); 53 | LexemeList *createLexemeList(void); 54 | Lexeme *addLexeme(LexemeList *, Lexeme*); 55 | void deleteLexemeList(LexemeList *); 56 | /**@}*/ 57 | 58 | /** 59 | * \name Buffer lexer 60 | * 61 | * Generates lexemes from a character buffer. 62 | */ 63 | /**@{*/ 64 | LexemeList *scanBuffer(const char *, unsigned int, const char *); 65 | /**@}*/ 66 | 67 | #endif /* __LEXER_H__ */ 68 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | doge - an interpreter for the shibe esoteric programming language 2 | 3 | ░░░░░░░░░▄░░░░░░░░░░░░░░▄░░░░ 4 | ░░░░░░░░▌▒█░░░░░░░░░░░▄▀▒▌░░░ 5 | ░░░░░░░░▌▒▒█░░░░░░░░▄▀▒▒▒▐░░░ 6 | ░░░░░░░▐▄▀▒▒▀▀▀▀▄▄▄▀▒▒▒▒▒▐░░░ 7 | ░░░░░▄▄▀▒░▒▒▒▒▒▒▒▒▒█▒▒▄█▒▐░░░ 8 | ░░░▄▀▒▒▒░░░▒▒▒░░░▒▒▒▀██▀▒▌░░░ 9 | ░░▐▒▒▒▄▄▒▒▒▒░░░▒▒▒▒▒▒▒▀▄▒▒▌░░ 10 | ░░▌░░▌█▀▒▒▒▒▒▄▀█▄▒▒▒▒▒▒▒█▒▐░░ 11 | ░▐░░░▒▒▒▒▒▒▒▒▌██▀▒▒░░░▒▒▒▀▄▌░ 12 | ░▌░▒▄██▄▒▒▒▒▒▒▒▒▒░░░░░░▒▒▒▒▌░ 13 | ▀▒▀▐▄█▄█▌▄░▀▒▒░░░░░░░░░░▒▒▒▐░ 14 | ▐▒▒▐▀▐▀▒░▄▄▒▄▒▒▒▒▒▒░▒░▒░▒▒▒▒▌ 15 | ▐▒▒▒▀▀▄▄▒▒▒▄▒▒▒▒▒▒▒▒░▒░▒░▒▒▐░ 16 | ░▌▒▒▒▒▒▒▀▀▀▒▒▒▒▒▒░▒░▒░▒░▒▒▒▌░ 17 | ░▐▒▒▒▒▒▒▒▒▒▒▒▒▒▒░▒░▒░▒▒▄▒▒▐░░ 18 | ░░▀▄▒▒▒▒▒▒▒▒▒▒▒░▒░▒░▒▄▒▒▒▒▌░░ 19 | ░░░░▀▄▒▒▒▒▒▒▒▒▒▒▄▄▄▀▒▒▒▒▄▀░░░ 20 | ░░░░░░▀▄▄▄▄▄▄▀▀▀▒▒▒▒▒▄▄▀░░░░░ 21 | ░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▀▀░░░░░░░░ 22 | 23 | https://github.com/justinmeza/doge 24 | 25 | SHIBE LICENSE VERSION 1.0 26 | 27 | wow 28 | such copyright 2013 justin meza 29 | 30 | so free software 31 | 32 | many distribute 33 | much modify 34 | 35 | no warranty 36 | 37 | BUILD 38 | 39 | $ mkdir build 40 | $ cd build 41 | $ cmake .. 42 | $ make 43 | $ ./doge ../example.shibe 44 | 45 | EXAMPLE 46 | 47 | so main 48 | 49 | omg comment 50 | 51 | so variabl 52 | 53 | variabl can be "doge" 54 | 55 | such variabl omg prints "doge" 56 | 57 | so temp 58 | temp can be 5 59 | 60 | so many loop 61 | 62 | omg blokcs end at closing wow 63 | 64 | such temp 65 | 66 | temp can be so minus temp and 1 67 | 68 | much saem temp and 0 69 | 70 | so if 71 | many yes 72 | so break 73 | 74 | wow 75 | 76 | such variabl 77 | 78 | such "Turing" 79 | 80 | wow 81 | 82 | wow 83 | -------------------------------------------------------------------------------- /error.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Error type definitions. 3 | * 4 | * \file error.h 5 | * 6 | * \author Justin J. Meza 7 | * 8 | * \date 2012 9 | */ 10 | 11 | #ifndef __ERROR_H__ 12 | #define __ERROR_H__ 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | /** 19 | * Represents an error type. The error types are organized based on which 20 | * module they occur in: 21 | * 22 | * - MN_* for the main body, 23 | * - LX_* for the lexer, 24 | * - TK_* for the tokenizer, 25 | * - PR_* for the parser, 26 | * - IN_* for the interpreter 27 | * 28 | * \note Remember to update the error message and error code arrays (in the 29 | * error C file) with the appropriate error message and code. 30 | */ 31 | typedef enum { 32 | MN_ERROR_OPENING_FILE, 33 | MN_ERROR_CLOSING_FILE, 34 | 35 | LX_LINE_CONTINUATION, 36 | LX_MULTIPLE_LINE_COMMENT, 37 | LX_EXPECTED_TOKEN_DELIMITER, 38 | 39 | TK_EXPECTED_FLOATING_POINT, 40 | TK_EXPECTED_INTEGER, 41 | TK_UNKNOWN_TOKEN, 42 | 43 | PR_UNKNOWN_IDENTIFIER_TYPE, 44 | PR_UNKNOWN_STATEMENT_TYPE, 45 | PR_UNKNOWN_EXPRESSION_TYPE, 46 | PR_EXPECTED_BOOLEAN, 47 | PR_EXPECTED_INTEGER, 48 | PR_EXPECTED_FLOAT, 49 | PR_EXPECTED_STRING, 50 | PR_EXPECTED_CONSTANT, 51 | PR_EXPECTED_TYPE, 52 | PR_EXPECTED_IDENTIFIER, 53 | PR_EXPECTED_TOKEN, 54 | PR_INVALID_OPERATOR, 55 | PR_EXPECTED_EXPRESSION, 56 | PR_EXPECTED_END_OF_EXPRESSION, 57 | PR_EXPECTED_END_OF_STATEMENT, 58 | PR_CANNOT_USE_STR_AS_LITERAL, 59 | PR_LITERAL_MUST_BE_UNIQUE, 60 | PR_EXPECTED_LOOP_NAME, 61 | PR_EXPECTED_EITHER_TOKEN, 62 | PR_EXPECTED_UNARY_FUNCTION, 63 | PR_EXPECTED_MATCHING_LOOP_NAME, 64 | PR_EXPECTED_STATEMENT, 65 | 66 | IN_INVALID_IDENTIFIER_TYPE, 67 | IN_UNABLE_TO_STORE_VARIABLE, 68 | IN_VARIABLE_DOES_NOT_EXIST, 69 | IN_CANNOT_IMPLICITLY_CAST_NIL, 70 | IN_CANNOT_CAST_FUNCTION_TO_BOOLEAN, 71 | IN_CANNOT_CAST_ARRAY_TO_BOOLEAN, 72 | IN_UNKNOWN_VALUE_DURING_BOOLEAN_CAST, 73 | IN_UNABLE_TO_CAST_VALUE, 74 | IN_EXPECTED_INTEGER_VALUE, 75 | IN_CANNOT_CAST_FUNCTION_TO_INTEGER, 76 | IN_CANNOT_CAST_ARRAY_TO_INTEGER, 77 | IN_UNKNOWN_VALUE_DURING_INTEGER_CAST, 78 | IN_EXPECTED_DECIMAL, 79 | IN_CANNOT_CAST_FUNCTION_TO_DECIMAL, 80 | IN_CANNOT_CAST_ARRAY_TO_DECIMAL, 81 | IN_UNKNOWN_VALUE_DURING_DECIMAL_CAST, 82 | IN_CANNOT_CAST_BOOLEAN_TO_STRING, 83 | IN_EXPECTED_CLOSING_PAREN, 84 | IN_INVALID_HEX_NUMBER, 85 | IN_CODE_POINT_MUST_BE_POSITIVE, 86 | IN_EXPECTED_CLOSING_SQUARE_BRACKET, 87 | IN_EXPECTED_CLOSING_CURLY_BRACE, 88 | IN_VARIABLE_NOT_AN_ARRAY, 89 | IN_CANNOT_CAST_FUNCTION_TO_STRING, 90 | IN_CANNOT_CAST_ARRAY_TO_STRING, 91 | IN_UNKNOWN_VALUE_DURING_STRING_CAST, 92 | IN_UNKNOWN_CAST_TYPE, 93 | IN_UNDEFINED_FUNCTION, 94 | IN_INCORRECT_NUMBER_OF_ARGUMENTS, 95 | IN_INVALID_RETURN_TYPE, 96 | IN_UNKNOWN_CONSTANT_TYPE, 97 | IN_DIVISION_BY_ZERO, 98 | IN_INVALID_OPERAND_TYPE, 99 | IN_INVALID_BOOLEAN_OPERATION_TYPE, 100 | IN_INVALID_EQUALITY_OPERATION_TYPE, 101 | IN_REDEFINITION_OF_VARIABLE, 102 | IN_INVALID_DECLARATION_TYPE, 103 | IN_INVALID_TYPE, 104 | IN_FUNCTION_NAME_USED_BY_VARIABLE, 105 | } ErrorType; 106 | 107 | void error(ErrorType, ...); 108 | 109 | #endif /* __ERROR_H__ */ 110 | -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "lexer.h" 6 | #include "tokenizer.h" 7 | #include "parser.h" 8 | #include "interpreter.h" 9 | #include "error.h" 10 | 11 | #define READSIZE 512 12 | 13 | static char *program_name; 14 | 15 | static char *shortopt = "hv"; 16 | static struct option longopt[] = { 17 | { "help", no_argument, NULL, (int)'h' }, 18 | { "version", no_argument, NULL, (int)'v' }, 19 | { 0, 0, 0, 0 } 20 | }; 21 | 22 | static void help(void) { 23 | fprintf(stderr, "\ 24 | Usage: %s [FILE] ... \n\ 25 | Interpret FILE(s) as shibe. Let FILE be '-' for stdin.\n\ 26 | -h, --help\t\toutput this help\n\ 27 | -v, --version\t\tprogram version\n", program_name); 28 | } 29 | 30 | static void version (char *revision) { 31 | fprintf(stderr, "%s %s\n", program_name, revision); 32 | } 33 | 34 | int main(int argc, char **argv) 35 | { 36 | unsigned int size = 0; 37 | unsigned int length = 0; 38 | char *buffer = NULL; 39 | LexemeList *lexemes = NULL; 40 | Token **tokens = NULL; 41 | MainNode *node = NULL; 42 | char *fname = NULL; 43 | FILE *file = NULL; 44 | int ch; 45 | 46 | char *revision = "v0.0.1"; 47 | program_name = argv[0]; 48 | 49 | while ((ch = getopt_long(argc, argv, shortopt, longopt, NULL)) != -1) { 50 | switch (ch) { 51 | default: 52 | help(); 53 | exit(EXIT_FAILURE); 54 | case 'h': 55 | help(); 56 | exit(EXIT_SUCCESS); 57 | case 'v': 58 | version(revision); 59 | exit(EXIT_SUCCESS); 60 | } 61 | } 62 | 63 | for (; optind < argc; optind++) { 64 | size = length = 0; 65 | buffer = fname = NULL; 66 | lexemes = NULL; 67 | tokens = NULL; 68 | node = NULL; 69 | file = NULL; 70 | 71 | if (!strncmp(argv[optind],"-\0",2)) { 72 | file = stdin; 73 | fname = "stdin"; 74 | } 75 | else { 76 | file = fopen(argv[optind], "r"); 77 | fname = argv[optind]; 78 | } 79 | 80 | if (!file) { 81 | error(MN_ERROR_OPENING_FILE, argv[optind]); 82 | return 1; 83 | } 84 | 85 | while (!feof(file)) { 86 | size += READSIZE; 87 | buffer = realloc(buffer, sizeof(char) * size); 88 | length += fread((buffer + size) - READSIZE, 89 | 1, 90 | READSIZE, 91 | file); 92 | } 93 | 94 | if (fclose(file) != 0) { 95 | error(MN_ERROR_CLOSING_FILE, argv[optind]); 96 | if (buffer) free(buffer); 97 | return 1; 98 | } 99 | if (!buffer) return 1; 100 | buffer[length] = '\0'; 101 | 102 | /* Remove hash bang line if run as a standalone script */ 103 | if (buffer[0] == '#' && buffer[1] == '!') { 104 | unsigned int n; 105 | for (n = 0; buffer[n] != '\n' && buffer[n] != '\r'; n++) 106 | buffer[n] = ' '; 107 | } 108 | 109 | /* 110 | * Remove UTF-8 BOM if present and add it to the output stream 111 | * (we assume here that if a BOM is present, the system will 112 | * also expect the output to include a BOM). 113 | */ 114 | if (buffer[0] == (char)0xef 115 | || buffer[1] == (char)0xbb 116 | || buffer[2] == (char)0xbf) { 117 | buffer[0] = ' '; 118 | buffer[1] = ' '; 119 | buffer[2] = ' '; 120 | printf("%c%c%c", 0xef, 0xbb, 0xbf); 121 | } 122 | 123 | /* Begin main pipeline */ 124 | if (!(lexemes = scanBuffer(buffer, length, fname))) { 125 | free(buffer); 126 | return 1; 127 | } 128 | free(buffer); 129 | if (!(tokens = tokenizeLexemes(lexemes))) { 130 | deleteLexemeList(lexemes); 131 | return 1; 132 | } 133 | deleteLexemeList(lexemes); 134 | if (!(node = parseMainNode(tokens))) { 135 | deleteTokens(tokens); 136 | return 1; 137 | } 138 | deleteTokens(tokens); 139 | if (interpretMainNode(node)) { 140 | deleteMainNode(node); 141 | return 1; 142 | } 143 | deleteMainNode(node); 144 | /* End main pipeline */ 145 | 146 | } 147 | 148 | return 0; 149 | } 150 | -------------------------------------------------------------------------------- /tokenizer.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Structures and functions for grouping lexemes into tokens. The tokenizer 3 | * reads through an array of lexemes (generated by the lexer) and groups them 4 | * into tokens based on their structure. In addition, some lexemes with 5 | * semantic meaning (such as integers, floats, strings, and booleans) will have 6 | * their values extracted and stored. 7 | * 8 | * \file tokenizer.h 9 | * 10 | * \author Justin J. Meza 11 | * 12 | * \date 2010-2012 13 | */ 14 | 15 | #ifndef __TOKENIZER_H__ 16 | #define __TOKENIZER_H__ 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | #include "lexer.h" 23 | #include "error.h" 24 | 25 | #undef DEBUG 26 | 27 | /** 28 | * Represents a token type. All of the token type names correspond to either 29 | * the semantic type of token data or the lexemes which make up the particular 30 | * token. 31 | * 32 | * \note Remember to update the keywords array (below) with the token image. 33 | */ 34 | typedef enum { 35 | TT_INTEGER, /**< Integer literal. */ 36 | TT_FLOAT, /**< Decimal literal. */ 37 | TT_STRING, /**< String literal. */ 38 | TT_IDENTIFIER, /**< Identifier literal. */ 39 | TT_BOOLEAN, /**< Boolean literal. */ 40 | TT_IT, /**< \ref impvar "Implicit variable". */ 41 | TT_ITZLIEKA, /**< Inherited object declaration. */ 42 | TT_NOOB, /**< Nil keyword. */ 43 | TT_NUMBR, /**< Integer keyword. */ 44 | TT_NUMBAR, /**< Decimal keyword. */ 45 | TT_TROOF, /**< Boolean keyword. */ 46 | TT_YARN, /**< String keyword. */ 47 | TT_BUKKIT, /**< Array. */ 48 | TT_EOF, /**< End of file. */ 49 | TT_NEWLINE, /**< Newline. */ 50 | TT_HAI, /**< Beginning of main block. */ 51 | TT_KTHXBYE, /**< End of main block. */ 52 | TT_ITZA, /**< Variable type initialization. */ 53 | TT_ITZ, /**< Variable value initialization. */ 54 | TT_RNOOB, /**< Deallocation. */ 55 | TT_R, /**< Assignment. */ 56 | TT_ANYR, /**< User-defined function argument separator. */ 57 | TT_AN, /**< Built-in function argument separator. */ 58 | TT_SUMOF, /**< Addition. */ 59 | TT_DIFFOF, /**< Subtraction. */ 60 | TT_PRODUKTOF, /**< Multiplication. */ 61 | TT_QUOSHUNTOF, /**< Division. */ 62 | TT_MODOF, /**< Modulo. */ 63 | TT_BIGGROF, /**< Greater than. */ 64 | TT_SMALLROF, /**< Less than. */ 65 | TT_BOTHOF, /**< Logical AND. */ 66 | TT_EITHEROF, /**< Logical OR. */ 67 | TT_WONOF, /**< Logical XOR. */ 68 | TT_NOT, /**< Logical NOT. */ 69 | TT_MKAY, /**< Infinite arity argument delimiter. */ 70 | TT_ALLOF, /**< Infinite arity logical AND. */ 71 | TT_ANYOF, /**< Infinite arity logical OR. */ 72 | TT_BOTHSAEM, /**< Equality. */ 73 | TT_DIFFRINT, /**< Inequality. */ 74 | TT_MAEK, /**< Cast. */ 75 | TT_A, /**< Cast target separator. */ 76 | TT_ISNOWA, /**< In-place cast. */ 77 | TT_SMOOSH, /**< String concatenation. */ 78 | TT_BANG, /**< Exclamation point (!) */ 79 | TT_GIMMEH, /**< Input. */ 80 | TT_ORLY, /**< Conditional. */ 81 | TT_YARLY, /**< True branch. */ 82 | TT_MEBBE, /**< Else branch. */ 83 | TT_NOWAI, /**< False branch. */ 84 | TT_OIC, /**< Conditional and switch delimiter. */ 85 | TT_WTF, /**< Switch. */ 86 | TT_OMG, /**< Case. */ 87 | TT_OMGWTF, /**< Default case. */ 88 | TT_GTFO, /**< Break or return without value. */ 89 | TT_IMINYR, /**< Loop beginning. */ 90 | TT_UPPIN, /**< Auto increment loop variable. */ 91 | TT_NERFIN, /**< Auto decrement loop variable. */ 92 | TT_YR, /**< Function name delimiter. */ 93 | TT_TIL, /**< Do until. */ 94 | TT_WILE, /**< Do while. */ 95 | TT_IMOUTTAYR, /**< Loop ending. */ 96 | TT_HOWIZ, /**< Function definition beginning. */ 97 | TT_IZ, /**< Function scope delimiter. */ 98 | TT_IFUSAYSO, /**< Function definition end. */ 99 | TT_FOUNDYR, /**< Return with value. */ 100 | TT_SRS, /**< Indirect variable access. */ 101 | TT_APOSTROPHEZ, /**< Array slot access ('Z). */ 102 | TT_OHAIIM, /**< Alternate array declaration. */ 103 | TT_IMLIEK, /**< Alternate inherited object declaration. */ 104 | TT_KTHX, /**< End of alternate array declaration. */ 105 | TT_HASA, /**< Variable declaration. */ 106 | TT_VISIBLE, /**< Print. */ 107 | 108 | TT_ENDOFTOKENS /**< Sentinel end of this enum -- don't move it! */ 109 | } TokenType; 110 | 111 | static const char *keywords[] = { 112 | "", /* TT_INTEGER */ 113 | "", /* TT_FLOAT */ 114 | "", /* TT_STRING */ 115 | "", /* TT_IDENTIFIER */ 116 | "", /* TT_BOOLEAN */ 117 | "IT", /* TT_IT */ 118 | "ITZ LIEK A", /* TT_ITZLIEKA */ 119 | "NOOB", /* TT_NOOB */ 120 | "NUMBR", /* TT_NUMBR */ 121 | "NUMBAR", /* TT_NUMBAR */ 122 | "TROOF", /* TT_TROOF */ 123 | "YARN", /* TT_YARN */ 124 | "BUKKIT", /* TT_BUKKIT */ 125 | "", /* TT_EOF */ 126 | "", /* TT_NEWLINE */ 127 | "so main", /* TT_HAI */ 128 | "KTHXBYE", /* TT_KTHXBYE */ 129 | "ITZ A", /* TT_ITZA */ 130 | "ITZ", /* TT_ITZ */ 131 | "R NOOB", /* TT_RNOOB */ 132 | "can be", /* TT_R */ 133 | "AN YR", /* TT_ANYR */ 134 | "and", /* TT_AN */ 135 | "so plus", /* TT_SUMOF */ 136 | "so minus", /* TT_DIFFOF */ 137 | "so times", /* TT_PRODUKTOF */ 138 | "so divide", /* TT_QUOSHUNTOF */ 139 | "so mod", /* TT_MODOF */ 140 | "much big", /* TT_BIGGROF */ 141 | "much small", /* TT_SMALLROF */ 142 | "BOTH OF", /* TT_BOTHOF */ 143 | "EITHER OF", /* TT_EITHEROF */ 144 | "WON OF", /* TT_WONOF */ 145 | "not", /* TT_NOT */ 146 | "MKAY", /* TT_MKAY */ 147 | "ALL OF", /* TT_ALLOF */ 148 | "ANY OF", /* TT_ANYOF */ 149 | "much saem", /* TT_BOTHSAEM */ 150 | "much diffrnt", /* TT_DIFFRINT */ 151 | "MAEK", /* TT_MAEK */ 152 | "A", /* TT_A */ 153 | "IS NOW A", /* TT_ISNOWA */ 154 | "SMOOSH", /* TT_SMOOSH */ 155 | "!", /* TT_BANG */ 156 | "GIMMEH", /* TT_GIMMEH */ 157 | "so if", /* TT_ORLY */ 158 | "many yes", /* TT_YARLY */ 159 | "MEBBE", /* TT_MEBBE */ 160 | "many no", /* TT_NOWAI */ 161 | "OIC", /* TT_OIC */ 162 | "WTF?", /* TT_WTF */ 163 | "OMG2", /* TT_OMG */ 164 | "OMGWTF", /* TT_OMGWTF */ 165 | "so break", /* TT_GTFO */ 166 | "so many", /* TT_IMINYR */ 167 | "such increment", /* TT_UPPIN */ 168 | "such decrement", /* TT_NERFIN */ 169 | "YR", /* TT_YR */ 170 | "TIL", /* TT_TIL */ 171 | "while", /* TT_WILE */ 172 | "IM OUTTA YR", /* TT_IMOUTTAYR */ 173 | "HOW IZ", /* TT_HOWIZ */ 174 | "IZ", /* TT_IZ */ 175 | "IF U SAY SO", /* TT_IFUSAYSO */ 176 | "FOUND YR", /* TT_FOUNDYR */ 177 | "SRS", /* TT_SRS */ 178 | "'Z", /* TT_APOSTROPHEZ */ 179 | "O HAI IM", /* TT_OHAIIM */ 180 | "IM LIEK", /* TT_IMLIEK */ 181 | "wow", /* TT_KTHX */ 182 | "so", /* TT_HASA */ 183 | "such", /* TT_VISIBLE */ 184 | "" /* TT_ENDOFTOKENS */ 185 | }; 186 | 187 | /** 188 | * Stores token data with semantic meaning. 189 | */ 190 | typedef union { 191 | long long i; /**< Integer data. */ 192 | float f; /**< Decimal data. */ 193 | } TokenData; 194 | 195 | /** 196 | * Stores a token type and any parsed values. 197 | */ 198 | typedef struct { 199 | TokenType type; /**< The type of token. */ 200 | TokenData data; /**< The stored data of type \a type. */ 201 | char *image; /**< The characters that comprise the token. */ 202 | const char *fname; /**< The name of the file containing the token. */ 203 | unsigned int line; /**< The line number the token was on. */ 204 | } Token; 205 | 206 | /** 207 | * \name Utilities 208 | * 209 | * Functions for performing helper tasks. 210 | */ 211 | /**@{*/ 212 | int isInteger(const char *); 213 | int isFloat(const char *); 214 | int isString(const char *); 215 | int isIdentifier(const char *); 216 | Token *isKeyword(LexemeList *, unsigned int *); 217 | /**@}*/ 218 | 219 | /** 220 | * \name Token modifiers 221 | * 222 | * Functions for creating and deleting tokens. 223 | */ 224 | /**@{*/ 225 | Token *createToken(TokenType, const char *, const char *, unsigned int); 226 | void deleteToken(Token *); 227 | int addToken(Token ***, unsigned int *, Token*); 228 | void deleteTokens(Token **); 229 | unsigned int acceptLexemes(LexemeList *, unsigned int, const char *); 230 | /**@}*/ 231 | 232 | /** 233 | * \name Lexeme tokenizer 234 | * 235 | * Generates tokens from lexemes. 236 | */ 237 | /**@{*/ 238 | Token **tokenizeLexemes(LexemeList *); 239 | /**@}*/ 240 | 241 | #endif /* __TOKENIZER_H__ */ 242 | -------------------------------------------------------------------------------- /error.c: -------------------------------------------------------------------------------- 1 | #include "error.h" 2 | 3 | static const char *err_msgs[] = { 4 | /* MN_ERROR_OPENING_FILE */ 5 | "Error opening file '%s'.\n", 6 | /* MN_ERROR_CLOSING_FILE */ 7 | "Error closing file '%s'.\n", 8 | 9 | /* LX_LINE_CONTINUATION */ 10 | "%s:%d: a line with continuation may not be followed by an empty line\n", 11 | /* LX_MULTIPLE_LINE_COMMENT */ 12 | "%s:%d: multiple line comment may not appear on the same line as code\n", 13 | /* LX_EXPECTED_TOKEN_DELIMITER */ 14 | "%s:%d: expected token delimiter after string literal\n", 15 | 16 | /* TK_EXPECTED_FLOATING_POINT */ 17 | "%s:%u: expected floating point decimal value\n", 18 | /* TK_EXPECTED_INTEGER */ 19 | "%s:%u: expected integer value\n", 20 | /* TK_UNKNOWN_TOKEN */ 21 | "%s:%u: unknown token at: %s\n", 22 | 23 | /* PR_UNKNOWN_IDENTIFIER_TYPE */ 24 | "%s:%u: unable to delete unknown identifier type\n", 25 | /* PR_UNKNOWN_STATEMENT_TYPE */ 26 | "unable to delete unknown statement type\n", 27 | /* PR_UNKNOWN_EXPRESSION_TYPE */ 28 | "unable to delete unknown expression type\n", 29 | /* PR_EXPECTED_BOOLEAN */ 30 | "%s:%u: expected integer at: %s\n", 31 | /* PR_EXPECTED_INTEGER */ 32 | "%s:%u: expected integer at: %s\n", 33 | /* PR_EXPECTED_FLOAT */ 34 | "%s:%u: expected float at: %s\n", 35 | /* PR_EXPECTED_STRING */ 36 | "%s:%u: expected string at: %s\n", 37 | /* PR_EXPECTED_CONSTANT */ 38 | "%s:%u: expected constant value at: %s\n", 39 | /* PR_EXPECTED_TYPE */ 40 | "%s:%u: expected type at: %s\n", 41 | /* PR_EXPECTED_IDENTIFIER */ 42 | "%s:%u: expected identifier at: %s\n", 43 | /* PR_EXPECTED_TOKEN */ 44 | "%s:%u: expected %s at: %s\n", 45 | /* PR_INVALID_OPERATOR */ 46 | "%s:%u: invalid operator at: %s\n", 47 | /* PR_EXPECTED_EXPRESSION */ 48 | "%s:%u: expected expression at: %s\n", 49 | /* PR_EXPECTED_END_OF_EXPRESSION */ 50 | "%s:%u: expected end of expression at: %s\n", 51 | /* PR_EXPECTED_END_OF_STATEMENT */ 52 | "%s:%u: expected end of statement at: %s\n", 53 | /* PR_CANNOT_USE_STR_AS_LITERAL */ 54 | "%s:%u: cannot use an interpolated string as an OMG literal at: %s\n", 55 | /* PR_LITERAL_MUST_BE_UNIQUE */ 56 | "%s:%u: OMG literal must be unique at: %s\n", 57 | /* PR_EXPECTED_LOOP_NAME */ 58 | "%s:%u: expected loop name at: %s\n", 59 | /* PR_EXPECTED_EITHER_TOKEN */ 60 | "%s:%u: expected %s or %s at: %s\n", 61 | /* PR_EXPECTED_UNARY_FUNCTION */ 62 | "%s:%u: expected unary function at: %s\n", 63 | /* PR_EXPECTED_MATCHING_LOOP_NAME */ 64 | "%s:%u: expected matching loop name at: %s\n", 65 | /* PR_EXPECTED_STATEMENT */ 66 | "%s:%u: expected statement at: %s\n", 67 | 68 | /* IN_INVALID_IDENTIFIER_TYPE */ 69 | "%s:%u invalid identifier type at: %s\n", 70 | /* IN_UNABLE_TO_STORE_VARIABLE */ 71 | "%s:%u unable to store variable: %s\n", 72 | /* IN_VARIABLE_DOES_NOT_EXIST */ 73 | "%s:%u variable does not exist: %s\n", 74 | /* IN_CANNOT_IMPLICITLY_CAST_NIL */ 75 | "Cannot implicitly cast nil\n", 76 | /* IN_CANNOT_CAST_FUNCTION_TO_BOOLEAN */ 77 | "Cannot cast function to boolean value\n", 78 | /* IN_CANNOT_CAST_ARRAY_TO_BOOLEAN */ 79 | "Cannot cast array to boolean value\n", 80 | /* IN_UNKNOWN_VALUE_DURING_BOOLEAN_CAST */ 81 | "Unknown value type encountered during boolean cast\n", 82 | /* IN_UNABLE_TO_CAST_VALUE */ 83 | "Unable to cast value\n", 84 | /* IN_EXPECTED_INTEGER_VALUE */ 85 | "Expected integer value\n", 86 | /* IN_CANNOT_CAST_FUNCTION_TO_INTEGER */ 87 | "Cannot cast function to integer value\n", 88 | /* IN_CANNOT_CAST_ARRAY_TO_INTEGER */ 89 | "Cannot cast array to integer value\n", 90 | /* IN_UNKNOWN_VALUE_DURING_INTEGER_CAST */ 91 | "Unknown value type encountered during integer cast\n", 92 | /* IN_EXPECTED_DECIMAL */ 93 | "Expected floating point decimal value\n", 94 | /* IN_CANNOT_CAST_FUNCTION_TO_DECIMAL */ 95 | "Cannot cast function to floating point decimal value\n", 96 | /* IN_CANNOT_CAST_ARRAY_TO_DECIMAL */ 97 | "Cannot cast array to floating point decimal value\n", 98 | /* IN_UNKNOWN_VALUE_DURING_DECIMAL_CAST */ 99 | "Unknown value type encountered during floating point decimal cast\n", 100 | /* IN_CANNOT_CAST_BOOLEAN_TO_STRING */ 101 | "Cannot cast boolean to string value\n", 102 | /* IN_EXPECTED_CLOSING_PAREN */ 103 | "Expected closing parenthesis after :(\n", 104 | /* IN_INVALID_HEX_NUMBER */ 105 | "Please supply a valid hexadecimal number\n", 106 | /* IN_CODE_POINT_MUST_BE_POSITIVE */ 107 | "Code point is supposed to be positive\n", 108 | /* IN_EXPECTED_CLOSING_SQUARE_BRACKET */ 109 | "Expected closing square bracket after :[\n", 110 | /* IN_EXPECTED_CLOSING_CURLY_BRACE */ 111 | "Expected closing curly brace after :{\n", 112 | /* IN_VARIABLE_NOT_AN_ARRAY */ 113 | "%s:%u variable is not an array: %s\n", 114 | /* IN_CANNOT_CAST_FUNCTION_TO_STRING */ 115 | "Cannot cast function to string value\n", 116 | /* IN_CANNOT_CAST_ARRAY_TO_STRING */ 117 | "Cannot cast array to string value\n", 118 | /* IN_UNKNOWN_VALUE_DURING_STRING_CAST */ 119 | "Unknown value type encountered during string cast\n", 120 | /* IN_UNKNOWN_CAST_TYPE */ 121 | "Unknown cast type\n", 122 | /* IN_UNDEFINED_FUNCTION */ 123 | "%s:%u: undefined function at: %s\n", 124 | /* IN_INCORRECT_NUMBER_OF_ARGUMENTS */ 125 | "%s:%u: incorrect number of arguments supplied to: %s\n", 126 | /* IN_INVALID_RETURN_TYPE */ 127 | "Invalid return type\n", 128 | /* IN_UNKNOWN_CONSTANT_TYPE */ 129 | "Unknown constant type\n", 130 | /* IN_DIVISION_BY_ZERO */ 131 | "Division by zero undefined\n", 132 | /* IN_INVALID_OPERAND_TYPE */ 133 | "Invalid operand type\n", 134 | /* IN_INVALID_BOOLEAN_OPERATION_TYPE */ 135 | "Invalid boolean operation type\n", 136 | /* IN_INVALID_EQUALITY_OPERATION_TYPE */ 137 | "Invalid equality operation type\n", 138 | /* IN_REDEFINITION_OF_VARIABLE */ 139 | "%s:%u: redefinition of existing variable at: %s\n", 140 | /* IN_INVALID_DECLARATION_TYPE */ 141 | "Unknown declaration type\n", 142 | /* IN_INVALID_TYPE */ 143 | "Invalid type\n", 144 | /* IN_FUNCTION_NAME_USED_BY_VARIABLE */ 145 | "%s:%u: function name already used by existing variable at: %s\n", 146 | }; 147 | 148 | static const int err_codes[] = { 149 | /* The 100 block is for the main body */ 150 | 100, /* MN_ERROR_OPENING_FILE */ 151 | 101, /* MN_ERROR_CLOSING_FILE */ 152 | 153 | /* The 200 block is for the lexer */ 154 | 200, /* LX_LINE_CONTINUATION */ 155 | 201, /* LX_MULTIPLE_LINE_COMMENT */ 156 | 202, /* LX_EXPECTED_TOKEN_DELIMITER */ 157 | 158 | /* The 300 block is for the tokenizer */ 159 | 300, /* TK_EXPECTED_FLOATING_POINT */ 160 | 301, /* TK_EXPECTED_INTEGER */ 161 | 302, /* TK_UNKNOWN_TOKEN */ 162 | 163 | /* The 400 block is for the parser */ 164 | 400, /* PR_UNKNOWN_IDENTIFIER_TYPE */ 165 | 401, /* PR_UNKNOWN_STATEMENT_TYPE */ 166 | 402, /* PR_UNKNOWN_EXPRESSION_TYPE */ 167 | 403, /* PR_EXPECTED_BOOLEAN */ 168 | 404, /* PR_EXPECTED_INTEGER */ 169 | 405, /* PR_EXPECTED_FLOAT */ 170 | 406, /* PR_EXPECTED_STRING */ 171 | 407, /* PR_EXPECTED_CONSTANT */ 172 | 408, /* PR_EXPECTED_TYPE */ 173 | 409, /* PR_EXPECTED_IDENTIFIER */ 174 | 410, /* PR_EXPECTED_TOKEN */ 175 | 411, /* PR_INVALID_OPERATOR */ 176 | 412, /* PR_EXPECTED_EXPRESSION */ 177 | 413, /* PR_EXPECTED_END_OF_EXPRESSION */ 178 | 414, /* PR_EXPECTED_END_OF_STATEMENT */ 179 | 415, /* PR_CANNOT_USE_STR_AS_LITERAL */ 180 | 416, /* PR_LITERAL_MUST_BE_UNIQUE */ 181 | 417, /* PR_EXPECTED_LOOP_NAME */ 182 | 418, /* PR_EXPECTED_ONE_OF */ 183 | 419, /* PR_EXPECTED_UNARY_FUNCTION */ 184 | 420, /* PR_EXPECTED_MATCHING_LOOP_NAME */ 185 | 421, /* PR_EXPECTED_STATEMENT */ 186 | 187 | /* The 500 block is for the interpreter */ 188 | 500, /* IN_INVALID_IDENTIFIER_TYPE */ 189 | 501, /* IN_UNABLE_TO_STORE_VARIABLE */ 190 | 502, /* IN_VARIABLE_DOES_NOT_EXIST */ 191 | 503, /* IN_CANNOT_IMPLICITLY_CAST_NIL */ 192 | 504, /* IN_CANNOT_CAST_FUNCTION_TO_BOOLEAN */ 193 | 505, /* IN_CANNOT_CAST_ARRAY_TO_BOOLEAN */ 194 | 506, /* IN_UNKNOWN_VALUE_DURING_BOOLEAN_CAST */ 195 | 507, /* IN_UNABLE_TO_CAST_VALUE */ 196 | 508, /* IN_EXPECTED_INTEGER_VALUE */ 197 | 509, /* IN_CANNOT_CAST_FUNCTION_TO_INTEGER */ 198 | 510, /* IN_CANNOT_CAST_ARRAY_TO_INTEGER */ 199 | 511, /* IN_UNKNOWN_VALUE_DURING_INTEGER_CAST */ 200 | 512, /* IN_EXPECTED_DECIMAL */ 201 | 513, /* IN_CANNOT_CAST_FUNCTION_TO_DECIMAL */ 202 | 514, /* IN_CANNOT_CAST_ARRAY_TO_DECIMAL */ 203 | 515, /* IN_UNKNOWN_VALUE_DURING_DECIMAL_CAST */ 204 | 516, /* IN_CANNOT_CAST_BOOLEAN_TO_STRING */ 205 | 517, /* IN_EXPECTED_CLOSING_PAREN */ 206 | 518, /* IN_INVALID_HEX_NUMBER */ 207 | 519, /* IN_CODE_POINT_MUST_BE_POSITIVE */ 208 | 520, /* IN_EXPECTED_CLOSING_SQUARE_BRACKET */ 209 | 521, /* IN_EXPECTED_CLOSING_CURLY_BRACE */ 210 | 522, /* IN_VARIABLE_NOT_AN_ARRAY */ 211 | 523, /* IN_CANNOT_CAST_FUNCTION_TO_STRING */ 212 | 524, /* IN_CANNOT_CAST_ARRAY_TO_STRING */ 213 | 525, /* IN_UNKNOWN_VALUE_DURING_STRING_CAST */ 214 | 526, /* IN_UNKNOWN_CAST_TYPE */ 215 | 527, /* IN_UNDEFINED_FUNCTION */ 216 | 528, /* IN_INCORRECT_NUMBER_OF_ARGUMENTS */ 217 | 529, /* IN_INVALID_RETURN_TYPE */ 218 | 530, /* IN_UNKNOWN_CONSTANT_TYPE */ 219 | 531, /* IN_DIVISION_BY_ZERO */ 220 | 532, /* IN_INVALID_OPERAND_TYPE */ 221 | 533, /* IN_INVALID_BOOLEAN_OPERATION_TYPE */ 222 | 534, /* IN_INVALID_EQUALITY_OPERATION_TYPE */ 223 | 535, /* IN_REDEFINITION_OF_VARIABLE */ 224 | 536, /* IN_INVALID_DECLARATION_TYPE */ 225 | 537, /* IN_INVALID_TYPE */ 226 | 538, /* IN_FUNCTION_NAME_USED_BY_VARIABLE */ 227 | }; 228 | 229 | void error(ErrorType e, ...) 230 | { 231 | va_list args; 232 | va_start(args, e); 233 | vfprintf(stderr, err_msgs[e], args); 234 | va_end(args); 235 | 236 | exit(err_codes[e]); 237 | } 238 | -------------------------------------------------------------------------------- /lexer.c: -------------------------------------------------------------------------------- 1 | #include "lexer.h" 2 | 3 | /** 4 | * Creates a lexeme. 5 | * 6 | * \param [in] image The string that identifies the lexeme. 7 | * 8 | * \param [in] fname The name of the file containing the lexeme. 9 | * 10 | * \param [in] line The line number the lexeme occurred on. 11 | * 12 | * \return A new lexeme with the desired properties. 13 | * 14 | * \retval NULL Memory allocation failed. 15 | */ 16 | Lexeme *createLexeme(char *image, const char *fname, unsigned int line) 17 | { 18 | Lexeme *ret = malloc(sizeof(Lexeme)); 19 | if (!ret) { 20 | perror("malloc"); 21 | return NULL; 22 | } 23 | ret->image = malloc(sizeof(char) * (strlen(image) + 1)); 24 | if (!(ret->image)) { 25 | free(ret); 26 | perror("malloc"); 27 | return NULL; 28 | } 29 | strcpy(ret->image, image); 30 | /** 31 | * \note \a fname is not copied because it only one copy is stored for 32 | * all lexemes from the same file. This is simply to avoid large 33 | * numbers of lexemes storing duplicate file name strings. 34 | */ 35 | ret->fname = fname; 36 | ret->line = line; 37 | #ifdef DEBUG 38 | fprintf(stderr, "Creating lexeme [%s]\n", image); 39 | #endif 40 | return ret; 41 | } 42 | 43 | /** 44 | * Deletes a lexeme. 45 | * 46 | * \param [in,out] lexeme The lexeme to delete. 47 | */ 48 | void deleteLexeme(Lexeme *lexeme) 49 | { 50 | if (!lexeme) return; 51 | free(lexeme->image); 52 | /** 53 | * \note We do not free the file name because it is shared between many 54 | * lexemes and is freed by whomever created the file name string. 55 | */ 56 | free(lexeme); 57 | } 58 | 59 | /** 60 | * Creates a list of lexemes. 61 | * 62 | * \return An empty lexeme list. 63 | * 64 | * \retval NULL Memory allocation failed. 65 | */ 66 | LexemeList *createLexemeList(void) 67 | { 68 | LexemeList *p = malloc(sizeof(LexemeList)); 69 | if (!p) { 70 | perror("malloc"); 71 | return NULL; 72 | } 73 | p->num = 0; 74 | p->lexemes = NULL; 75 | return p; 76 | } 77 | 78 | /** 79 | * Adds a lexeme to a list of lexemes. 80 | * 81 | * \param [in,out] list The list of lexemes to add \a lexeme to. 82 | * 83 | * \param [in] lexeme The lexeme to add to \a list. 84 | * 85 | * \post \a lexeme will be added to the end of \a list and the size of \a list 86 | * will be updated. 87 | * 88 | * \return A pointer to the added lexeme (will be the same as \a lexeme). 89 | * 90 | * \retval NULL Memory allocation failed. 91 | */ 92 | Lexeme *addLexeme(LexemeList *list, Lexeme *lexeme) 93 | { 94 | unsigned int newsize; 95 | void *mem = NULL; 96 | if (!list) return NULL; 97 | newsize = list->num + 1; 98 | mem = realloc(list->lexemes, sizeof(Lexeme *) * newsize); 99 | if (!mem) { 100 | perror("realloc"); 101 | return NULL; 102 | } 103 | list->lexemes = mem; 104 | list->lexemes[list->num] = lexeme; 105 | list->num = newsize; 106 | return lexeme; 107 | } 108 | 109 | /** 110 | * Deletes a list of lexemes. 111 | * 112 | * \param [in,out] list The lexeme list to delete. 113 | * 114 | * \post The memory at \a list and all of its members will be freed. 115 | */ 116 | void deleteLexemeList(LexemeList *list) 117 | { 118 | unsigned int n; 119 | if (!list) return; 120 | for (n = 0; n < list->num; n++) 121 | deleteLexeme(list->lexemes[n]); 122 | free(list->lexemes); 123 | free(list); 124 | } 125 | 126 | /** 127 | * Scans a buffer, removing unnecessary characters and grouping characters into 128 | * lexemes. Lexemes are strings of characters separated by whitespace (although 129 | * newline characters are considered separate lexemes). String literals are 130 | * handled a bit differently: Starting at the first quotation character, 131 | * characters are collected until either a non-escaped quotation character is 132 | * read (i.e., a quotation character not preceded by a colon which itself is not 133 | * preceded by a colon) or a newline or carriage return character is read, 134 | * whichever comes first. This handles the odd (but possible) case of strings 135 | * such as "::" which print out a single colon. Also handled are the effects of 136 | * commas, ellipses, bangs (!), and array accesses ('Z). 137 | * 138 | * \param [in] buffer The characters to turn into lexemes. 139 | * 140 | * \param [in] size The number of characters in \a buffer. 141 | * 142 | * \param [in] fname The name of the file \a buffer was read from. 143 | * 144 | * \return A list of lexemes created from the contents of \a buffer. 145 | */ 146 | LexemeList *scanBuffer(const char *buffer, unsigned int size, const char *fname) 147 | { 148 | const char *start = buffer; 149 | LexemeList *list = NULL; 150 | unsigned int line = 1; 151 | list = createLexemeList(); 152 | if (!list) return NULL; 153 | while (start < buffer + size) { 154 | char *temp = NULL; 155 | unsigned int len = 1; 156 | /* Comma (,) is a soft newline */ 157 | if (*start == ',') { 158 | Lexeme *lex = createLexeme("\n", fname, line); 159 | if (!lex) { 160 | deleteLexemeList(list); 161 | return NULL; 162 | } 163 | if (!addLexeme(list, lex)) { 164 | deleteLexeme(lex); 165 | deleteLexemeList(list); 166 | return NULL; 167 | } 168 | start++; 169 | continue; 170 | } 171 | /* Bang (!) is its own lexeme */ 172 | if (*start == '!') { 173 | Lexeme *lex = createLexeme("!", fname, line); 174 | if (!lex) { 175 | deleteLexemeList(list); 176 | return NULL; 177 | } 178 | if (!addLexeme(list, lex)) { 179 | deleteLexeme(lex); 180 | deleteLexemeList(list); 181 | return NULL; 182 | } 183 | start++; 184 | continue; 185 | } 186 | /* Apostrophe Z ('Z) is its own lexeme */ 187 | if (!strncmp(start, "'Z", 2)) { 188 | Lexeme *lex = createLexeme("'Z", fname, line); 189 | if (!lex) { 190 | deleteLexemeList(list); 191 | return NULL; 192 | } 193 | if (!addLexeme(list, lex)) { 194 | deleteLexeme(lex); 195 | deleteLexemeList(list); 196 | return NULL; 197 | } 198 | start += 2; 199 | continue; 200 | } 201 | /* Skip over leading whitespace */ 202 | while (isspace(*start)) { 203 | unsigned int newline = 0; 204 | /* Newline is its own lexeme */ 205 | if (!strncmp(start, "\r\n", 2)) { 206 | newline = 1; 207 | start++; 208 | } 209 | else if (*start == '\r' || *start == '\n') { 210 | newline = 1; 211 | } 212 | if (newline) { 213 | Lexeme *lex = createLexeme("\n", fname, line); 214 | if (!lex) { 215 | deleteLexemeList(list); 216 | return NULL; 217 | } 218 | if (!addLexeme(list, lex)) { 219 | deleteLexeme(lex); 220 | deleteLexemeList(list); 221 | return NULL; 222 | } 223 | line++; 224 | } 225 | start++; 226 | continue; 227 | } 228 | /* Skip over ellipses (...) and newline */ 229 | if ((!strncmp(start, "\xE2\x80\xA6\r\n", 5) && (start += 5)) 230 | || (!strncmp(start, "\xE2\x80\xA6\r", 4) && (start += 4)) 231 | || (!strncmp(start, "\xE2\x80\xA6\n", 4) && (start += 4)) 232 | || (!strncmp(start, "...\r\n", 5) && (start += 5)) 233 | || (!strncmp(start, "...\r", 4) && (start += 4)) 234 | || (!strncmp(start, "...\n", 4) && (start += 4))) { 235 | const char *test = start; 236 | /* Make sure next line is not empty */ 237 | while (*test && isspace(*test)) { 238 | if (*test == '\r' || *test == '\n') { 239 | error(LX_LINE_CONTINUATION, fname, line); 240 | deleteLexemeList(list); 241 | return NULL; 242 | } 243 | test++; 244 | } 245 | continue; 246 | } 247 | /* Skip over comments */ 248 | if ((list->num == 0 249 | || *(list->lexemes[list->num - 1]->image) == '\n') 250 | && !strncmp(start, "OBTW", 4)) { 251 | start += 4; 252 | while (strncmp(start, "TLDR", 4)) { 253 | if ((!strncmp(start, "\r\n", 2) && (start += 2)) 254 | || (*start == '\r' && start++) 255 | || (*start == '\n' && start++)) 256 | line++; 257 | else 258 | start++; 259 | } 260 | start += 4; 261 | /* Must end in newline */ 262 | while (*start && isspace(*start) && *start != '\r' && *start != '\n') 263 | start++; 264 | if (start == buffer || *start == ',' || *start == '\r' || *start == '\n') 265 | continue; 266 | error(LX_MULTIPLE_LINE_COMMENT, fname, line); 267 | deleteLexemeList(list); 268 | return NULL; 269 | } 270 | if (!strncmp(start, "omg", 3)) { 271 | start += 3; 272 | while (*start && *start != '\r' && *start != '\n') 273 | start++; 274 | continue; 275 | } 276 | /* We have removed or processed any leading characters at this 277 | * point */ 278 | if (!*start) break; 279 | if (*start == '"') { 280 | /* Find the end of the string, watching for escape 281 | * sequences */ 282 | while ((start[len] 283 | && *(start + len) != '\r' 284 | && *(start + len) != '\n' 285 | && *(start + len) != '"') 286 | || (*(start + len) == '"' 287 | && *(start + len - 1) == ':' 288 | && *(start + len - 2) != ':')) 289 | len++; 290 | if (*(start + len) == '"') len++; 291 | /* Make sure this is the end of the token */ 292 | if (start[len] && !isspace(start[len]) 293 | && *(start + len) != ',' 294 | && *(start + len) != '!' 295 | && strncmp(start + len, "'Z", 2) 296 | && strncmp(start + len, "...", 3) 297 | && strncmp(start + len, "\xE2\x80\xA6", 3)) { 298 | error(LX_EXPECTED_TOKEN_DELIMITER, fname, line); 299 | deleteLexemeList(list); 300 | return NULL; 301 | } 302 | } 303 | else { 304 | /* Scan for the end of the token */ 305 | while (start[len] && !isspace(start[len]) 306 | && *(start + len) != ',' 307 | && *(start + len) != '!' 308 | && strncmp(start + len, "'Z", 2) 309 | && strncmp(start + len, "...", 3) 310 | && strncmp(start + len, "\xE2\x80\xA6", 3)) 311 | len++; 312 | } 313 | temp = malloc(sizeof(char) * (len + 1)); 314 | if (!temp) { 315 | perror("malloc"); 316 | deleteLexemeList(list); 317 | return NULL; 318 | } 319 | strncpy(temp, start, len); 320 | temp[len] = '\0'; 321 | Lexeme *lex = createLexeme(temp, fname, line); 322 | if (!lex) { 323 | free(temp); 324 | deleteLexemeList(list); 325 | return NULL; 326 | } 327 | if (!addLexeme(list, lex)) { 328 | free(temp); 329 | deleteLexeme(lex); 330 | deleteLexemeList(list); 331 | return NULL; 332 | } 333 | free(temp); 334 | start += len; 335 | } 336 | /* Create an end-of-file lexeme */ 337 | Lexeme *lex = createLexeme("$", fname, line); 338 | if (!lex) { 339 | deleteLexemeList(list); 340 | return NULL; 341 | } 342 | if (!addLexeme(list, lex)) { 343 | deleteLexeme(lex); 344 | deleteLexemeList(list); 345 | return NULL; 346 | } 347 | return list; 348 | } 349 | -------------------------------------------------------------------------------- /tokenizer.c: -------------------------------------------------------------------------------- 1 | #include "tokenizer.h" 2 | 3 | /** 4 | * Checks if a string follows the format for an integer. Specifically, it 5 | * checks if the string matches the regular expression: (-?[1-9][0-9]*|0). 6 | * 7 | * \param [in] image The string to check. 8 | * 9 | * \retval 0 \a image does not match the pattern for an integer. 10 | * 11 | * \retval 1 \a image matches the pattern for an integer. 12 | */ 13 | int isInteger(const char *image) 14 | { 15 | const char *cur = image; 16 | if (*cur == '-' 17 | || (isdigit(*cur) && *cur != '0') 18 | || (*cur == '0' && *(cur + 1) == '\0')) { 19 | cur++; 20 | while (isdigit(*cur)) cur++; 21 | if (*cur == '\0') return 1; 22 | } 23 | return 0; 24 | } 25 | 26 | /** 27 | * Checks if a string follows the format for a decimal. Specifically, it checks 28 | * if the string matches the regular expression: (-?[0-9].[0-9]*). 29 | * 30 | * \param [in] image The string to check. 31 | * 32 | * \retval 0 \a image does not match the pattern for a decimal. 33 | * 34 | * \retval 1 \a image matches the pattern for a decimal. 35 | */ 36 | int isFloat(const char *image) 37 | { 38 | const char *cur = image; 39 | if (*cur == '-' || isdigit(*cur)) { 40 | cur++; 41 | while (isdigit(*cur)) cur++; 42 | if (*cur == '.') { 43 | cur++; 44 | while (isdigit(*cur)) cur++; 45 | if (*cur == '\0') return 1; 46 | } 47 | } 48 | return 0; 49 | } 50 | 51 | /** 52 | * Checks if a string follows the format for a string literal. Specifically, it 53 | * checks if the string matches the regular expression: (".*"). 54 | * 55 | * \param [in] image The string to check. 56 | * 57 | * \retval 0 \a image does not match the pattern for a string. 58 | * 59 | * \retval 1 \a image matches the pattern for a string. 60 | */ 61 | int isString(const char *image) 62 | { 63 | size_t len = strlen(image); 64 | return (len >= 2 && image[0] == '"' && image[len - 1] == '"'); 65 | } 66 | 67 | /** 68 | * Checks if a string follows the format for an identifier. Specifically, it 69 | * checks if the string matches the regular expression: ([a-zA-Z][a-zA-Z0-9_]*). 70 | * 71 | * \param image [in] The string to check. 72 | * 73 | * \retval 0 \a image does not match the pattern for an identifier. 74 | * 75 | * \retval 1 \a image matches the pattern for an identifier. 76 | */ 77 | int isIdentifier(const char *image) 78 | { 79 | const char *cur = image; 80 | /* First character must be alphabetic */ 81 | if (!cur || !isalpha(*cur)) return 0; 82 | cur++; 83 | while (*cur) { 84 | if (isalnum(*cur) || *cur == '_') cur++; 85 | else return 0; 86 | } 87 | return 1; 88 | } 89 | 90 | /** 91 | * Creates a token. 92 | * 93 | * \param [in] type The type of token to create. 94 | * 95 | * \param [in] image The string that represents the token. 96 | * 97 | * \param [in] fname The name of the file containing the token. 98 | * 99 | * \param [in] line The number of the line containing the token. 100 | * 101 | * \return A pointer to a new token with the desired properties. 102 | * 103 | * \retval NULL Memory allocation failed. 104 | */ 105 | Token *createToken(TokenType type, 106 | const char *image, 107 | const char *fname, 108 | unsigned int line) 109 | { 110 | Token *ret = malloc(sizeof(Token)); 111 | if (!ret) { 112 | perror("malloc"); 113 | return NULL; 114 | } 115 | ret->type = type; 116 | ret->image = malloc(sizeof(char) * (strlen(image) + 1)); 117 | if (!(ret->image)) { 118 | free(ret); 119 | perror("malloc"); 120 | return NULL; 121 | } 122 | strcpy(ret->image, image); 123 | /** 124 | * \note fname is not copied because only one copy is stored for all 125 | * Token structures that share it. 126 | */ 127 | ret->fname = fname; 128 | ret->line = line; 129 | return ret; 130 | } 131 | 132 | /** 133 | * Deletes a token. 134 | * 135 | * \param [in,out] token The token to delete. 136 | * 137 | * \post The memory at \a token and all of its members will be freed. 138 | */ 139 | void deleteToken(Token *token) 140 | { 141 | if (!token) return; 142 | free(token->image); 143 | free(token); 144 | } 145 | 146 | /** 147 | * Adds a token to a list. 148 | * 149 | * \param [in,out] list The list of tokens to add \a token to. 150 | * 151 | * \param [in,out] num The number of tokens in \a list. 152 | * 153 | * \param [in] token The token to add to \a list. 154 | * 155 | * \post \a token will be added to the end of \a list and the size of \a list 156 | * will be updated. 157 | * 158 | * \retval 0 Memory allocation failed. 159 | * 160 | * \retval 1 \a token was added to \a list. 161 | */ 162 | int addToken(Token ***list, 163 | unsigned int *num, 164 | Token *token) 165 | { 166 | unsigned int newsize = *num + 1; 167 | void *mem = realloc(*list, sizeof(Token *) * newsize); 168 | if (!mem) { 169 | perror("realloc"); 170 | return 0; 171 | } 172 | *list = mem; 173 | (*list)[*num] = token; 174 | *num = newsize; 175 | #ifdef DEBUG 176 | fprintf(stderr, "Adding token type %d [%s]\n", token->type, token->image); 177 | #endif 178 | return 1; 179 | } 180 | 181 | /** 182 | * Deletes a list of tokens. 183 | * 184 | * \param list [in,out] The list of tokens to delete. 185 | * 186 | * \post The memory at \a list and all of its members will be freed. 187 | */ 188 | void deleteTokens(Token **list) 189 | { 190 | Token **tok = list; 191 | while (*tok) { 192 | deleteToken(*tok); 193 | tok++; 194 | } 195 | free(list); 196 | } 197 | 198 | /** 199 | * Matches lexemes against a string. Traverses \a lexemes starting at \a start 200 | * and compares lexeme images to space-delimited substrings from \a match. 201 | * 202 | * \param lexemes [in] The list of lexemes to match from. 203 | * 204 | * \param start [in] The index within \a lexemes to start matching at. 205 | * 206 | * \param match [in] A string of space-delimited substrings to match. 207 | * 208 | * \return The number of lexemes matched. 209 | */ 210 | unsigned int acceptLexemes(LexemeList *lexemes, 211 | unsigned int start, 212 | const char *match) 213 | { 214 | unsigned int offset = 0; 215 | unsigned int n; 216 | unsigned int i; 217 | for (n = 0, i = 0; 218 | match[n] || lexemes->lexemes[start + offset]->image[i]; 219 | n++) { 220 | if (match[n] == ' ') { 221 | offset++; 222 | i = 0; 223 | continue; 224 | } 225 | if (lexemes->lexemes[start + offset]->image[i] != match[n]) 226 | return 0; 227 | i++; 228 | } 229 | return offset + 1; 230 | } 231 | 232 | /** 233 | * Checks if the next lexemes in a list comprise a keyword and, if so, generates 234 | * a new token representing that keyword. Specifically, \a lexemes is searched, 235 | * starting at \a start for keywords. If one is found, an appropriate token is 236 | * created and returned and \a start is incremented by the number of lexemes 237 | * matched minus one. 238 | * 239 | * \param lexemes [in] A list of lexemes to search for keywords in. 240 | * 241 | * \param start [in,out] The position within \a lexemes to begin searching for 242 | * keywords. 243 | * 244 | * \post If a keyword is not found, \a start will not be modified. Otherwise, 245 | * \a start will be incremented by the number of lexemes matched minus one. 246 | * 247 | * \return A pointer to the token containing the matched keyword. 248 | * 249 | * \retval NULL No keywords were found or there was an error allocating memory. 250 | */ 251 | Token *isKeyword(LexemeList *lexemes, 252 | unsigned int *start) 253 | { 254 | Token *token = NULL; 255 | TokenType type; 256 | const char *fname = lexemes->lexemes[*start]->fname; 257 | unsigned int line = lexemes->lexemes[*start]->line; 258 | /* For each keyword, */ 259 | for (type = 0; type != TT_ENDOFTOKENS; type++) { 260 | /* Check if the start of lexemes match */ 261 | unsigned int num = acceptLexemes(lexemes, 262 | *start, keywords[type]); 263 | if (!num) continue; 264 | /* If so, create a new token for the keyword */ 265 | token = createToken(type, keywords[type], fname, line); 266 | /* And advance the start */ 267 | *start += (num - 1); 268 | break; 269 | } 270 | return token; 271 | } 272 | 273 | /** 274 | * Converts a list of lexemes into tokens. Also parses integers, floats, and 275 | * strings into tokens with semantic meaning. 276 | * 277 | * \param list [in] A list of lexemes to tokenize. 278 | * 279 | * \return A list of tokens generated from \a list. 280 | * 281 | * \retval NULL An unrecognized token was encounteres or memory allocation 282 | * failed. 283 | */ 284 | Token **tokenizeLexemes(LexemeList *list) 285 | { 286 | void *mem = NULL; 287 | Token **ret = NULL; 288 | unsigned int retsize = 0; 289 | unsigned int n; 290 | for (n = 0; n < list->num; n++) { 291 | Lexeme *lexeme = list->lexemes[n]; 292 | const char *image = lexeme->image; 293 | const char *fname = lexeme->fname; 294 | unsigned int line = lexeme->line; 295 | Token *token = NULL; 296 | /* String */ 297 | if (isString(image)) { 298 | token = createToken(TT_STRING, image, fname, line); 299 | } 300 | /* Float */ 301 | else if (isFloat(image)) { 302 | token = createToken(TT_FLOAT, image, fname, line); 303 | if (sscanf(lexeme->image, "%f", &(token->data.f)) != 1) 304 | error(TK_EXPECTED_FLOATING_POINT, fname, line); 305 | } 306 | /* Integer */ 307 | else if (isInteger(image)) { 308 | token = createToken(TT_INTEGER, image, fname, line); 309 | if (sscanf(lexeme->image, "%lli", &(token->data.i)) != 1) 310 | error(TK_EXPECTED_INTEGER, fname, line); 311 | } 312 | /* FAIL */ 313 | else if (!strcmp(image, "FAIL")) { 314 | token = createToken(TT_BOOLEAN, "FAIL", fname, line); 315 | token->data.i = 0; 316 | } 317 | /* WIN */ 318 | else if (!strcmp(image, "WIN")) { 319 | token = createToken(TT_BOOLEAN, "WIN", fname, line); 320 | token->data.i = 1; 321 | } 322 | /* CAN HAS STDIO? */ 323 | else if (n < list->num - 2 324 | && !strcmp(lexeme->image, "CAN") 325 | && !strcmp(list->lexemes[n + 1]->image, "HAS") 326 | && !strcmp(list->lexemes[n + 2]->image, "STDIO?")) { 327 | n += 2; 328 | /* Just for fun; not actually in spec */ 329 | continue; 330 | } 331 | /* Newline */ 332 | /* Note that the spec is unclear as to whether a command *must* 333 | * follow a comma. For now, we let commas end a line. */ 334 | else if (!strcmp(image, "\n")) { 335 | /* Note that we ignore any initial newlines */ 336 | if (retsize < 1) { 337 | #ifdef DEBUG 338 | fprintf(stderr, "Skipping initial newline.\n"); 339 | #endif 340 | continue; 341 | } 342 | else if (ret[retsize - 1]->type == TT_NEWLINE) { 343 | #ifdef DEBUG 344 | fprintf(stderr, "Skipping duplicate newline.\n"); 345 | #endif 346 | continue; 347 | } 348 | else { 349 | token = createToken(TT_NEWLINE, "end of line", fname, line); 350 | } 351 | } 352 | /* Keyword */ 353 | else if ((token = isKeyword(list, &n))) { 354 | } 355 | /* Identifier */ 356 | /* This must be placed after keyword parsing or else most 357 | * keywords would be tokenized as identifiers. */ 358 | else if (isIdentifier(image)) { 359 | token = createToken(TT_IDENTIFIER, image, fname, line); 360 | } 361 | /* EOF */ 362 | else if (!strcmp(image, "$")) { 363 | token = createToken(TT_EOF, "end of file", fname, line); 364 | } 365 | else { 366 | error(TK_UNKNOWN_TOKEN, fname, line, image); 367 | /* Clean up */ 368 | deleteToken(ret[retsize - 1]); 369 | ret[retsize - 1] = NULL; 370 | deleteTokens(ret); 371 | return NULL; 372 | } 373 | 374 | /* Add the token to the token array */ 375 | if (!addToken(&ret, &retsize, token)) { 376 | /* Clean up */ 377 | if (token) deleteToken(token); 378 | deleteToken(ret[retsize - 1]); 379 | ret[retsize - 1] = NULL; 380 | deleteTokens(ret); 381 | return NULL; 382 | } 383 | } 384 | mem = realloc(ret, sizeof(Token *) * ++retsize); 385 | if (!mem) { 386 | deleteToken(ret[retsize - 2]); 387 | ret[retsize - 2] = NULL; 388 | deleteTokens(ret); 389 | return NULL; 390 | } 391 | ret = mem; 392 | ret[retsize - 1] = NULL; 393 | return ret; 394 | } 395 | -------------------------------------------------------------------------------- /interpreter.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Structures and functions for interpreting a parse tree. The interpreter 3 | * traverses a parse tree in a depth-first manner, interpreting each node it 4 | * reaches along the way. This is the last stage of the processing of a source 5 | * code file. 6 | * 7 | * \file interpreter.h 8 | * 9 | * \author Justin J. Meza 10 | * 11 | * \date 2010-2012 12 | */ 13 | 14 | #ifndef __INTERPRETER_H__ 15 | #define __INTERPRETER_H__ 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | #include "parser.h" 22 | #include "unicode.h" 23 | 24 | /** 25 | * Retrieves a value's integer data. 26 | */ 27 | #define getInteger(value) (value->data.i) 28 | 29 | /** 30 | * Retrieves a value's decimal data. 31 | */ 32 | #define getFloat(value) (value->data.f) 33 | 34 | /** 35 | * Retrieves a value's string data. 36 | */ 37 | #define getString(value) (value->data.s) 38 | 39 | /** 40 | * Retrieves a value's function data. 41 | */ 42 | #define getFunction(value) (value->data.fn) 43 | 44 | /** 45 | * Retrieves a value's array data. 46 | */ 47 | #define getArray(value) (value->data.a) 48 | 49 | /** 50 | * Represents a value type. 51 | */ 52 | typedef enum { 53 | VT_INTEGER, /**< An integer value. */ 54 | VT_FLOAT, /**< A decimal value. */ 55 | VT_BOOLEAN, /**< A boolean value. */ 56 | VT_STRING, /**< A string value. */ 57 | VT_NIL, /**< Represents no value. */ 58 | VT_FUNC, /**< A function. */ 59 | VT_ARRAY /**< An array. */ 60 | } ValueType; 61 | 62 | /** 63 | * Stores value data. 64 | */ 65 | typedef union { 66 | long long i; /**< Integer data. */ 67 | float f; /**< Decimal data. */ 68 | char *s; /**< String data. */ 69 | FuncDefStmtNode *fn; /**< Function data. */ 70 | struct scopeobject *a; /**< Array data. */ 71 | } ValueData; 72 | 73 | /** 74 | * Increments a value's semaphore. 75 | */ 76 | #define V(value) (value->semaphore++) 77 | 78 | /** 79 | * Decrements a value's semaphore. 80 | */ 81 | #define P(value) (value->semaphore--) 82 | 83 | /** 84 | * Stores a value. 85 | */ 86 | typedef struct { 87 | ValueType type; /**< The type of value stored. */ 88 | ValueData data; /**< The value data. */ 89 | unsigned short semaphore; /**< A semaphore for value usage. */ 90 | } ValueObject; 91 | 92 | /** 93 | * Represents the return type. 94 | */ 95 | typedef enum { 96 | RT_DEFAULT, /**< Code block completed successfully. */ 97 | RT_BREAK, /**< Broke out of a loop or switch statement. */ 98 | RT_RETURN /**< Returned from a function. */ 99 | } ReturnType; 100 | 101 | /** 102 | * Stores return state. 103 | */ 104 | typedef struct { 105 | ReturnType type; /**< The type of return encountered. */ 106 | ValueObject *value; /**< The optional return value. */ 107 | } ReturnObject; 108 | 109 | /** 110 | * Stores a set of variables hierarchically. 111 | */ 112 | typedef struct scopeobject { 113 | struct scopeobject *parent; /**< The parent scope. */ 114 | struct scopeobject *caller; /**< The caller scope (if in a function). */ 115 | ValueObject *impvar; /**< The \ref impvar "implicit variable". */ 116 | unsigned int numvals; /**< The number of values in the scope. */ 117 | char **names; /**< The names of the values. */ 118 | ValueObject **values; /**< The values in the scope. */ 119 | } ScopeObject; 120 | 121 | /** 122 | * \name Utilities 123 | * 124 | * Functions for performing helper tasks. 125 | */ 126 | /**@{*/ 127 | void printInterpreterError(const char *, IdentifierNode *, ScopeObject *); 128 | char *copyString(char *); 129 | unsigned int isDecString(const char *); 130 | unsigned int isHexString(const char *); 131 | char *resolveIdentifierName(IdentifierNode *, ScopeObject *); 132 | /**@}*/ 133 | 134 | /** 135 | * \name Value object modifiers 136 | * 137 | * Functions for creating, copying, and deleting value objects. 138 | */ 139 | /**@{*/ 140 | ValueObject *createNilValueObject(void); 141 | ValueObject *createBooleanValueObject(int); 142 | ValueObject *createIntegerValueObject(long long); 143 | ValueObject *createFloatValueObject(float); 144 | ValueObject *createStringValueObject(char *); 145 | ValueObject *createFunctionValueObject(FuncDefStmtNode *); 146 | ValueObject *createArrayValueObject(ScopeObject *); 147 | ValueObject *copyValueObject(ValueObject *); 148 | void deleteValueObject(ValueObject *); 149 | /**@}*/ 150 | 151 | /** 152 | * \name Scope object modifiers 153 | * 154 | * Functions for manipulating scope objects and their data. 155 | */ 156 | /**@{*/ 157 | ScopeObject *createScopeObject(ScopeObject *); 158 | ScopeObject *createScopeObjectCaller(ScopeObject *, ScopeObject *); 159 | void deleteScopeObject(ScopeObject *); 160 | ValueObject *createScopeValue(ScopeObject *, ScopeObject *, IdentifierNode *); 161 | ValueObject *updateScopeValue(ScopeObject *, ScopeObject *, IdentifierNode *, ValueObject *); 162 | ValueObject *getScopeValue(ScopeObject *, ScopeObject *, IdentifierNode *); 163 | ValueObject *getScopeValueLocal(ScopeObject *, ScopeObject *, IdentifierNode *); 164 | ScopeObject *getScopeObject(ScopeObject *, ScopeObject *, IdentifierNode *); 165 | ScopeObject *getScopeObjectLocal(ScopeObject *, ScopeObject *, IdentifierNode *); 166 | void deleteScopeValue(ScopeObject *, ScopeObject *, IdentifierNode *); 167 | /**@}*/ 168 | 169 | /** 170 | * \name Return object modifiers 171 | * 172 | * Functions for creating and deleting return objects. 173 | */ 174 | /**@{*/ 175 | ReturnObject *createReturnObject(ReturnType, ValueObject *); 176 | void deleteReturnObject(ReturnObject *); 177 | /**@}*/ 178 | 179 | /** 180 | * \name Casts 181 | * 182 | * Functions for performing casts between different types of values. 183 | */ 184 | /**@{*/ 185 | ValueObject *castBooleanImplicit(ValueObject *, ScopeObject *); 186 | ValueObject *castIntegerImplicit(ValueObject *, ScopeObject *); 187 | ValueObject *castFloatImplicit(ValueObject *, ScopeObject *); 188 | ValueObject *castStringImplicit(ValueObject *, ScopeObject *); 189 | ValueObject *castBooleanExplicit(ValueObject *, ScopeObject *); 190 | ValueObject *castIntegerExplicit(ValueObject *, ScopeObject *); 191 | ValueObject *castFloatExplicit(ValueObject *, ScopeObject *); 192 | ValueObject *castStringExplicit(ValueObject *, ScopeObject *); 193 | /**@}*/ 194 | 195 | /** 196 | * \name Node interpreters 197 | * 198 | * Functions for interpreting basic parse tree nodes. 199 | */ 200 | /**@{*/ 201 | ValueObject *interpretExprNode(ExprNode *, ScopeObject *); 202 | ReturnObject *interpretStmtNode(StmtNode *, ScopeObject *); 203 | ReturnObject *interpretStmtNodeList(StmtNodeList *, ScopeObject *); 204 | ReturnObject *interpretBlockNode(BlockNode *, ScopeObject *); 205 | int interpretMainNode(MainNode *); 206 | /**@}*/ 207 | 208 | /** 209 | * \name Expression interpreters 210 | * 211 | * Functions for interpreting expression parse tree nodes. 212 | */ 213 | /**@{*/ 214 | ValueObject *interpretImpVarExprNode(ExprNode *, ScopeObject *); 215 | ValueObject *interpretCastExprNode(ExprNode *, ScopeObject *); 216 | ValueObject *interpretFuncCallExprNode(ExprNode *, ScopeObject *); 217 | ValueObject *interpretIdentifierExprNode(ExprNode *, ScopeObject *); 218 | ValueObject *interpretConstantExprNode(ExprNode *, ScopeObject *); 219 | /**@}*/ 220 | 221 | /** 222 | * \name Operation interpreters 223 | * 224 | * Functions for interpreting operation parse tree nodes. 225 | */ 226 | /**@{*/ 227 | ValueObject *interpretNotOpExprNode(OpExprNode *, ScopeObject *); 228 | ValueObject *interpretArithOpExprNode(OpExprNode *, ScopeObject *); 229 | ValueObject *interpretBoolOpExprNode(OpExprNode *, ScopeObject *); 230 | ValueObject *interpretEqualityOpExprNode(OpExprNode *, ScopeObject *); 231 | ValueObject *interpretConcatOpExprNode(OpExprNode *, ScopeObject *); 232 | ValueObject *interpretOpExprNode(ExprNode *, ScopeObject *); 233 | /**@}*/ 234 | 235 | /** 236 | * \name Statement interpreters 237 | * 238 | * Functions for interpreting statement parse tree nodes. 239 | */ 240 | /**@{*/ 241 | ReturnObject *interpretCastStmtNode(StmtNode *, ScopeObject *); 242 | ReturnObject *interpretPrintStmtNode(StmtNode *, ScopeObject *); 243 | ReturnObject *interpretInputStmtNode(StmtNode *, ScopeObject *); 244 | ReturnObject *interpretAssignmentStmtNode(StmtNode *, ScopeObject *); 245 | ReturnObject *interpretDeclarationStmtNode(StmtNode *, ScopeObject *); 246 | ReturnObject *interpretIfThenElseStmtNode(StmtNode *, ScopeObject *); 247 | ReturnObject *interpretSwitchStmtNode(StmtNode *, ScopeObject *); 248 | ReturnObject *interpretBreakStmtNode(StmtNode *, ScopeObject *); 249 | ReturnObject *interpretReturnStmtNode(StmtNode *, ScopeObject *); 250 | ReturnObject *interpretLoopStmtNode(StmtNode *, ScopeObject *); 251 | ReturnObject *interpretDeallocationStmtNode(StmtNode *, ScopeObject *); 252 | ReturnObject *interpretFuncDefStmtNode(StmtNode *, ScopeObject *); 253 | ReturnObject *interpretExprStmtNode(StmtNode *, ScopeObject *); 254 | ReturnObject *interpretAltArrayDefStmtNode(StmtNode *, ScopeObject *); 255 | /**@}*/ 256 | 257 | /** 258 | * \name Arithmetic operations (integer-integer) 259 | * 260 | * Functions for performing integer-integer operations on values. 261 | */ 262 | /**@{*/ 263 | ValueObject *opAddIntegerInteger(ValueObject *, ValueObject *); 264 | ValueObject *opSubIntegerInteger(ValueObject *, ValueObject *); 265 | ValueObject *opMultIntegerInteger(ValueObject *, ValueObject *); 266 | ValueObject *opDivIntegerInteger(ValueObject *, ValueObject *); 267 | ValueObject *opMaxIntegerInteger(ValueObject *, ValueObject *); 268 | ValueObject *opMinIntegerInteger(ValueObject *, ValueObject *); 269 | ValueObject *opModIntegerInteger(ValueObject *, ValueObject *); 270 | /**@}*/ 271 | 272 | /** 273 | * \name Arithmetic operations (integer-float) 274 | * 275 | * Functions for performing integer-float operations on values. 276 | */ 277 | /**@{*/ 278 | ValueObject *opAddIntegerFloat(ValueObject *, ValueObject *); 279 | ValueObject *opSubIntegerFloat(ValueObject *, ValueObject *); 280 | ValueObject *opMultIntegerFloat(ValueObject *, ValueObject *); 281 | ValueObject *opDivIntegerFloat(ValueObject *, ValueObject *); 282 | ValueObject *opMaxIntegerFloat(ValueObject *, ValueObject *); 283 | ValueObject *opMinIntegerFloat(ValueObject *, ValueObject *); 284 | ValueObject *opModIntegerFloat(ValueObject *, ValueObject *); 285 | /**@}*/ 286 | 287 | /** 288 | * \name Arithmetic operations (float-integer) 289 | * 290 | * Functions for performing float-integer operations on values. 291 | */ 292 | /**@{*/ 293 | ValueObject *opAddFloatInteger(ValueObject *, ValueObject *); 294 | ValueObject *opSubFloatInteger(ValueObject *, ValueObject *); 295 | ValueObject *opMultFloatInteger(ValueObject *, ValueObject *); 296 | ValueObject *opDivFloatInteger(ValueObject *, ValueObject *); 297 | ValueObject *opMaxFloatInteger(ValueObject *, ValueObject *); 298 | ValueObject *opMinFloatInteger(ValueObject *, ValueObject *); 299 | ValueObject *opModFloatInteger(ValueObject *, ValueObject *); 300 | /**@}*/ 301 | 302 | /** 303 | * \name Arithmetic operations (float-float) 304 | * 305 | * Functions for performing float-float operations on values. 306 | */ 307 | /**@{*/ 308 | ValueObject *opAddFloatFloat(ValueObject *, ValueObject *); 309 | ValueObject *opSubFloatFloat(ValueObject *, ValueObject *); 310 | ValueObject *opMultFloatFloat(ValueObject *, ValueObject *); 311 | ValueObject *opDivFloatFloat(ValueObject *, ValueObject *); 312 | ValueObject *opMaxFloatFloat(ValueObject *, ValueObject *); 313 | ValueObject *opMinFloatFloat(ValueObject *, ValueObject *); 314 | ValueObject *opModFloatFloat(ValueObject *, ValueObject *); 315 | /**@}*/ 316 | 317 | /** 318 | * \name Equality operations (boolean-boolean) 319 | * 320 | * Functions for performing boolean-boolean operations on values. 321 | */ 322 | /**@{*/ 323 | ValueObject *opEqBooleanBoolean(ValueObject *, ValueObject *); 324 | ValueObject *opNeqBooleanBoolean(ValueObject *, ValueObject *); 325 | /**@}*/ 326 | 327 | /** 328 | * \name Equality operations (integer-integer) 329 | * 330 | * Functions for performing integer-integer operations on values. 331 | */ 332 | /**@{*/ 333 | ValueObject *opEqIntegerInteger(ValueObject *, ValueObject *); 334 | ValueObject *opNeqIntegerInteger(ValueObject *, ValueObject *); 335 | /**@}*/ 336 | 337 | /** 338 | * \name Equality operations (integer-float) 339 | * 340 | * Functions for performing integer-float operations on values. 341 | */ 342 | /**@{*/ 343 | ValueObject *opEqIntegerFloat(ValueObject *, ValueObject *); 344 | ValueObject *opNeqIntegerFloat(ValueObject *, ValueObject *); 345 | /**@}*/ 346 | 347 | /** 348 | * \name Equality operations (float-integer) 349 | * 350 | * Functions for performing float-integer operations on values. 351 | */ 352 | /**@{*/ 353 | ValueObject *opEqFloatInteger(ValueObject *, ValueObject *); 354 | ValueObject *opNeqFloatInteger(ValueObject *, ValueObject *); 355 | /**@}*/ 356 | 357 | /** 358 | * \name Equality operations (float-float) 359 | * 360 | * Functions for performing float-float operations on values. 361 | */ 362 | /**@{*/ 363 | ValueObject *opEqFloatFloat(ValueObject *, ValueObject *); 364 | ValueObject *opNeqFloatFloat(ValueObject *, ValueObject *); 365 | /**@}*/ 366 | 367 | /** 368 | * \name Equality operations (string-string) 369 | * 370 | * Functions for performing string-string operations on values. 371 | */ 372 | /**@{*/ 373 | ValueObject *opEqStringString(ValueObject *, ValueObject *); 374 | ValueObject *opNeqStringString(ValueObject *, ValueObject *); 375 | /**@}*/ 376 | 377 | /** 378 | * \name Equality operations (nil-nil) 379 | * 380 | * Functions for performing nil-nil operations on values. 381 | */ 382 | /**@{*/ 383 | ValueObject *opEqNilNil(ValueObject *, ValueObject *); 384 | ValueObject *opNeqNilNil(ValueObject *, ValueObject *); 385 | /**@}*/ 386 | 387 | #endif /* __INTERPRETER_H__ */ 388 | -------------------------------------------------------------------------------- /parser.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Structures and functions for parsing tokens to a parse tree. The parser 3 | * reads through a list of tokens (generated by the tokenizer) and adds semantic 4 | * meaning to them by forming them into a parse tree which can then be passed on 5 | * to later stages (such as the interpreter). 6 | * 7 | * \file parser.h 8 | * 9 | * \author Justin J. Meza 10 | * 11 | * \date 2010-2012 12 | */ 13 | 14 | #ifndef __PARSER_H__ 15 | #define __PARSER_H__ 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include "tokenizer.h" 24 | 25 | #undef DEBUG 26 | 27 | /** 28 | * Represents a statement type. 29 | */ 30 | typedef enum { 31 | ST_CAST, /**< Cast statement. */ 32 | ST_PRINT, /**< Print statement. */ 33 | ST_INPUT, /**< Input statement. */ 34 | ST_ASSIGNMENT, /**< Assignment statement. */ 35 | ST_DECLARATION, /**< Declaration statement. */ 36 | ST_IFTHENELSE, /**< If/then/else statement. */ 37 | ST_SWITCH, /**< Switch statement. */ 38 | ST_BREAK, /**< Break statement. */ 39 | ST_RETURN, /**< Return statement. */ 40 | ST_LOOP, /**< Loop statement. */ 41 | ST_DEALLOCATION, /**< Deallocation statement. */ 42 | ST_FUNCDEF, /**< Function definition statement. */ 43 | ST_EXPR, /**< Expression statement. */ 44 | ST_ALTARRAYDEF, /**< Function definition statement. */ 45 | } StmtType; 46 | 47 | /** 48 | * Stores statement data. 49 | */ 50 | typedef struct { 51 | StmtType type; /**< The type of statement in \a node. */ 52 | void *stmt; /**< The statement. */ 53 | } StmtNode; 54 | 55 | /** 56 | * Stores a list of statements. 57 | */ 58 | typedef struct { 59 | unsigned int num; /**< The number of statements. */ 60 | StmtNode **stmts; /**< The array of statements. */ 61 | } StmtNodeList; 62 | 63 | /** 64 | * Represents an expression type. 65 | */ 66 | typedef enum { 67 | ET_CAST, /**< Cast expression. */ 68 | ET_CONSTANT, /**< Constant expression. */ 69 | ET_IDENTIFIER, /**< Identifier expression. */ 70 | ET_FUNCCALL, /**< Function call expression. */ 71 | ET_OP, /**< Operation expression. */ 72 | ET_IMPVAR /**< \ref impvar "Implicit variable". */ 73 | } ExprType; 74 | 75 | /** 76 | * Stores an expression. 77 | */ 78 | typedef struct { 79 | ExprType type; /**< The type of expression in \a expr. */ 80 | void *expr; /**< The expression. */ 81 | } ExprNode; 82 | 83 | /** 84 | * Stores a list of expressions. 85 | */ 86 | typedef struct { 87 | unsigned int num; /**< The number of expressions. */ 88 | ExprNode **exprs; /**< The array of statements. */ 89 | } ExprNodeList; 90 | 91 | /** 92 | * Represents an identifier type. 93 | */ 94 | typedef enum { 95 | IT_DIRECT, /**< Direct identifier. */ 96 | IT_INDIRECT /**< Indirect identifier. */ 97 | } IdentifierType; 98 | 99 | /** 100 | * Stores an identifier. 101 | */ 102 | typedef struct identifiernode { 103 | IdentifierType type; /**< The type of identifier in \a id. */ 104 | void *id; /**< The identifier. */ 105 | char *fname; /**< The original file name. */ 106 | unsigned int line; /**< The original line number. */ 107 | struct identifiernode *slot; /**< The slot to access. */ 108 | } IdentifierNode; 109 | 110 | /** 111 | * Stores a list of identifiers. 112 | */ 113 | typedef struct { 114 | unsigned int num; /**< The number of identifiers. */ 115 | IdentifierNode **ids; /**< The array of identifiers. */ 116 | } IdentifierNodeList; 117 | 118 | /** 119 | * Stores a code block. 120 | */ 121 | typedef struct { 122 | StmtNodeList *stmts; /**< The list of statements in the block. */ 123 | } BlockNode; 124 | 125 | /** 126 | * Stores a list of code blocks. 127 | */ 128 | typedef struct { 129 | unsigned int num; /**< The number of code blocks. */ 130 | BlockNode **blocks; /**< The array of code blocks. */ 131 | } BlockNodeList; 132 | 133 | /** 134 | * Represents a constant type. 135 | */ 136 | typedef enum { 137 | CT_INTEGER, /**< Integer constant. */ 138 | CT_FLOAT, /**< Decimal constant. */ 139 | CT_BOOLEAN, /**< Boolean constant. */ 140 | CT_STRING, /**< String constant. */ 141 | CT_NIL, /**< Nil constant. */ 142 | CT_ARRAY /**< Array constant. */ 143 | } ConstantType; 144 | 145 | /** 146 | * Stores constant data. 147 | */ 148 | typedef union { 149 | long long i; /**< Integer data. */ 150 | float f; /**< Decimal data. */ 151 | char *s; /**< String data. */ 152 | } ConstantData; 153 | 154 | /** 155 | * Stores a constant. 156 | */ 157 | typedef struct { 158 | ConstantType type; /**< The type of constant in \a data. */ 159 | ConstantData data; /**< The constant. */ 160 | } ConstantNode; 161 | 162 | /** 163 | * Stores a function definition statement. 164 | */ 165 | typedef struct { 166 | IdentifierNode *scope; /**< The scope of the function. */ 167 | IdentifierNode *name; /**< The name of the function. */ 168 | IdentifierNodeList *args; /**< The names of the function arguments. */ 169 | BlockNode *body; /**< The body of the function. */ 170 | } FuncDefStmtNode; 171 | 172 | /** 173 | * Stores an alternate array definition statement. 174 | */ 175 | typedef struct { 176 | IdentifierNode *name; /**< The name of the array. */ 177 | BlockNode *body; /**< The body of the array definition. */ 178 | IdentifierNode *parent; /**< An optional inherited array. */ 179 | } AltArrayDefStmtNode; 180 | 181 | /** 182 | * Stores the main code block of a program. 183 | * 184 | * \note This could be represented with just a BlockNode, but it seems 185 | * significant enough to merit its own structure. 186 | */ 187 | typedef struct { 188 | BlockNode *block; /**< The first block of code to execute. */ 189 | } MainNode; 190 | 191 | /** 192 | * Stores a variable type. 193 | */ 194 | typedef struct { 195 | ConstantType type; /**< The type variable. */ 196 | } TypeNode; 197 | 198 | /** 199 | * Stores a cast statement. This statement changes the type of a variable. 200 | */ 201 | typedef struct { 202 | IdentifierNode *target; /**< The name of the variable to cast. */ 203 | TypeNode *newtype; /**< The type to cast \a target to. */ 204 | } CastStmtNode; 205 | 206 | /** 207 | * Stores a print statement. This statement prints a list of expressions with 208 | * an optional newline. 209 | */ 210 | typedef struct { 211 | ExprNodeList *args; /**< The expressions to print. */ 212 | int nonl; /**< Whether to print an ending newline. */ 213 | } PrintStmtNode; 214 | 215 | /** 216 | * Stores an input statement. This statement accepts input from the user and 217 | * stores it in a variable. 218 | */ 219 | typedef struct { 220 | IdentifierNode *target; /**< The variable to store the input in. */ 221 | } InputStmtNode; 222 | 223 | /** 224 | * Stores an assignment statement. This statement stores an evaluated 225 | * expression in a variable. 226 | */ 227 | typedef struct { 228 | IdentifierNode *target; /**< The variable to store \a expr in. */ 229 | ExprNode *expr; /**< The expression to store. */ 230 | } AssignmentStmtNode; 231 | 232 | /** 233 | * Stores a declaration statement. This statement creates a new variable in a 234 | * given scope and optionally initializes it to an expression. 235 | * 236 | * \note Either provide \a expr OR \a type. If both are provided, the result is 237 | * undefined. 238 | */ 239 | typedef struct { 240 | IdentifierNode *scope; /**< The scope to create the variable in. */ 241 | IdentifierNode *target; /**< The name of the variable to create. */ 242 | ExprNode *expr; /**< An optional initialization expression. */ 243 | TypeNode *type; /**< An optional initialization type. */ 244 | IdentifierNode *parent; /**< An optional inherited array. */ 245 | } DeclarationStmtNode; 246 | 247 | /** 248 | * Stores an if/then/else statement. This statement checks the value of the 249 | * \ref impvar "implicit variable" and executes the \c yes block if it can be 250 | * cast to true. Else, the \c guards are evaluated and the corresponding code 251 | * in one of the \c blocks is executed. Finally, if none of these things occur, 252 | * the \c no block is executed. 253 | */ 254 | typedef struct { 255 | BlockNode *yes; /**< The code to execute if \c IT is true. */ 256 | BlockNode *no; /**< The code to execute if nothing else does. */ 257 | ExprNodeList *guards; /**< The guards for the \c blocks. */ 258 | BlockNodeList *blocks; /**< The code to execute if a guard is true. */ 259 | } IfThenElseStmtNode; 260 | 261 | /** 262 | * Stores a switch statement. This statement compares the value of the \ref 263 | * impvar "implicit variable" to each of the \a guards and executes the 264 | * respective block of code in \a blocks if they match. If no matches are 265 | * found, the optional default block of code, \a def, is executed. 266 | */ 267 | typedef struct { 268 | ExprNodeList *guards; /**< The expressions to evaluate. */ 269 | BlockNodeList *blocks; /**< The blocks of code to execute. */ 270 | BlockNode *def; /**< An optional default block of code. */ 271 | } SwitchStmtNode; 272 | 273 | /** 274 | * Stores a return statement. This statement signals that control should be 275 | * returned to the caller with a status value. 276 | */ 277 | typedef struct { 278 | ExprNode *value; /**< The value to return. */ 279 | } ReturnStmtNode; 280 | 281 | /** 282 | * Stores a loop statement. This statement repeatedly executes its \a body 283 | * while \a guard evaluates to true, executing \a update at the end of each 284 | * cycle. 285 | */ 286 | typedef struct { 287 | IdentifierNode *name; /**< The name of the loop. */ 288 | IdentifierNode *var; /**< The variable to be updated. */ 289 | ExprNode *guard; /**< The expression to determine continuation. */ 290 | ExprNode *update; /**< The expression to update \a var with. */ 291 | BlockNode *body; /**< The code to execute at each iteration. */ 292 | } LoopStmtNode; 293 | 294 | /** 295 | * Stores a deallocation statement. This statement releases the resources used 296 | * by a variable. 297 | */ 298 | typedef struct { 299 | IdentifierNode *target; /**< The variable to deallocate. */ 300 | } DeallocationStmtNode; 301 | 302 | /** 303 | * Stores a cast expression. This expression evaluates an expression and casts 304 | * its value to a particular type. 305 | */ 306 | typedef struct { 307 | ExprNode *target; /**< The expression to cast. */ 308 | TypeNode *newtype; /**< The type to cast \a target to. */ 309 | } CastExprNode; 310 | 311 | /** 312 | * Stores a function call expression. This expression calls a named function 313 | * and evaluates to the return value of that function. 314 | */ 315 | typedef struct { 316 | IdentifierNode *scope; /**< The scope to call the function in. */ 317 | IdentifierNode *name; /**< The name of the function to call. */ 318 | ExprNodeList *args; /**< The arguments to supply the function. */ 319 | } FuncCallExprNode; 320 | 321 | /** 322 | * Represents the type of operation an OpExprNode performs. 323 | */ 324 | typedef enum { 325 | OP_ADD, /**< Addition. */ 326 | OP_SUB, /**< Subtraction. */ 327 | OP_MULT, /**< Multiplication. */ 328 | OP_DIV, /**< Division. */ 329 | OP_MOD, /**< Modulo. */ 330 | OP_MAX, /**< Maximum. */ 331 | OP_MIN, /**< Minimum. */ 332 | 333 | OP_AND, /**< Logical AND. */ 334 | OP_OR, /**< Logical OR. */ 335 | OP_XOR, /**< Logical XOR. */ 336 | OP_NOT, /**< Logical NOT. */ 337 | 338 | OP_EQ, /**< Equality. */ 339 | OP_NEQ, /**< Inequality. */ 340 | 341 | OP_CAT /**< String concatenation. */ 342 | } OpType; 343 | 344 | /** 345 | * Stores an operation expression. This expression applies an operator to its 346 | * arguments. 347 | */ 348 | typedef struct { 349 | OpType type; /**< The type of operation to perform. */ 350 | ExprNodeList *args; /**< The arguments to perform the operation on. */ 351 | } OpExprNode; 352 | 353 | /** 354 | * \name MainNode modifiers 355 | * 356 | * Functions for creating and deleting MainNodes. 357 | */ 358 | /**@{*/ 359 | MainNode *createMainNode(BlockNode *); 360 | void deleteMainNode(MainNode *); 361 | /**@}*/ 362 | 363 | /** 364 | * \name BlockNode modifiers 365 | * 366 | * Functions for creating and deleting single or multiple BlockNodes. 367 | */ 368 | /**@{*/ 369 | BlockNode *createBlockNode(StmtNodeList *); 370 | void deleteBlockNode(BlockNode *); 371 | BlockNodeList *createBlockNodeList(void); 372 | int addBlockNode(BlockNodeList *, BlockNode *); 373 | void deleteBlockNodeList(BlockNodeList *); 374 | /**@}*/ 375 | 376 | /** 377 | * \name IdentifierNode modifiers 378 | * 379 | * Functions for creating and deleting single or multiple IdentifierNodes. 380 | */ 381 | /**@{*/ 382 | IdentifierNode *createIdentifierNode(IdentifierType, void *, IdentifierNode *, const char *, unsigned int); 383 | void deleteIdentifierNode(IdentifierNode *); 384 | IdentifierNodeList *createIdentifierNodeList(void); 385 | int addIdentifierNode(IdentifierNodeList *, IdentifierNode *); 386 | void deleteIdentifierNodeList(IdentifierNodeList *); 387 | 388 | /**@}*/ 389 | 390 | /** 391 | * \name TypeNode modifiers 392 | * 393 | * Functions for creating and deleting TypeNodes. 394 | */ 395 | /**@{*/ 396 | TypeNode *createTypeNode(ConstantType); 397 | void deleteTypeNode(TypeNode *); 398 | /**@}*/ 399 | 400 | /** 401 | * \name StmtNode modifiers 402 | * 403 | * Functions for creating and deleting single or multiple of StmtNodes. 404 | */ 405 | /**@{*/ 406 | StmtNode *createStmtNode(StmtType, void *); 407 | void deleteStmtNode(StmtNode *); 408 | StmtNodeList *createStmtNodeList(void); 409 | int addStmtNode(StmtNodeList *, StmtNode *); 410 | void deleteStmtNodeList(StmtNodeList *); 411 | /**@}*/ 412 | 413 | /** 414 | * \name CastStmtNode modifiers 415 | * 416 | * Functions for creating and deleting CastStmtNodes. 417 | */ 418 | /**@{*/ 419 | CastStmtNode *createCastStmtNode(IdentifierNode *, TypeNode *); 420 | void deleteCastStmtNode(CastStmtNode *); 421 | /**@}*/ 422 | 423 | /** 424 | * \name PrintStmtNode modifiers 425 | * 426 | * Functions for creating and deleting PrintStmtNodes. 427 | */ 428 | /**@{*/ 429 | PrintStmtNode *createPrintStmtNode(ExprNodeList *, int); 430 | void deletePrintStmtNode(PrintStmtNode *); 431 | /**@}*/ 432 | 433 | /** 434 | * \name InputStmtNode modifiers 435 | * 436 | * Functions for creating and deleting InputStmtNodes. 437 | */ 438 | /**@{*/ 439 | InputStmtNode *createInputStmtNode(IdentifierNode *); 440 | void deleteInputStmtNode(InputStmtNode *); 441 | /**@}*/ 442 | 443 | /** 444 | * \name AssignmentStmtNode modifiers 445 | * 446 | * Functions for creating and deleting AssignmentStmtNodes. 447 | */ 448 | /**@{*/ 449 | AssignmentStmtNode *createAssignmentStmtNode(IdentifierNode *, ExprNode *); 450 | void deleteAssignmentStmtNode(AssignmentStmtNode *); 451 | /**@}*/ 452 | 453 | /** 454 | * \name DeclarationStmtNode modifiers 455 | * 456 | * Functions for creating and deleting DeclarationStmtNodes. 457 | */ 458 | /**@{*/ 459 | DeclarationStmtNode *createDeclarationStmtNode(IdentifierNode *, IdentifierNode *, ExprNode *, TypeNode *, IdentifierNode *); 460 | void deleteDeclarationStmtNode(DeclarationStmtNode *); 461 | /**@}*/ 462 | 463 | /** 464 | * \name IfThenElseStmtNode modifiers 465 | * 466 | * Functions for creating and deleting IfThenElseStmtNodes. 467 | */ 468 | /**@{*/ 469 | IfThenElseStmtNode *createIfThenElseStmtNode(BlockNode *, BlockNode *, ExprNodeList *, BlockNodeList *); 470 | void deleteIfThenElseStmtNode(IfThenElseStmtNode *); 471 | /**@}*/ 472 | 473 | /** 474 | * \name SwitchStmtNode modifiers 475 | * 476 | * Functions for creating and deleting SwitchStmtNodes. 477 | */ 478 | /**@{*/ 479 | SwitchStmtNode *createSwitchStmtNode(ExprNodeList *, BlockNodeList *, BlockNode *); 480 | void deleteSwitchStmtNode(SwitchStmtNode *); 481 | /**@}*/ 482 | 483 | /** 484 | * \name ReturnStmtNode modifiers 485 | * 486 | * Functions for creating and deleting ReturnStmtNodes. 487 | */ 488 | /**@{*/ 489 | ReturnStmtNode *createReturnStmtNode(ExprNode *); 490 | void deleteReturnStmtNode(ReturnStmtNode *); 491 | /**@}*/ 492 | 493 | /** 494 | * \name LoopStmtNode modifiers 495 | * 496 | * Functions for creating and deleting LoopStmtNodes. 497 | */ 498 | /**@{*/ 499 | LoopStmtNode *createLoopStmtNode(IdentifierNode *, IdentifierNode *, ExprNode *, ExprNode *, BlockNode *); 500 | void deleteLoopStmtNode(LoopStmtNode *); 501 | /**@}*/ 502 | 503 | /** 504 | * \name DeallocationStmtNode modifiers 505 | * 506 | * Functions for creating and deleting DeallocationStmtNodes. 507 | */ 508 | /**@{*/ 509 | DeallocationStmtNode *createDeallocationStmtNode(IdentifierNode *); 510 | void deleteDeallocationStmtNode(DeallocationStmtNode *); 511 | /**@}*/ 512 | 513 | /** 514 | * \name FuncDefStmtNode modifiers 515 | * 516 | * Functions for creating and deleting FuncDefStmtNodes. 517 | */ 518 | /**@{*/ 519 | FuncDefStmtNode *createFuncDefStmtNode(IdentifierNode *, IdentifierNode *, IdentifierNodeList *, BlockNode *); 520 | void deleteFuncDefStmtNode(FuncDefStmtNode *); 521 | /**@}*/ 522 | 523 | /** 524 | * \name AltArrayDefStmtNode modifiers 525 | * 526 | * Functions for creating and deleting AltArrayDefStmtNodes. 527 | */ 528 | /**@{*/ 529 | AltArrayDefStmtNode *createAltArrayDefStmtNode(IdentifierNode *, BlockNode *, IdentifierNode *); 530 | void deleteAltArrayDefStmtNode(AltArrayDefStmtNode *); 531 | /**@}*/ 532 | 533 | /** 534 | * \name ExprNode modifiers 535 | * 536 | * Functions for creating and deleting single or multiple ExprNodes. 537 | */ 538 | /**@{*/ 539 | ExprNode *createExprNode(ExprType, void *); 540 | void deleteExprNode(ExprNode *); 541 | ExprNodeList *createExprNodeList(void); 542 | int addExprNode(ExprNodeList *, ExprNode *); 543 | void deleteExprNodeList(ExprNodeList *); 544 | /**@}*/ 545 | 546 | /** 547 | * \name CastExprNode modifiers 548 | * 549 | * Functions for creating and deleting CastExprNodes. 550 | */ 551 | /**@{*/ 552 | CastExprNode *createCastExprNode(ExprNode *, TypeNode *); 553 | void deleteCastExprNode(CastExprNode *); 554 | /**@}*/ 555 | 556 | /** 557 | * \name FuncCallExprNode modifiers 558 | * 559 | * Functions for creating and deleting FuncCallExprNodes. 560 | */ 561 | /**@{*/ 562 | FuncCallExprNode *createFuncCallExprNode(IdentifierNode *, IdentifierNode *, ExprNodeList *); 563 | void deleteFuncCallExprNode(FuncCallExprNode *); 564 | /**@}*/ 565 | 566 | /** 567 | * \name OpExprNode modifiers 568 | * 569 | * Functions for creating and deleting OpExprNodes. 570 | */ 571 | /**@{*/ 572 | OpExprNode *createOpExprNode(OpType, ExprNodeList *); 573 | void deleteOpExprNode(OpExprNode *); 574 | /**@}*/ 575 | 576 | /** 577 | * \name Utilities 578 | * 579 | * Functions for performing helper tasks. 580 | */ 581 | /**@{*/ 582 | int acceptToken(Token ***, TokenType); 583 | int peekToken(Token ***, TokenType); 584 | int nextToken(Token ***, TokenType); 585 | /**@}*/ 586 | 587 | /** 588 | * \name Parsing functions 589 | * 590 | * Functions for parsing a stream of tokens. 591 | */ 592 | /**@{*/ 593 | ConstantNode *parseConstantNode(Token ***); 594 | TypeNode *parseTypeNode(Token ***); 595 | IdentifierNode *parseIdentifierNode(Token ***); 596 | ExprNode *parseExprNode(Token ***); 597 | StmtNode *parseStmtNode(Token ***); 598 | BlockNode *parseBlockNode(Token ***); 599 | MainNode *parseMainNode(Token **); 600 | ExprNode *parseCastExprNode(Token ***); 601 | ExprNode *parseConstantExprNode(Token ***); 602 | ExprNode *parseIdentifierExprNode(Token ***); 603 | ExprNode *parseFuncCallExprNode(Token ***); 604 | ExprNode *parseOpExprNode(Token ***); 605 | StmtNode *parseCastStmtNode(Token ***); 606 | StmtNode *parsePrintStmtNode(Token ***); 607 | StmtNode *parseInputStmtNode(Token ***); 608 | StmtNode *parseAssignmentStmtNode(Token ***); 609 | StmtNode *parseDeclarationStmtNode(Token ***); 610 | StmtNode *parseIfThenElseStmtNode(Token ***); 611 | StmtNode *parseSwitchStmtNode(Token ***); 612 | StmtNode *parseBreakStmtNode(Token ***); 613 | StmtNode *parseReturnStmtNode(Token ***); 614 | StmtNode *parseLoopStmtNode(Token ***); 615 | StmtNode *parseDeallocationStmtNode(Token ***); 616 | StmtNode *parseFuncDefStmtNode(Token ***); 617 | StmtNode *parseAltArrayDefStmtNode(Token ***); 618 | /**@}*/ 619 | 620 | /** 621 | * \name ConstantNode modifiers 622 | * 623 | * Functions for creating and deleting ConstantNode. 624 | */ 625 | /**@{*/ 626 | ConstantNode *createBooleanConstantNode(int); 627 | ConstantNode *createIntegerConstantNode(long long); 628 | ConstantNode *createFloatConstantNode(float); 629 | ConstantNode *createStringConstantNode(char *); 630 | void deleteConstantNode(ConstantNode *); 631 | /**@}*/ 632 | 633 | #endif /* __PARSER_H__ */ 634 | -------------------------------------------------------------------------------- /interpreter.c: -------------------------------------------------------------------------------- 1 | #include "interpreter.h" 2 | 3 | /** 4 | * Creates a new string by copying the contents of another string. 5 | * 6 | * \param [in] data The string to copy. 7 | * 8 | * \return A new string whose contents is a copy of \a data. 9 | * 10 | * \retval NULL Memory allocation failed. 11 | */ 12 | char *copyString(char *data) 13 | { 14 | char *p = malloc(sizeof(char) * (strlen(data) + 1)); 15 | if (!p) { 16 | perror("malloc"); 17 | return NULL; 18 | } 19 | strcpy(p, data); 20 | return p; 21 | } 22 | 23 | /** 24 | * Checks if a string follows the format of a decimal number. 25 | * 26 | * \param [in] data The string to check the format of. 27 | * 28 | * \retval 0 The string is not a decimal number. 29 | * 30 | * \retval 1 The string is a decimal number. 31 | */ 32 | unsigned int isDecString(const char *data) 33 | { 34 | size_t n; 35 | size_t len = strlen(data); 36 | 37 | /* Check for an empty string */ 38 | if (len == 0) return 0; 39 | 40 | /* Check for non-digit, non-hyphen, and non-period characters */ 41 | for (n = 0; n < len; n++) { 42 | if (!isdigit(data[n]) 43 | && data[n] != '.' 44 | && data[n] != '-') 45 | return 0; 46 | } 47 | 48 | return 1; 49 | } 50 | 51 | /** 52 | * Checks if a string follows the format of a hexadecimal number. 53 | * 54 | * \param [in] data The characters to check the format of. 55 | * 56 | * \retval 0 The string is not a hexadecimal number. 57 | * 58 | * \retval 1 The string is a hexadecimal number. 59 | */ 60 | unsigned int isHexString(const char *data) 61 | { 62 | size_t n; 63 | size_t len = strlen(data); 64 | 65 | /* Check for empty string */ 66 | if (len == 0) return 0; 67 | 68 | /* Check for non-digit and non-A-through-F characters */ 69 | for (n = 0; n < len; n++) { 70 | if (!isdigit(data[n]) 71 | && data[n] != 'A' 72 | && data[n] != 'B' 73 | && data[n] != 'C' 74 | && data[n] != 'D' 75 | && data[n] != 'E' 76 | && data[n] != 'F' 77 | && data[n] != 'a' 78 | && data[n] != 'b' 79 | && data[n] != 'c' 80 | && data[n] != 'd' 81 | && data[n] != 'e' 82 | && data[n] != 'f') 83 | return 0; 84 | } 85 | 86 | return 1; 87 | } 88 | 89 | /** 90 | * Evaluates an identifier to produce its name as a string. 91 | * 92 | * \param [in] id The identifier to evaluate. 93 | * 94 | * \param [in] scope The scope to evaluate \a id under. 95 | * 96 | * \return A new string containing the evaluated name of the identifier. 97 | * 98 | * \retval NULL Memory allocation failed. 99 | */ 100 | char *resolveIdentifierName(IdentifierNode *id, 101 | ScopeObject *scope) 102 | { 103 | ValueObject *val = NULL; 104 | ValueObject *str = NULL; 105 | char *ret = NULL; 106 | 107 | if (!id) goto resolveIdentifierNameAbort; 108 | 109 | if (id->type == IT_DIRECT) { 110 | /* Just return a copy of the character array */ 111 | const char *temp = (char *)(id->id); 112 | ret = malloc(sizeof(char) * (strlen(temp) + 1)); 113 | strcpy(ret, temp); 114 | } 115 | else if (id->type == IT_INDIRECT) { 116 | ExprNode *expr = (ExprNode *)(id->id); 117 | 118 | /* Interpret the identifier expression */ 119 | val = interpretExprNode(expr, scope); 120 | if (!val) goto resolveIdentifierNameAbort; 121 | 122 | /* Then cast it to a string */ 123 | str = castStringExplicit(val, scope); 124 | if (!str) goto resolveIdentifierNameAbort; 125 | deleteValueObject(val); 126 | 127 | /* Copy the evaluated string */ 128 | ret = copyString(getString(str)); 129 | if (!ret) goto resolveIdentifierNameAbort; 130 | deleteValueObject(str); 131 | } 132 | else { 133 | char *name = resolveIdentifierName(id, scope); 134 | error(IN_INVALID_IDENTIFIER_TYPE, id->fname, id->line, name); 135 | free(name); 136 | } 137 | 138 | return ret; 139 | 140 | resolveIdentifierNameAbort: /* Exception handline */ 141 | 142 | /* Clean up any allocated structures */ 143 | if (ret) free(ret); 144 | if (str) deleteValueObject(str); 145 | if (val) deleteValueObject(val); 146 | 147 | return NULL; 148 | } 149 | 150 | /** 151 | * Creates a nil-type value. 152 | * 153 | * \return A new nil-type value. 154 | * 155 | * \retval NULL Memory allocation failed. 156 | */ 157 | ValueObject *createNilValueObject(void) 158 | { 159 | ValueObject *p = malloc(sizeof(ValueObject)); 160 | if (!p) { 161 | perror("malloc"); 162 | return NULL; 163 | } 164 | p->type = VT_NIL; 165 | p->semaphore = 1; 166 | return p; 167 | } 168 | 169 | /** 170 | * Creates a boolean-type value. 171 | * 172 | * \param [in] data The boolean data to store. 173 | * 174 | * \return A boolean-type value equalling 0 if \a data equals 0 and 1 otherwise. 175 | * 176 | * \retval NULL Memory allocation failed. 177 | */ 178 | ValueObject *createBooleanValueObject(int data) 179 | { 180 | ValueObject *p = malloc(sizeof(ValueObject)); 181 | if (!p) { 182 | perror("malloc"); 183 | return NULL; 184 | } 185 | p->type = VT_BOOLEAN; 186 | p->data.i = (data != 0); 187 | p->semaphore = 1; 188 | return p; 189 | } 190 | 191 | /** 192 | * Creates a integer-type value. 193 | * 194 | * \param [in] data The integer data to store. 195 | * 196 | * \return An integer-type value equalling \a data. 197 | * 198 | * \retval NULL Memory allocation failed. 199 | */ 200 | ValueObject *createIntegerValueObject(long long data) 201 | { 202 | ValueObject *p = malloc(sizeof(ValueObject)); 203 | if (!p) { 204 | perror("malloc"); 205 | return NULL; 206 | } 207 | p->type = VT_INTEGER; 208 | p->data.i = data; 209 | p->semaphore = 1; 210 | return p; 211 | } 212 | 213 | /** 214 | * Creates a floating-point-type value. 215 | * 216 | * \param [in] data The floating-point data to store. 217 | * 218 | * \return A floating-point-type value equalling \a data. 219 | * 220 | * \retval NULL Memory allocation failed. 221 | */ 222 | ValueObject *createFloatValueObject(float data) 223 | { 224 | ValueObject *p = malloc(sizeof(ValueObject)); 225 | if (!p) { 226 | perror("malloc"); 227 | return NULL; 228 | } 229 | p->type = VT_FLOAT; 230 | p->data.f = data; 231 | p->semaphore = 1; 232 | return p; 233 | } 234 | 235 | /** 236 | * Creates a string-type value. 237 | * 238 | * \param [in] data The string data to store. 239 | * 240 | * \note \a data is stored as-is; no copy of it is made. 241 | * 242 | * \return A string-type value equalling \a data. 243 | * 244 | * \retval NULL Memory allocation failed. 245 | */ 246 | ValueObject *createStringValueObject(char *data) 247 | { 248 | ValueObject *p = malloc(sizeof(ValueObject)); 249 | if (!p) { 250 | perror("malloc"); 251 | return NULL; 252 | } 253 | p->type = VT_STRING; 254 | p->data.s = data; 255 | p->semaphore = 1; 256 | return p; 257 | } 258 | 259 | /** 260 | * Creates a function-type value. 261 | * 262 | * \param [in] def The function definition to store. 263 | * 264 | * \return A function-type value containing \a data. 265 | * 266 | * \retval NULL Memory allocation failed. 267 | */ 268 | ValueObject *createFunctionValueObject(FuncDefStmtNode *def) 269 | { 270 | ValueObject *p = malloc(sizeof(ValueObject)); 271 | if (!p) { 272 | perror("malloc"); 273 | return NULL; 274 | } 275 | p->type = VT_FUNC; 276 | p->data.fn = def; 277 | p->semaphore = 1; 278 | return p; 279 | } 280 | 281 | /** 282 | * Creates an array-type value. 283 | * 284 | * \param [in] parent The optional parent scope to use. 285 | * 286 | * \note \a parent may be NULL, in which case this array is treated as the root. 287 | * 288 | * \return An empty array-type value with parent \a parent. 289 | * 290 | * \retval NULL Memory allocation failed. 291 | */ 292 | ValueObject *createArrayValueObject(ScopeObject *parent) 293 | { 294 | ValueObject *p = malloc(sizeof(ValueObject)); 295 | if (!p) { 296 | perror("malloc"); 297 | return NULL; 298 | } 299 | p->type = VT_ARRAY; 300 | p->data.a = createScopeObject(parent); 301 | if (!p->data.a) { 302 | free(p); 303 | return NULL; 304 | } 305 | p->semaphore = 1; 306 | return p; 307 | } 308 | 309 | /** 310 | * Copies a value. 311 | * 312 | * Instead of actually performing a copy of memory, this function increments a 313 | * semaphore in \a value and returns \a value again. The semaphore gets 314 | * decremented when \a value gets deleted. This way, an immutable copy of a 315 | * value may be made without actually copying its blocks of memory; this reduces 316 | * the overhead associated with copying a value--a fairly common 317 | * operation--while still preserving its usability. 318 | * 319 | * \param [in,out] value The value to copy. 320 | * 321 | * \return A value with the same type and contents as \a value. 322 | * 323 | * \retval NULL The type of \a value is unrecognized. 324 | */ 325 | ValueObject *copyValueObject(ValueObject *value) 326 | { 327 | V(value); 328 | return value; 329 | } 330 | 331 | /** 332 | * Deletes a value. 333 | * 334 | * This function decrements a semaphore in \a value and deletes \a value if the 335 | * semaphore reaches 0 (no copies of this value are need anymore). The 336 | * semaphore gets incremented when either the value is created or it gets 337 | * copied. This way, an immutable copy of the value may be made without 338 | * actually copying its memory. 339 | * 340 | * \param [in,out] value The value to delete. 341 | * 342 | * \post The memory at \a value and any of its members will be freed (although 343 | * see note for full details). 344 | */ 345 | void deleteValueObject(ValueObject *value) 346 | { 347 | if (!value) return; 348 | P(value); 349 | if (!value->semaphore) { 350 | if (value->type == VT_STRING) 351 | free(value->data.s); 352 | /* FuncDefStmtNode structures get freed with the parse tree */ 353 | else if (value->type == VT_ARRAY) 354 | deleteScopeObject(value->data.a); 355 | free(value); 356 | } 357 | } 358 | 359 | /** 360 | * Creates a scope. 361 | * 362 | * Scopes are used to map identifiers to values. Scopes are organized 363 | * hierarchically. 364 | * 365 | * \param [in] parent The optional parent scope to use. 366 | * 367 | * \return An empty scope with parent \a parent. 368 | * 369 | * \retval NULL Memory allocation failed. 370 | */ 371 | ScopeObject *createScopeObject(ScopeObject *parent) 372 | { 373 | ScopeObject *p = malloc(sizeof(ScopeObject)); 374 | if (!p) { 375 | perror("malloc"); 376 | return NULL; 377 | } 378 | p->impvar = createNilValueObject(); 379 | if (!p->impvar) { 380 | free(p); 381 | return NULL; 382 | } 383 | p->numvals = 0; 384 | p->names = NULL; 385 | p->values = NULL; 386 | p->parent = parent; 387 | if (parent) p->caller = parent->caller; 388 | else p->caller = NULL; 389 | return p; 390 | } 391 | 392 | /** 393 | * Creates a scope with a specific caller. 394 | * 395 | * \param [in] parent The optional parent scope to use. 396 | * 397 | * \param [in] caller The caller scope to use. 398 | * 399 | * \return An empty scope with parent \a parent and caller \a caller. 400 | * 401 | * \retval NULL Memory allocation failed. 402 | */ 403 | ScopeObject *createScopeObjectCaller(ScopeObject *parent, 404 | ScopeObject *caller) 405 | { 406 | ScopeObject *p = createScopeObject(parent); 407 | if (!p) return NULL; 408 | if (caller) p->caller = caller; 409 | return p; 410 | } 411 | 412 | /** 413 | * Deletes a scope. 414 | * 415 | * \param [in,out] scope The scope to delete. 416 | * 417 | * \post The memory at \a scope and any of its members will be freed. 418 | */ 419 | void deleteScopeObject(ScopeObject *scope) 420 | { 421 | unsigned int n; 422 | if (!scope) return; 423 | for (n = 0; n < scope->numvals; n++) { 424 | free(scope->names[n]); 425 | deleteValueObject(scope->values[n]); 426 | } 427 | free(scope->names); 428 | free(scope->values); 429 | deleteValueObject(scope->impvar); 430 | free(scope); 431 | } 432 | 433 | /** 434 | * Creates a new, nil-type value in a scope. 435 | * 436 | * \param [in] src The scope to evaluate \a target under. 437 | * 438 | * \param [in,out] dest The scope to create the new value in. 439 | * 440 | * \param [in] target The name of the value to create. 441 | * 442 | * \return The newly-created value. 443 | * 444 | * \retval NULL Memory allocation failed. 445 | */ 446 | ValueObject *createScopeValue(ScopeObject *src, 447 | ScopeObject *dest, 448 | IdentifierNode *target) 449 | { 450 | ScopeObject *parent = dest; 451 | IdentifierNode *child = target; 452 | int status; 453 | unsigned int newnumvals; 454 | void *mem1 = NULL; 455 | void *mem2 = NULL; 456 | char *name = NULL; 457 | 458 | /* Traverse the target to the terminal child and parent */ 459 | status = resolveTerminalSlot(src, dest, target, &parent, &child); 460 | if (!status) goto createScopeValueAbort; 461 | 462 | /* Store the new number of values */ 463 | newnumvals = dest->numvals + 1; 464 | 465 | /* Look up the identifier name */ 466 | name = resolveIdentifierName(target, src); 467 | if (!name) goto createScopeValueAbort; 468 | 469 | /* Add value to local scope */ 470 | mem1 = realloc(dest->names, sizeof(IdentifierNode *) * newnumvals); 471 | if (!mem1) { 472 | perror("realloc"); 473 | goto createScopeValueAbort; 474 | } 475 | mem2 = realloc(dest->values, sizeof(ValueObject *) * newnumvals); 476 | if (!mem2) { 477 | perror("realloc"); 478 | goto createScopeValueAbort; 479 | } 480 | 481 | dest->names = mem1; 482 | dest->values = mem2; 483 | dest->names[dest->numvals] = name; 484 | dest->values[dest->numvals] = createNilValueObject(); 485 | if (!dest->values[dest->numvals]) goto createScopeValueAbort; 486 | dest->numvals = newnumvals; 487 | 488 | return dest->values[dest->numvals - 1]; 489 | 490 | createScopeValueAbort: /* In case something goes wrong... */ 491 | 492 | /* Clean up any allocated structures */ 493 | if (name) free(name); 494 | if (mem1) free(mem1); 495 | if (mem2) free(mem2); 496 | 497 | return NULL; 498 | } 499 | 500 | /** 501 | * Updates a value in a scope. 502 | * 503 | * \param [in] src The scope to evaluate \a target under. 504 | * 505 | * \param [in,out] dest The scope to update the value in. 506 | * 507 | * \param [in] target The name of the value to create. 508 | * 509 | * \param [in] value The new value to assign. 510 | * 511 | * \return The updated value (will be the same as \a val). 512 | * 513 | * \retval NULL Either \a target could not be evaluated in \a src or \a target 514 | * could not be found in \a dest. 515 | */ 516 | ValueObject *updateScopeValue(ScopeObject *src, 517 | ScopeObject *dest, 518 | IdentifierNode *target, 519 | ValueObject *value) 520 | { 521 | ScopeObject *parent = dest; 522 | IdentifierNode *child = target; 523 | int status; 524 | char *name = NULL; 525 | 526 | /* Traverse the target to the terminal child and parent */ 527 | status = resolveTerminalSlot(src, dest, target, &parent, &child); 528 | if (!status) goto updateScopeValueAbort; 529 | 530 | /* Look up the identifier name */ 531 | name = resolveIdentifierName(child, src); 532 | if (!name) goto updateScopeValueAbort; 533 | 534 | /* Traverse upwards through scopes */ 535 | do { 536 | unsigned int n; 537 | /* Check for existing value in current scope */ 538 | for (n = 0; n < parent->numvals; n++) { 539 | if (!strcmp(parent->names[n], name)) { 540 | free(name); 541 | /* Wipe out the old value */ 542 | deleteValueObject(parent->values[n]); 543 | /* Assign the new value */ 544 | if (value) { 545 | parent->values[n] = value; 546 | } 547 | else { 548 | parent->values[n] = createNilValueObject(); 549 | } 550 | return parent->values[n]; 551 | } 552 | } 553 | } while ((parent = parent->parent)); 554 | 555 | { 556 | char *name = resolveIdentifierName(target, src); 557 | error(IN_UNABLE_TO_STORE_VARIABLE, target->fname, target->line, name); 558 | free(name); 559 | } 560 | 561 | updateScopeValueAbort: /* In case something goes wrong... */ 562 | 563 | /* Clean up any allocated structures */ 564 | if (name) free(name); 565 | 566 | return NULL; 567 | } 568 | 569 | /** 570 | * Gets a stored value in a scope. 571 | * 572 | * \param [in] src The scope to evaluate \a target under. 573 | * 574 | * \param [in,out] dest The scope to update the value in. 575 | * 576 | * \param [in] target The name of the value to get. 577 | * 578 | * \return The value in \a dest, named by evaluating \a target under \a src. 579 | * 580 | * \retval NULL Either \a target could not be evaluated in \a src or \a target 581 | * could not be found in \a dest. 582 | */ 583 | ValueObject *getScopeValue(ScopeObject *src, 584 | ScopeObject *dest, 585 | IdentifierNode *target) 586 | { 587 | ScopeObject *parent = dest; 588 | IdentifierNode *child = target; 589 | char *name = NULL; 590 | int status; 591 | 592 | /* Traverse the target to the terminal child and parent */ 593 | status = resolveTerminalSlot(src, dest, target, &parent, &child); 594 | if (!status) goto getScopeValueAbort; 595 | 596 | /* Look up the identifier name */ 597 | name = resolveIdentifierName(child, src); 598 | if (!name) goto getScopeValueAbort; 599 | 600 | /* Traverse upwards through scopes */ 601 | do { 602 | unsigned int n; 603 | /* Check for value in current scope */ 604 | for (n = 0; n < parent->numvals; n++) { 605 | if (!strcmp(parent->names[n], name)) { 606 | free(name); 607 | return parent->values[n]; 608 | } 609 | } 610 | } while ((parent = parent->parent)); 611 | 612 | { 613 | char *name = resolveIdentifierName(child, src); 614 | error(IN_VARIABLE_DOES_NOT_EXIST, child->fname, child->line, name); 615 | free(name); 616 | } 617 | 618 | getScopeValueAbort: /* In case something goes wrong... */ 619 | 620 | /* Clean up any allocated structures */ 621 | if (name) free(name); 622 | 623 | return NULL; 624 | } 625 | 626 | /** 627 | * Gets a scope without accessing any arrays. 628 | * 629 | * \param [in] src The scope to evaluate \a target under. 630 | * 631 | * \param [in,out] dest The scope to update the value in. 632 | * 633 | * \param [in] target The name of the value containing the scope to get. 634 | * 635 | * \return The scope contained in the value in \a dest, named by evaluating \a 636 | * target under \a src, without accessing any arrays. 637 | * 638 | * \retval NULL Either \a target could not be evaluated in \a src or \a target 639 | * could not be found in \a dest. 640 | */ 641 | /** \todo Add this definition to interpreter.h */ 642 | ScopeObject *getScopeObjectLocal(ScopeObject *src, 643 | ScopeObject *dest, 644 | IdentifierNode *target) 645 | { 646 | ScopeObject *current = dest; 647 | char *name = NULL; 648 | 649 | /* Look up the identifier name */ 650 | name = resolveIdentifierName(target, src); 651 | if (!name) goto getScopeObjectLocalAbort; 652 | 653 | /* Check for calling object reference variable */ 654 | if (!strcmp(name, "ME")) { 655 | /* Traverse upwards through callers */ 656 | for (current = dest; 657 | current->caller; 658 | current = current->caller); 659 | free(name); 660 | return current; 661 | } 662 | 663 | /* Traverse upwards through scopes */ 664 | do { 665 | unsigned int n; 666 | /* Check for value in current scope */ 667 | for (n = 0; n < current->numvals; n++) { 668 | if (!strcmp(current->names[n], name)) { 669 | free(name); 670 | return getArray(current->values[n]); 671 | } 672 | } 673 | } while ((current = current->parent)); 674 | 675 | { 676 | char *name = resolveIdentifierName(target, src); 677 | error(IN_VARIABLE_DOES_NOT_EXIST, target->fname, target->line, name); 678 | free(name); 679 | } 680 | 681 | getScopeObjectLocalAbort: /* In case something goes wrong... */ 682 | 683 | /* Clean up any allocated structures */ 684 | if (name) free(name); 685 | 686 | return NULL; 687 | } 688 | 689 | /** 690 | * Gets a value from a scope without accessing its ancestors. 691 | * 692 | * \param [in] src The scope to evaluate \a target under. 693 | * 694 | * \param [in,out] dest The scope to update the value in. 695 | * 696 | * \param [in] target The name of the value to get. 697 | * 698 | * \return The value in \a dest, named by evaluating \a target under \a src, 699 | * without accessing any ancestors of \a dest. 700 | * 701 | * \retval NULL Either \a target could not be evaluated in \a src or \a target 702 | * could not be found in \a dest. 703 | */ 704 | ValueObject *getScopeValueLocal(ScopeObject *src, 705 | ScopeObject *dest, 706 | IdentifierNode *target) 707 | { 708 | unsigned int n; 709 | char *name = NULL; 710 | ScopeObject *scope = NULL; 711 | 712 | /* Access any slots */ 713 | while (target->slot) { 714 | /* 715 | * Look up the target in the dest scope, using the src scope 716 | * for resolving variables in indirect identifiers 717 | */ 718 | scope = getScopeObjectLocal(src, dest, target); 719 | if (!scope) return 0; 720 | dest = scope; 721 | 722 | target = target->slot; 723 | } 724 | 725 | /* Look up the identifier name */ 726 | name = resolveIdentifierName(target, src); 727 | if (!name) goto getScopeValueLocalAbort; 728 | 729 | /* Check for value in current scope */ 730 | for (n = 0; n < dest->numvals; n++) { 731 | if (!strcmp(dest->names[n], name)) { 732 | free(name); 733 | return dest->values[n]; 734 | } 735 | } 736 | 737 | getScopeValueLocalAbort: /* In case something goes wrong... */ 738 | 739 | /* Clean up any allocated structures */ 740 | if (name) free(name); 741 | 742 | return NULL; 743 | } 744 | 745 | /** 746 | * Gets a scope from within another scope. 747 | * 748 | * \param [in] src The scope to evaluate \a target under. 749 | * 750 | * \param [in,out] dest The scope to update the value in. 751 | * 752 | * \param [in] target The name of the scope to get. 753 | * 754 | * \return The value in \a dest, named by evaluating \a target under \a src, 755 | * without accessing any ancestors of \a dest. 756 | * 757 | * \retval NULL Either \a target could not be evaluated in \a src or \a target 758 | * could not be found in \a dest. 759 | */ 760 | ScopeObject *getScopeObject(ScopeObject *src, 761 | ScopeObject *dest, 762 | IdentifierNode *target) 763 | { 764 | ValueObject *val = NULL; 765 | char *name = NULL; 766 | int status; 767 | int isI; 768 | int isME; 769 | ScopeObject *scope; 770 | 771 | /* Look up the identifier name */ 772 | name = resolveIdentifierName(target, src); 773 | if (!name) goto getScopeObjectAbort; 774 | 775 | /* Check for targets with special meanings */ 776 | isI = strcmp(name, "I"); 777 | isME = strcmp(name, "ME"); 778 | free(name); 779 | name = NULL; 780 | 781 | if (!isI) { 782 | /* The function scope variable */ 783 | return src; 784 | } 785 | else if (!isME) { 786 | /* The calling object scope variable */ 787 | scope = getScopeObjectLocal(src, dest, target); 788 | if (!scope) goto getScopeObjectAbort; 789 | return scope; 790 | } 791 | 792 | /* Access any slots */ 793 | while (target->slot) { 794 | /* 795 | * Look up the target in the dest scope, using the src scope 796 | * for resolving variables in indirect identifiers 797 | */ 798 | scope = getScopeObjectLocal(src, dest, target); 799 | if (!scope) goto getScopeObjectAbort; 800 | dest = scope; 801 | 802 | target = target->slot; 803 | } 804 | 805 | val = getScopeValue(src, dest, target); 806 | if (!val) goto getScopeObjectAbort; 807 | if (val->type != VT_ARRAY) { 808 | char *name = resolveIdentifierName(target, src); 809 | error(IN_VARIABLE_NOT_AN_ARRAY, target->fname, target->line, name); 810 | free(name); 811 | goto getScopeObjectAbort; 812 | } 813 | 814 | return getArray(val); 815 | 816 | getScopeObjectAbort: /* In case something goes wrong... */ 817 | 818 | /* Clean up any allocated structures */ 819 | if (name) free(name); 820 | 821 | return NULL; 822 | } 823 | 824 | /** 825 | * Deletes a value from a scope. 826 | * 827 | * \param [in] src The scope to evaluate \a target under. 828 | * 829 | * \param [in,out] dest The scope to update the value in. 830 | * 831 | * \param [in] target The name of the value to delete. 832 | */ 833 | void deleteScopeValue(ScopeObject *src, 834 | ScopeObject *dest, 835 | IdentifierNode *target) 836 | { 837 | ScopeObject *current = NULL; 838 | char *name = NULL; 839 | void *mem1 = NULL; 840 | void *mem2 = NULL; 841 | ScopeObject *scope = NULL; 842 | 843 | /* Access any slots */ 844 | while (target->slot) { 845 | /* 846 | * Look up the target in the dest scope, using the src scope 847 | * for resolving variables in indirect identifiers 848 | */ 849 | scope = getScopeObjectLocal(src, dest, target); 850 | if (!scope) goto deleteScopeValueAbort; 851 | dest = scope; 852 | target = target->slot; 853 | } 854 | current = dest; 855 | 856 | /* Look up the identifier name */ 857 | name = resolveIdentifierName(target, src); 858 | if (!name) goto deleteScopeValueAbort; 859 | 860 | /* Traverse upwards through scopes */ 861 | do { 862 | unsigned int n; 863 | /* Check for existing value in current scope */ 864 | for (n = 0; n < current->numvals; n++) { 865 | if (!strcmp(current->names[n], name)) { 866 | unsigned int i; 867 | unsigned int newnumvals = dest->numvals - 1; 868 | free(name); 869 | /* Wipe out the name and value */ 870 | free(current->names[n]); 871 | deleteValueObject(current->values[n]); 872 | /* Reorder the tables */ 873 | for (i = n; i < current->numvals - 1; i++) { 874 | current->names[i] = current->names[i + 1]; 875 | current->values[i] = current->values[i + 1]; 876 | } 877 | /* Resize the tables */ 878 | mem1 = realloc(dest->names, sizeof(IdentifierNode *) * newnumvals); 879 | if (!mem1) { 880 | perror("realloc"); 881 | goto deleteScopeValueAbort; 882 | } 883 | mem2 = realloc(dest->values, sizeof(ValueObject *) * newnumvals); 884 | if (!mem2) { 885 | perror("realloc"); 886 | goto deleteScopeValueAbort; 887 | } 888 | dest->names = mem1; 889 | dest->values = mem2; 890 | dest->numvals = newnumvals; 891 | return; 892 | } 893 | } 894 | } while ((current = current->parent)); 895 | 896 | free(name); 897 | 898 | return; 899 | 900 | deleteScopeValueAbort: /* In case something goes wrong... */ 901 | 902 | /* Clean up any allocated structures */ 903 | if (name) free(name); 904 | if (mem1) free(mem1); 905 | if (mem2) free(mem2); 906 | if (scope) free(scope); 907 | 908 | return; 909 | } 910 | 911 | /** 912 | * Creates a returned value. 913 | * 914 | * \param [in] type The type of returned value. 915 | * 916 | * \param [in] value An optional value to return. 917 | * 918 | * \return A pointer to a returned value with the desired properties. 919 | * 920 | * \retval NULL Memory allocation failed. 921 | */ 922 | ReturnObject *createReturnObject(ReturnType type, 923 | ValueObject *value) 924 | { 925 | ReturnObject *p = malloc(sizeof(ReturnObject)); 926 | if (!p) { 927 | perror("malloc"); 928 | return NULL; 929 | } 930 | p->type = type; 931 | p->value = value; 932 | return p; 933 | } 934 | 935 | /** 936 | * Deletes a returned value. 937 | * 938 | * \param [in,out] object The returned value to be deleted. 939 | * 940 | * \post The memory at \a object and all of its members will be freed. 941 | */ 942 | void deleteReturnObject(ReturnObject *object) 943 | { 944 | if (!object) return; 945 | if (object->type == RT_RETURN) 946 | deleteValueObject(object->value); 947 | free(object); 948 | } 949 | 950 | /** 951 | * Starting from an initial parent scope and target identifier, traverses down 952 | * until the target identifier is not a scope. Stores the value of the terminal 953 | * child identifier and its parent scope. 954 | * 955 | * \param [in] src The scope to resolve \a target in. 956 | * 957 | * \param [in] dest The scope to retrieve \a target from. 958 | * 959 | * \param [in] target The array slot to traverse. 960 | * 961 | * \param [out] parent The parent of the terminal child identifier of \a target. 962 | * 963 | * \param [out] child The terminal child identifier of \a target. 964 | * 965 | * \return A status code indicating success or failure. 966 | * 967 | * \retval 0 Failed to traverse array. 968 | * 969 | * \retval 1 Succeeded to traverse array. 970 | * 971 | * \post \a parent will point to the parent scope containing the terminal child. 972 | * 973 | * \post \a child will point to the terminal child. 974 | */ 975 | int resolveTerminalSlot(ScopeObject *src, 976 | ScopeObject *dest, 977 | IdentifierNode *target, 978 | ScopeObject **parent, 979 | IdentifierNode **child) 980 | { 981 | ScopeObject *scope = NULL; 982 | 983 | /* Start with default values */ 984 | *parent = dest; 985 | *child = target; 986 | 987 | /* Access any slots */ 988 | while (target->slot) { 989 | /* 990 | * Look up the target in the dest scope, using the src scope 991 | * for resolving variables in indirect identifiers 992 | */ 993 | scope = getScopeObjectLocal(src, dest, target); 994 | if (!scope) goto resolveTerminalSlotAbort; 995 | dest = scope; 996 | 997 | /* Change the target to the old target's slot */ 998 | target = target->slot; 999 | } 1000 | 1001 | /* Store the output values */ 1002 | *parent = dest; 1003 | *child = target; 1004 | 1005 | return 1; 1006 | 1007 | resolveTerminalSlotAbort: /* In case something goes wrong... */ 1008 | 1009 | /* Clean up any allocated structures */ 1010 | if (scope) deleteScopeObject(scope); 1011 | 1012 | return 0; 1013 | } 1014 | 1015 | /** 1016 | * Casts the contents of a value to boolean type in an implicit way. Casting is 1017 | * not done directly to \a node, instead, it is performed on a copy which is 1018 | * what is returned. 1019 | * 1020 | * \param [in] node The value to cast. 1021 | * 1022 | * \param [in] scope The scope to use for variable interpolation. 1023 | * 1024 | * \return A pointer to a value with a copy of the contents of \a node, cast to 1025 | * boolean type. 1026 | * 1027 | * \retval NULL An error occurred while casting. 1028 | */ 1029 | ValueObject *castBooleanImplicit(ValueObject *node, 1030 | ScopeObject *scope) 1031 | { 1032 | if (!node) return NULL; 1033 | return castBooleanExplicit(node, scope); 1034 | } 1035 | 1036 | /** 1037 | * Casts the contents of a value to integer type in an implicit way. Casting is 1038 | * not done directly to \a node, instead, it is performed on a copy which is 1039 | * what is returned. 1040 | * 1041 | * \param [in] node The value to cast. 1042 | * 1043 | * \param [in] scope The scope to use for variable interpolation. 1044 | * 1045 | * \return A pointer to a value with a copy of the contents of \a node, cast to 1046 | * integer type. 1047 | * 1048 | * \retval NULL An error occurred while casting. 1049 | */ 1050 | ValueObject *castIntegerImplicit(ValueObject *node, 1051 | ScopeObject *scope) 1052 | { 1053 | if (!node) return NULL; 1054 | if (node->type == VT_NIL) { 1055 | error(IN_CANNOT_IMPLICITLY_CAST_NIL); 1056 | return NULL; 1057 | } 1058 | else return castIntegerExplicit(node, scope); 1059 | } 1060 | 1061 | /** 1062 | * Casts the contents of a value to decimal type in an implicit way. Casting is 1063 | * not done directly to \a node, instead, it is performed on a copy which is 1064 | * what is returned. 1065 | * 1066 | * \param [in] node The value to cast. 1067 | * 1068 | * \param [in] scope The scope to use for variable interpolation. 1069 | * 1070 | * \return A pointer to a value with a copy of the contents of \a node, cast to 1071 | * decimal type. 1072 | * 1073 | * \retval NULL An error occurred while casting. 1074 | */ 1075 | ValueObject *castFloatImplicit(ValueObject *node, 1076 | ScopeObject *scope) 1077 | { 1078 | if (!node) return NULL; 1079 | if (node->type == VT_NIL) { 1080 | error(IN_CANNOT_IMPLICITLY_CAST_NIL); 1081 | return NULL; 1082 | } 1083 | else return castFloatExplicit(node, scope); 1084 | } 1085 | 1086 | /** 1087 | * Casts the contents of a value to string type in an implicit way. Casting is 1088 | * not done directly to \a node, instead, it is performed on a copy which is 1089 | * what is returned. 1090 | * 1091 | * \param [in] node The value to cast. 1092 | * 1093 | * \param [in] scope The scope to use for variable interpolation. 1094 | * 1095 | * \note \a scope is used to resolve variable interpolation within the string 1096 | * before casting it. Therefore, a simple way to interpolate the variables 1097 | * within a string is to call this function with it. 1098 | * 1099 | * \return A pointer to a value with a copy of the contents of \a node, cast to 1100 | * string type. 1101 | * 1102 | * \retval NULL An error occurred while casting. 1103 | */ 1104 | ValueObject *castStringImplicit(ValueObject *node, 1105 | ScopeObject *scope) 1106 | { 1107 | if (!node) return NULL; 1108 | if (node->type == VT_NIL) { 1109 | error(IN_CANNOT_IMPLICITLY_CAST_NIL); 1110 | return NULL; 1111 | } 1112 | else return castStringExplicit(node, scope); 1113 | } 1114 | 1115 | /** 1116 | * Casts the contents of a value to boolean type in an explicit way. Casting is 1117 | * not done directly to \a node, instead, it is performed on a copy which is 1118 | * what is returned. 1119 | * 1120 | * \param [in] node The value to cast. 1121 | * 1122 | * \param [in] scope The scope to use for variable interpolation. 1123 | * 1124 | * \return A pointer to a value with a copy of the contents of \a node, cast to 1125 | * boolean type. 1126 | * 1127 | * \retval NULL An error occurred while casting. 1128 | */ 1129 | ValueObject *castBooleanExplicit(ValueObject *node, 1130 | ScopeObject *scope) 1131 | { 1132 | if (!node) return NULL; 1133 | switch (node->type) { 1134 | case VT_NIL: 1135 | return createBooleanValueObject(0); 1136 | case VT_BOOLEAN: 1137 | return createBooleanValueObject(getInteger(node)); 1138 | case VT_INTEGER: 1139 | return createBooleanValueObject(getInteger(node) != 0); 1140 | case VT_FLOAT: 1141 | return createBooleanValueObject(fabs(getFloat(node) - 0.0) > FLT_EPSILON); 1142 | case VT_STRING: 1143 | if (strstr(getString(node), ":{")) { 1144 | /* Perform interpolation */ 1145 | ValueObject *ret = NULL; 1146 | ValueObject *interp = castStringExplicit(node, scope); 1147 | if (!interp) return NULL; 1148 | ret = createBooleanValueObject(getString(interp)[0] != '\0'); 1149 | deleteValueObject(interp); 1150 | return ret; 1151 | } 1152 | else 1153 | return createBooleanValueObject(getString(node)[0] != '\0'); 1154 | case VT_FUNC: 1155 | error(IN_CANNOT_CAST_FUNCTION_TO_BOOLEAN); 1156 | return NULL; 1157 | case VT_ARRAY: 1158 | error(IN_CANNOT_CAST_ARRAY_TO_BOOLEAN); 1159 | return NULL; 1160 | default: 1161 | error(IN_UNKNOWN_VALUE_DURING_BOOLEAN_CAST); 1162 | return NULL; 1163 | } 1164 | } 1165 | 1166 | /** 1167 | * Casts the contents of a value to integer type in an explicit way. Casting is 1168 | * not done directly to \a node, instead, it is performed on a copy which is 1169 | * what is returned. 1170 | * 1171 | * \param [in] node The value to cast. 1172 | * 1173 | * \param [in] scope The scope to use for variable interpolation. 1174 | * 1175 | * \return A pointer to a value with a copy of the contents of \a node, cast to 1176 | * integer type. 1177 | * 1178 | * \retval NULL An error occurred while casting. 1179 | */ 1180 | ValueObject *castIntegerExplicit(ValueObject *node, 1181 | ScopeObject *scope) 1182 | { 1183 | if (!node) return NULL; 1184 | switch (node->type) { 1185 | case VT_NIL: 1186 | return createIntegerValueObject(0); 1187 | case VT_BOOLEAN: 1188 | case VT_INTEGER: 1189 | return createIntegerValueObject(getInteger(node)); 1190 | case VT_FLOAT: 1191 | return createIntegerValueObject((long long)getFloat(node)); 1192 | case VT_STRING: 1193 | if (strstr(getString(node), ":{")) { 1194 | /* Perform interpolation */ 1195 | ValueObject *ret = NULL; 1196 | ValueObject *interp = castStringExplicit(node, scope); 1197 | long long value; 1198 | if (!interp) return NULL; 1199 | if (!isDecString(getString(interp))) { 1200 | error(IN_UNABLE_TO_CAST_VALUE); 1201 | deleteValueObject(interp); 1202 | return NULL; 1203 | } 1204 | if (sscanf(getString(interp), "%lli", &value) != 1) { 1205 | error(IN_EXPECTED_INTEGER_VALUE); 1206 | deleteValueObject(interp); 1207 | return NULL; 1208 | } 1209 | ret = createIntegerValueObject(value); 1210 | deleteValueObject(interp); 1211 | return ret; 1212 | } 1213 | else { 1214 | long long value; 1215 | if (!isDecString(getString(node))) { 1216 | error(IN_UNABLE_TO_CAST_VALUE); 1217 | return NULL; 1218 | } 1219 | if (sscanf(getString(node), "%lli", &value) != 1) { 1220 | error(IN_EXPECTED_INTEGER_VALUE); 1221 | return NULL; 1222 | } 1223 | return createIntegerValueObject(value); 1224 | } 1225 | case VT_FUNC: 1226 | error(IN_CANNOT_CAST_FUNCTION_TO_INTEGER); 1227 | return NULL; 1228 | case VT_ARRAY: 1229 | error(IN_CANNOT_CAST_ARRAY_TO_INTEGER); 1230 | return NULL; 1231 | default: 1232 | error(IN_UNKNOWN_VALUE_DURING_INTEGER_CAST); 1233 | return NULL; 1234 | } 1235 | } 1236 | 1237 | /** 1238 | * Casts the contents of a value to decimal type in an explicit way. Casting is 1239 | * not done directly to \a node, instead, it is performed on a copy which is 1240 | * what is returned. 1241 | * 1242 | * \param [in] node The value to cast. 1243 | * 1244 | * \param [in] scope The scope to use for variable interpolation. 1245 | * 1246 | * \return A pointer to a value with a copy of the contents of \a node, cast to 1247 | * decimal type. 1248 | * 1249 | * \retval NULL An error occurred while casting. 1250 | */ 1251 | ValueObject *castFloatExplicit(ValueObject *node, 1252 | ScopeObject *scope) 1253 | { 1254 | if (!node) return NULL; 1255 | switch (node->type) { 1256 | case VT_NIL: 1257 | return createFloatValueObject(0.0); 1258 | case VT_BOOLEAN: 1259 | case VT_INTEGER: 1260 | return createFloatValueObject((float)getInteger(node)); 1261 | case VT_FLOAT: 1262 | return createFloatValueObject(getFloat(node)); 1263 | case VT_STRING: 1264 | if (strstr(getString(node), ":{")) { 1265 | /* Perform interpolation */ 1266 | ValueObject *ret = NULL; 1267 | ValueObject *interp = castStringExplicit(node, scope); 1268 | float value; 1269 | if (!interp) return NULL; 1270 | if (!isDecString(getString(interp))) { 1271 | error(IN_UNABLE_TO_CAST_VALUE); 1272 | deleteValueObject(interp); 1273 | return NULL; 1274 | } 1275 | if (sscanf(getString(interp), "%f", &value) != 1) { 1276 | error(IN_EXPECTED_DECIMAL); 1277 | deleteValueObject(interp); 1278 | return NULL; 1279 | } 1280 | ret = createFloatValueObject(value); 1281 | deleteValueObject(interp); 1282 | return ret; 1283 | } 1284 | else { 1285 | float value; 1286 | if (!isDecString(getString(node))) { 1287 | error(IN_UNABLE_TO_CAST_VALUE); 1288 | return NULL; 1289 | } 1290 | if (sscanf(getString(node), "%f", &value) != 1) { 1291 | error(IN_EXPECTED_DECIMAL); 1292 | return NULL; 1293 | } 1294 | return createFloatValueObject(value); 1295 | } 1296 | case VT_FUNC: 1297 | error(IN_CANNOT_CAST_FUNCTION_TO_DECIMAL); 1298 | return NULL; 1299 | case VT_ARRAY: 1300 | error(IN_CANNOT_CAST_ARRAY_TO_DECIMAL); 1301 | return NULL; 1302 | default: 1303 | error(IN_UNKNOWN_VALUE_DURING_DECIMAL_CAST); 1304 | return NULL; 1305 | } 1306 | } 1307 | 1308 | /** 1309 | * Casts the contents of a value to string type in an explicit way. Casting is 1310 | * not done directly to \a node, instead, it is performed on a copy which is 1311 | * what is returned. 1312 | * 1313 | * \param [in] node The value to cast. 1314 | * 1315 | * \param [in] scope The scope to use for variable interpolation. 1316 | * 1317 | * \note \a scope is used to resolve variable interpolation within the string 1318 | * before casting it. Therefore, a simple way to interpolate the variables 1319 | * within a string is to call this function with it. 1320 | * 1321 | * \return A pointer to a value with a copy of the contents of \a node, cast to 1322 | * string type. 1323 | * 1324 | * \retval NULL An error occurred while casting. 1325 | */ 1326 | ValueObject *castStringExplicit(ValueObject *node, 1327 | ScopeObject *scope) 1328 | { 1329 | if (!node) return NULL; 1330 | switch (node->type) { 1331 | case VT_NIL: { 1332 | char *str = copyString(""); 1333 | if (!str) return NULL; 1334 | return createStringValueObject(str); 1335 | } 1336 | case VT_BOOLEAN: { 1337 | /* 1338 | * \note The spec does not define how TROOFs may be cast 1339 | * to YARNs. 1340 | */ 1341 | error(IN_CANNOT_CAST_BOOLEAN_TO_STRING); 1342 | return NULL; 1343 | } 1344 | case VT_INTEGER: { 1345 | char *data = NULL; 1346 | /* 1347 | * One character per integer bit plus one more for the 1348 | * null character 1349 | */ 1350 | size_t size = sizeof(long long) * 8 + 1; 1351 | data = malloc(sizeof(char) * size); 1352 | if (!data) return NULL; 1353 | sprintf(data, "%lli", getInteger(node)); 1354 | return createStringValueObject(data); 1355 | } 1356 | case VT_FLOAT: { 1357 | char *data = NULL; 1358 | unsigned int precision = 2; 1359 | /* 1360 | * One character per float bit plus one more for the 1361 | * null character 1362 | */ 1363 | size_t size = sizeof(float) * 8 + 1; 1364 | data = malloc(sizeof(char) * size); 1365 | if (!data) return NULL; 1366 | sprintf(data, "%f", getFloat(node)); 1367 | /* Truncate to a certain number of decimal places */ 1368 | strchr(data, '.')[precision + 1] = '\0'; 1369 | return createStringValueObject(data); 1370 | } 1371 | case VT_STRING: { 1372 | char *temp = NULL; 1373 | char *data = NULL; 1374 | char *str = getString(node); 1375 | unsigned int a, b; 1376 | size_t size; 1377 | /* Perform interpolation */ 1378 | size = strlen(getString(node)) + 1; 1379 | temp = malloc(sizeof(char) * size); 1380 | for (a = 0, b = 0; str[b] != '\0'; ) { 1381 | if (!strncmp(str + b, ":)", 2)) { 1382 | temp[a] = '\n'; 1383 | a++, b += 2; 1384 | } 1385 | else if (!strncmp(str + b, ":>", 2)) { 1386 | temp[a] = '\t'; 1387 | a++, b += 2; 1388 | } 1389 | else if (!strncmp(str + b, ":o", 2)) { 1390 | temp[a] = '\a'; 1391 | a++, b += 2; 1392 | } 1393 | else if (!strncmp(str + b, ":\"", 2)) { 1394 | temp[a] = '"'; 1395 | a++, b += 2; 1396 | } 1397 | else if (!strncmp(str + b, "::", 2)) { 1398 | temp[a] = ':'; 1399 | a++, b += 2; 1400 | } 1401 | else if (!strncmp(str + b, ":(", 2)) { 1402 | const char *start = str + b + 2; 1403 | const char *end = strchr(start, ')'); 1404 | size_t len; 1405 | char *image = NULL; 1406 | long codepoint; 1407 | char out[3]; 1408 | size_t num; 1409 | void *mem = NULL; 1410 | if (end < start) { 1411 | error(IN_EXPECTED_CLOSING_PAREN); 1412 | free(temp); 1413 | return NULL; 1414 | } 1415 | len = (size_t)(end - start); 1416 | image = malloc(sizeof(char) * (len + 1)); 1417 | strncpy(image, start, len); 1418 | image[len] = '\0'; 1419 | if (!isHexString(image)) { 1420 | error(IN_INVALID_HEX_NUMBER); 1421 | free(temp); 1422 | free(image); 1423 | return NULL; 1424 | } 1425 | codepoint = strtol(image, NULL, 16); 1426 | free(image); 1427 | if (codepoint < 0) { 1428 | error(IN_CODE_POINT_MUST_BE_POSITIVE); 1429 | free(temp); 1430 | return NULL; 1431 | } 1432 | num = convertCodePointToUTF8((unsigned int)codepoint, out); 1433 | if (num == 0) { 1434 | free(temp); 1435 | return NULL; 1436 | } 1437 | size += num; 1438 | mem = realloc(temp, size); 1439 | if (!mem) { 1440 | perror("realloc"); 1441 | free(temp); 1442 | return NULL; 1443 | } 1444 | temp = mem; 1445 | strncpy(temp + a, out, num); 1446 | a += num, b += len + 3; 1447 | } 1448 | else if (!strncmp(str + b, ":[", 2)) { 1449 | const char *start = str + b + 2; 1450 | const char *end = strchr(start, ']'); 1451 | size_t len; 1452 | char *image = NULL; 1453 | long codepoint; 1454 | char out[3]; 1455 | size_t num; 1456 | void *mem = NULL; 1457 | if (end < start) { 1458 | error(IN_EXPECTED_CLOSING_SQUARE_BRACKET); 1459 | free(temp); 1460 | return NULL; 1461 | } 1462 | len = (size_t)(end - start); 1463 | image = malloc(sizeof(char) * (len + 1)); 1464 | strncpy(image, start, len); 1465 | strncpy(image, start, len); 1466 | image[len] = '\0'; 1467 | codepoint = convertNormativeNameToCodePoint(image); 1468 | free(image); 1469 | if (codepoint < 0) { 1470 | error(IN_CODE_POINT_MUST_BE_POSITIVE); 1471 | free(temp); 1472 | return NULL; 1473 | } 1474 | num = convertCodePointToUTF8((unsigned int)codepoint, out); 1475 | size += num; 1476 | mem = realloc(temp, size); 1477 | if (!mem) { 1478 | perror("realloc"); 1479 | free(temp); 1480 | return NULL; 1481 | } 1482 | temp = mem; 1483 | strncpy(temp + a, out, num); 1484 | a += num, b += len + 3; 1485 | } 1486 | else if (!strncmp(str + b, ":{", 2)) { 1487 | IdentifierNode *target = NULL; 1488 | ValueObject *val = NULL, *use = NULL; 1489 | /* Copy the variable name into image */ 1490 | const char *start = str + b + 2; 1491 | const char *end = strchr(start, '}'); 1492 | size_t len; 1493 | char *image = NULL; 1494 | void *mem = NULL; 1495 | if (end < start) { 1496 | error(IN_EXPECTED_CLOSING_CURLY_BRACE); 1497 | free(temp); 1498 | return NULL; 1499 | } 1500 | len = (size_t)(end - start); 1501 | image = malloc(sizeof(char) * (len + 1)); 1502 | strncpy(image, start, len); 1503 | image[len] = '\0'; 1504 | if (!strcmp(image, "IT")) 1505 | /* Lookup implicit variable */ 1506 | val = scope->impvar; 1507 | else { 1508 | /* 1509 | * Create a new IdentifierNode 1510 | * structure and look up its 1511 | * value 1512 | */ 1513 | target = createIdentifierNode(IT_DIRECT, image, NULL, NULL, 0); 1514 | if (!target) { 1515 | free(temp); 1516 | return NULL; 1517 | } 1518 | val = getScopeValue(scope, scope, target); 1519 | if (!val) { 1520 | error(IN_VARIABLE_DOES_NOT_EXIST, target->fname, target->line, image); 1521 | deleteIdentifierNode(target); 1522 | free(temp); 1523 | return NULL; 1524 | } 1525 | deleteIdentifierNode(target); 1526 | } 1527 | /* Cast the variable value to a string */ 1528 | if (!(use = castStringImplicit(val, scope))) { 1529 | free(temp); 1530 | return NULL; 1531 | } 1532 | /* Update the size of the new string */ 1533 | size += strlen(getString(use)); 1534 | mem = realloc(temp, size); 1535 | if (!mem) { 1536 | perror("realloc"); 1537 | free(temp); 1538 | } 1539 | temp = mem; 1540 | /* Copy the variable string into the new string */ 1541 | strcpy(temp + a, getString(use)); 1542 | a += strlen(getString(use)), b += len + 3; 1543 | deleteValueObject(use); 1544 | } 1545 | else { 1546 | temp[a] = str[b]; 1547 | a++, b++; 1548 | } 1549 | } 1550 | temp[a] = '\0'; 1551 | data = malloc(sizeof(char) * (strlen(temp) + 1)); 1552 | strcpy(data, temp); 1553 | free(temp); 1554 | return createStringValueObject(data); 1555 | } 1556 | case VT_FUNC: { 1557 | error(IN_CANNOT_CAST_FUNCTION_TO_STRING); 1558 | return NULL; 1559 | } 1560 | case VT_ARRAY: 1561 | error(IN_CANNOT_CAST_ARRAY_TO_STRING); 1562 | return NULL; 1563 | default: 1564 | error(IN_UNKNOWN_VALUE_DURING_STRING_CAST); 1565 | return NULL; 1566 | } 1567 | } 1568 | 1569 | /** 1570 | * Interprets an implicit variable. 1571 | * 1572 | * \param [in] node Not used (see note). 1573 | * 1574 | * \param [in] scope The scope from which to use the implicit variable. 1575 | * 1576 | * \note \a node is not used by this function but is still included in its 1577 | * prototype to allow this function to be stored in a jump table for fast 1578 | * execution. 1579 | * 1580 | * \return A pointer to the value of \a scope's implicit variable. 1581 | */ 1582 | ValueObject *interpretImpVarExprNode(ExprNode *node, 1583 | ScopeObject *scope) 1584 | { 1585 | node = NULL; 1586 | return scope->impvar; 1587 | } 1588 | 1589 | /** 1590 | * Interprets a cast. 1591 | * 1592 | * \param [in] node A pointer to the expression to interpret. 1593 | * 1594 | * \param [in] scope A pointer to a scope to evaluate \a node under. 1595 | * 1596 | * \pre \a node contains a expression created by createCastExprNode(). 1597 | * 1598 | * \return A pointer to the cast value. 1599 | * 1600 | * \retval NULL An error occurred during interpretation. 1601 | */ 1602 | ValueObject *interpretCastExprNode(ExprNode *node, 1603 | ScopeObject *scope) 1604 | { 1605 | CastExprNode *expr = (CastExprNode *)node->expr; 1606 | ValueObject *val = interpretExprNode(expr->target, scope); 1607 | ValueObject *ret = NULL; 1608 | if (!val) return NULL; 1609 | switch(expr->newtype->type) { 1610 | case CT_NIL: 1611 | deleteValueObject(val); 1612 | return createNilValueObject(); 1613 | case CT_BOOLEAN: 1614 | ret = castBooleanExplicit(val, scope); 1615 | deleteValueObject(val); 1616 | return ret; 1617 | case CT_INTEGER: 1618 | ret = castIntegerExplicit(val, scope); 1619 | deleteValueObject(val); 1620 | return ret; 1621 | case CT_FLOAT: 1622 | ret = castFloatExplicit(val, scope); 1623 | deleteValueObject(val); 1624 | return ret; 1625 | case CT_STRING: 1626 | ret = castStringExplicit(val, scope); 1627 | deleteValueObject(val); 1628 | return ret; 1629 | default: 1630 | error(IN_UNKNOWN_CAST_TYPE); 1631 | deleteValueObject(val); 1632 | return NULL; 1633 | } 1634 | } 1635 | 1636 | /** 1637 | * Interprets a function call. 1638 | * 1639 | * \param [in] node A pointer to the expression to interpret. 1640 | * 1641 | * \param [in,out] scope A pointer to a scope to evaluate \a node under. 1642 | * 1643 | * \pre \a node contains an expression created by createFuncCallExprNode(). 1644 | * 1645 | * \return A pointer to the returned value. 1646 | * 1647 | * \retval NULL An error occurred during interpretation. 1648 | */ 1649 | ValueObject *interpretFuncCallExprNode(ExprNode *node, 1650 | ScopeObject *scope) 1651 | { 1652 | FuncCallExprNode *expr = (FuncCallExprNode *)node->expr; 1653 | unsigned int n; 1654 | ScopeObject *outer = NULL; 1655 | ValueObject *def = NULL; 1656 | ReturnObject *retval = NULL; 1657 | ValueObject *ret = NULL; 1658 | ScopeObject *dest = NULL; 1659 | ScopeObject *target = NULL; 1660 | 1661 | dest = getScopeObject(scope, scope, expr->scope); 1662 | 1663 | target = getScopeObjectLocal(scope, dest, expr->name); 1664 | if (!target) return NULL; 1665 | 1666 | outer = createScopeObjectCaller(scope, target); 1667 | if (!outer) return NULL; 1668 | 1669 | def = getScopeValue(scope, dest, expr->name); 1670 | 1671 | if (!def || def->type != VT_FUNC) { 1672 | IdentifierNode *id = (IdentifierNode *)(expr->name); 1673 | char *name = resolveIdentifierName(id, scope); 1674 | if (name) { 1675 | error(IN_UNDEFINED_FUNCTION, id->fname, id->line, name); 1676 | free(name); 1677 | } 1678 | deleteScopeObject(outer); 1679 | return NULL; 1680 | } 1681 | /* Check for correct supplied arity */ 1682 | if (getFunction(def)->args->num != expr->args->num) { 1683 | IdentifierNode *id = (IdentifierNode *)(expr->name); 1684 | char *name = resolveIdentifierName(id, scope); 1685 | if (name) { 1686 | error(IN_INCORRECT_NUMBER_OF_ARGUMENTS, id->fname, id->line, name); 1687 | free(name); 1688 | } 1689 | deleteScopeObject(outer); 1690 | return NULL; 1691 | } 1692 | for (n = 0; n < getFunction(def)->args->num; n++) { 1693 | ValueObject *val = NULL; 1694 | if (!createScopeValue(scope, outer, getFunction(def)->args->ids[n])) { 1695 | deleteScopeObject(outer); 1696 | return NULL; 1697 | } 1698 | if (!(val = interpretExprNode(expr->args->exprs[n], scope))) { 1699 | deleteScopeObject(outer); 1700 | return NULL; 1701 | } 1702 | if (!updateScopeValue(scope, outer, getFunction(def)->args->ids[n], val)) { 1703 | deleteScopeObject(outer); 1704 | deleteValueObject(val); 1705 | return NULL; 1706 | } 1707 | } 1708 | /** 1709 | * \note We use interpretStmtNodeList here because we want to have 1710 | * access to the function's scope as we may need to retrieve the 1711 | * implicit variable in the case of a default return. 1712 | */ 1713 | if (!(retval = interpretStmtNodeList(getFunction(def)->body->stmts, outer))) { 1714 | deleteScopeObject(outer); 1715 | return NULL; 1716 | } 1717 | switch (retval->type) { 1718 | case RT_DEFAULT: 1719 | /* Extract return value */ 1720 | ret = outer->impvar; 1721 | outer->impvar = NULL; 1722 | break; 1723 | case RT_BREAK: 1724 | ret = createNilValueObject(); 1725 | break; 1726 | case RT_RETURN: 1727 | /* Extract return value */ 1728 | ret = retval->value; 1729 | retval->value = NULL; 1730 | break; 1731 | default: 1732 | error(IN_INVALID_RETURN_TYPE); 1733 | break; 1734 | } 1735 | deleteReturnObject(retval); 1736 | deleteScopeObject(outer); 1737 | return ret; 1738 | } 1739 | 1740 | /** 1741 | * Interprets an identifier. 1742 | * 1743 | * \param [in] node A pointer to the expression to interpret. 1744 | * 1745 | * \param [in,out] scope A pointer to a scope to evaluate \a node under. 1746 | * 1747 | * \pre \a node contains an identifier created by createIdentifierNode(). 1748 | * 1749 | * \return A pointer to the cast value. 1750 | * 1751 | * \retval NULL An error occurred during interpretation. 1752 | */ 1753 | ValueObject *interpretIdentifierExprNode(ExprNode *node, 1754 | ScopeObject *scope) 1755 | { 1756 | ValueObject *val = getScopeValue(scope, scope, node->expr); 1757 | if (!val) return NULL; 1758 | return copyValueObject(val); 1759 | } 1760 | 1761 | /** 1762 | * Interprets a constant. 1763 | * 1764 | * \param [in] node A pointer to the expression to interpret. 1765 | * 1766 | * \param [in] scope Not used (see note). 1767 | * 1768 | * \note \a node is not used by this function but is still included in its 1769 | * prototype to allow this function to be stored in a jump table for fast 1770 | * execution. 1771 | * 1772 | * \pre \a node contains a constant created by createXConstantNode(), where X is 1773 | * either Boolean, Integer, Float, or String. 1774 | * 1775 | * \return A pointer to the constant value. 1776 | * 1777 | * \retval NULL An error occurred during interpretation. 1778 | */ 1779 | ValueObject *interpretConstantExprNode(ExprNode *node, 1780 | ScopeObject *scope) 1781 | { 1782 | ConstantNode *expr = (ConstantNode *)node->expr; 1783 | scope = NULL; 1784 | switch (expr->type) { 1785 | case CT_NIL: 1786 | return createNilValueObject(); 1787 | case CT_BOOLEAN: 1788 | return createBooleanValueObject(expr->data.i); 1789 | case CT_INTEGER: 1790 | return createIntegerValueObject(expr->data.i); 1791 | case CT_FLOAT: 1792 | return createFloatValueObject(expr->data.f); 1793 | case CT_STRING: { 1794 | /* 1795 | * \note For efficiency, string interpolation should be 1796 | * performed by caller because it only needs to be 1797 | * performed when necessary. 1798 | */ 1799 | char *str = copyString(expr->data.s); 1800 | if (!str) return NULL; 1801 | return createStringValueObject(str); 1802 | } 1803 | default: 1804 | error(IN_UNKNOWN_CONSTANT_TYPE); 1805 | return NULL; 1806 | } 1807 | } 1808 | 1809 | /** 1810 | * Interprets a logical NOT operation. 1811 | * 1812 | * \param [in] expr A pointer to the expression to interpret. 1813 | * 1814 | * \param [in] scope A pointer to a scope to evaluate \a node under. 1815 | * 1816 | * \note Only the first element of \a args is used. 1817 | * 1818 | * \return A pointer to the value of the logical negation of the first element 1819 | * of \a args. 1820 | * 1821 | * \retval NULL An error occurred during interpretation. 1822 | */ 1823 | ValueObject *interpretNotOpExprNode(OpExprNode *expr, 1824 | ScopeObject *scope) 1825 | { 1826 | ValueObject *val = interpretExprNode(expr->args->exprs[0], scope); 1827 | ValueObject *use = val; 1828 | int retval; 1829 | unsigned short cast = 0; 1830 | if (!val) return NULL; 1831 | if (val->type != VT_BOOLEAN && val->type != VT_INTEGER) { 1832 | use = castBooleanImplicit(val, scope); 1833 | if (!use) { 1834 | deleteValueObject(val); 1835 | return NULL; 1836 | } 1837 | cast = 1; 1838 | } 1839 | retval = getInteger(use); 1840 | if (cast) deleteValueObject(use); 1841 | deleteValueObject(val); 1842 | return createBooleanValueObject(!retval); 1843 | } 1844 | 1845 | /** 1846 | * Adds an integer to an integer. 1847 | * 1848 | * \param [in] a The first operand. 1849 | * 1850 | * \param [in] b The second operand. 1851 | * 1852 | * \return A pointer to the value of the sum of \a a and \a b. 1853 | */ 1854 | ValueObject *opAddIntegerInteger(ValueObject *a, 1855 | ValueObject *b) 1856 | { 1857 | return createIntegerValueObject(getInteger(a) + getInteger(b)); 1858 | } 1859 | 1860 | /** 1861 | * Subtracts an integer from an integer. 1862 | * 1863 | * \param [in] a The first operand. 1864 | * 1865 | * \param [in] b The second operand. 1866 | * 1867 | * \return A pointer to the value of the difference of \a a and \a b. 1868 | */ 1869 | ValueObject *opSubIntegerInteger(ValueObject *a, 1870 | ValueObject *b) 1871 | { 1872 | return createIntegerValueObject(getInteger(a) - getInteger(b)); 1873 | } 1874 | 1875 | /** 1876 | * Multiplies an integer by an integer. 1877 | * 1878 | * \param [in] a The first operand. 1879 | * 1880 | * \param [in] b The second operand. 1881 | * 1882 | * \return A pointer to the value of the product of \a a and \a b. 1883 | */ 1884 | ValueObject *opMultIntegerInteger(ValueObject *a, 1885 | ValueObject *b) 1886 | { 1887 | return createIntegerValueObject(getInteger(a) * getInteger(b)); 1888 | } 1889 | 1890 | /** 1891 | * Divides an integer by an integer. 1892 | * 1893 | * \param [in] a The first operand. 1894 | * 1895 | * \param [in] b The second operand. 1896 | * 1897 | * \return A pointer to the value of the quotient of \a a and \a b. 1898 | * 1899 | * \retval NULL Division by zero. 1900 | */ 1901 | ValueObject *opDivIntegerInteger(ValueObject *a, 1902 | ValueObject *b) 1903 | { 1904 | if (getInteger(b) == 0) { 1905 | error(IN_DIVISION_BY_ZERO); 1906 | return NULL; 1907 | } 1908 | return createIntegerValueObject(getInteger(a) / getInteger(b)); 1909 | } 1910 | 1911 | /** 1912 | * Finds the maximum of an integer and an integer. 1913 | * 1914 | * \param [in] a The first operand. 1915 | * 1916 | * \param [in] b The second operand. 1917 | * 1918 | * \return A pointer to the value of the maximum of \a a and \a b. 1919 | */ 1920 | ValueObject *opMaxIntegerInteger(ValueObject *a, 1921 | ValueObject *b) 1922 | { 1923 | return createIntegerValueObject(getInteger(a) > getInteger(b) ? getInteger(a) : getInteger(b)); 1924 | } 1925 | 1926 | /** 1927 | * Finds the minimum of an integer and an integer. 1928 | * 1929 | * \param [in] a The first operand. 1930 | * 1931 | * \param [in] b The second operand. 1932 | * 1933 | * \return A pointer to the value of the minimum of \a a and \a b. 1934 | */ 1935 | ValueObject *opMinIntegerInteger(ValueObject *a, 1936 | ValueObject *b) 1937 | { 1938 | return createIntegerValueObject(getInteger(a) < getInteger(b) ? getInteger(a) : getInteger(b)); 1939 | } 1940 | 1941 | /** 1942 | * Calculates the modulus of an integer and an integer. 1943 | * 1944 | * \param [in] a The first operand. 1945 | * 1946 | * \param [in] b The second operand. 1947 | * 1948 | * \return A pointer to the value of the modulus of \a a and \a b. 1949 | */ 1950 | ValueObject *opModIntegerInteger(ValueObject *a, 1951 | ValueObject *b) 1952 | { 1953 | if (getInteger(b) == 0) { 1954 | error(IN_DIVISION_BY_ZERO); 1955 | return NULL; 1956 | } 1957 | return createIntegerValueObject(getInteger(a) % getInteger(b)); 1958 | } 1959 | 1960 | /** 1961 | * Adds an integer to a decimal. 1962 | * 1963 | * \param [in] a The first operand. 1964 | * 1965 | * \param [in] b The second operand. 1966 | * 1967 | * \return A pointer to the value of the sum of \a a and \a b. 1968 | */ 1969 | ValueObject *opAddIntegerFloat(ValueObject *a, 1970 | ValueObject *b) 1971 | { 1972 | return createFloatValueObject((float)(getInteger(a) + getFloat(b))); 1973 | } 1974 | 1975 | /** 1976 | * Subtracts an integer from a decimal. 1977 | * 1978 | * \param [in] a The first operand. 1979 | * 1980 | * \param [in] b The second operand. 1981 | * 1982 | * \return A pointer to the value of the difference of \a a and \a b. 1983 | */ 1984 | ValueObject *opSubIntegerFloat(ValueObject *a, 1985 | ValueObject *b) 1986 | { 1987 | return createFloatValueObject((float)(getInteger(a) - getFloat(b))); 1988 | } 1989 | 1990 | /** 1991 | * Multiplies an integer by a decimal. 1992 | * 1993 | * \param [in] a The first operand. 1994 | * 1995 | * \param [in] b The second operand. 1996 | * 1997 | * \return A pointer to the value of the product of \a a and \a b. 1998 | */ 1999 | ValueObject *opMultIntegerFloat(ValueObject *a, 2000 | ValueObject *b) 2001 | { 2002 | return createFloatValueObject((float)(getInteger(a) * getFloat(b))); 2003 | } 2004 | 2005 | /** 2006 | * Divides an integer by a decimal. 2007 | * 2008 | * \param [in] a The first operand. 2009 | * 2010 | * \param [in] b The second operand. 2011 | * 2012 | * \return A pointer to the value of the quotient of \a a and \a b. 2013 | * 2014 | * \retval NULL Division by zero. 2015 | */ 2016 | ValueObject *opDivIntegerFloat(ValueObject *a, 2017 | ValueObject *b) 2018 | { 2019 | if (fabs(getFloat(b) - 0.0) < FLT_EPSILON) { 2020 | error(IN_DIVISION_BY_ZERO); 2021 | return NULL; 2022 | } 2023 | return createFloatValueObject((float)(getInteger(a) / getFloat(b))); 2024 | } 2025 | 2026 | /** 2027 | * Finds the maximum of an integer and a decimal. 2028 | * 2029 | * \param [in] a The first operand. 2030 | * 2031 | * \param [in] b The second operand. 2032 | * 2033 | * \return A pointer to the value of the maximum of \a a and \a b. 2034 | */ 2035 | ValueObject *opMaxIntegerFloat(ValueObject *a, 2036 | ValueObject *b) 2037 | { 2038 | return createFloatValueObject((float)(getInteger(a)) > getFloat(b) ? (float)(getInteger(a)) : getFloat(b)); 2039 | } 2040 | 2041 | /** 2042 | * Finds the minimum of an integer and a decimal. 2043 | * 2044 | * \param [in] a The first operand. 2045 | * 2046 | * \param [in] b The second operand. 2047 | * 2048 | * \return A pointer to the value of the minimum of \a a and \a b. 2049 | */ 2050 | ValueObject *opMinIntegerFloat(ValueObject *a, 2051 | ValueObject *b) 2052 | { 2053 | return createFloatValueObject((float)(getInteger(a)) < getFloat(b) ? (float)(getInteger(a)) : getFloat(b)); 2054 | } 2055 | 2056 | /** 2057 | * Calculates the modulus of an integer and a decimal. 2058 | * 2059 | * \param [in] a The first operand. 2060 | * 2061 | * \param [in] b The second operand. 2062 | * 2063 | * \return A pointer to the value of the modulus of \a a and \a b. 2064 | */ 2065 | ValueObject *opModIntegerFloat(ValueObject *a, 2066 | ValueObject *b) 2067 | { 2068 | if (fabs(getFloat(b) - 0.0) < FLT_EPSILON) { 2069 | error(IN_DIVISION_BY_ZERO); 2070 | return NULL; 2071 | } 2072 | return createFloatValueObject((float)(fmod((double)(getInteger(a)), getFloat(b)))); 2073 | } 2074 | 2075 | /** 2076 | * Adds a decimal to an integer. 2077 | * 2078 | * \param [in] a The first operand. 2079 | * 2080 | * \param [in] b The second operand. 2081 | * 2082 | * \return A pointer to the value of the sum of \a a and \a b. 2083 | */ 2084 | ValueObject *opAddFloatInteger(ValueObject *a, 2085 | ValueObject *b) 2086 | { 2087 | return createFloatValueObject(getFloat(a) + getInteger(b)); 2088 | } 2089 | 2090 | /** 2091 | * Subtracts a decimal from an integer. 2092 | * 2093 | * \param [in] a The first operand. 2094 | * 2095 | * \param [in] b The second operand. 2096 | * 2097 | * \return A pointer to the value of the difference of \a a and \a b. 2098 | */ 2099 | ValueObject *opSubFloatInteger(ValueObject *a, 2100 | ValueObject *b) 2101 | { 2102 | return createFloatValueObject(getFloat(a) - getInteger(b)); 2103 | } 2104 | 2105 | /** 2106 | * Multiplies a decimal by an integer. 2107 | * 2108 | * \param [in] a The first operand. 2109 | * 2110 | * \param [in] b The second operand. 2111 | * 2112 | * \return A pointer to the value of the product of \a a and \a b. 2113 | */ 2114 | ValueObject *opMultFloatInteger(ValueObject *a, 2115 | ValueObject *b) 2116 | { 2117 | return createFloatValueObject(getFloat(a) * getInteger(b)); 2118 | } 2119 | 2120 | /** 2121 | * Divides a decimal by an integer. 2122 | * 2123 | * \param [in] a The first operand. 2124 | * 2125 | * \param [in] b The second operand. 2126 | * 2127 | * \return A pointer to the value of the quotient of \a a and \a b. 2128 | * 2129 | * \retval NULL Division by zero. 2130 | */ 2131 | ValueObject *opDivFloatInteger(ValueObject *a, 2132 | ValueObject *b) 2133 | { 2134 | if (getInteger(b) == 0) { 2135 | error(IN_DIVISION_BY_ZERO); 2136 | return NULL; 2137 | } 2138 | return createFloatValueObject(getFloat(a) / getInteger(b)); 2139 | } 2140 | 2141 | /** 2142 | * Finds the maximum of a decimal and an integer. 2143 | * 2144 | * \param [in] a The first operand. 2145 | * 2146 | * \param [in] b The second operand. 2147 | * 2148 | * \return A pointer to the value of the maximum of \a a and \a b. 2149 | */ 2150 | ValueObject *opMaxFloatInteger(ValueObject *a, 2151 | ValueObject *b) 2152 | { 2153 | return createFloatValueObject(getFloat(a) > (float)(getInteger(b)) ? getFloat(a) : (float)(getInteger(b))); 2154 | } 2155 | 2156 | /** 2157 | * Finds the minimum of a decimal and an integer. 2158 | * 2159 | * \param [in] a The first operand. 2160 | * 2161 | * \param [in] b The second operand. 2162 | * 2163 | * \return A pointer to the value of the minimum of \a a and \a b. 2164 | */ 2165 | ValueObject *opMinFloatInteger(ValueObject *a, 2166 | ValueObject *b) 2167 | { 2168 | return createFloatValueObject(getFloat(a) < (float)(getInteger(b)) ? getFloat(a) : (float)(getInteger(b))); 2169 | } 2170 | 2171 | /** 2172 | * Calculates the modulus of a decimal and an integer. 2173 | * 2174 | * \param [in] a The first operand. 2175 | * 2176 | * \param [in] b The second operand. 2177 | * 2178 | * \return A pointer to the value of the modulus of \a a and \a b. 2179 | */ 2180 | ValueObject *opModFloatInteger(ValueObject *a, 2181 | ValueObject *b) 2182 | { 2183 | if (getInteger(b) == 0) { 2184 | error(IN_DIVISION_BY_ZERO); 2185 | return NULL; 2186 | } 2187 | return createFloatValueObject((float)(fmod(getFloat(a), (double)(getInteger(b))))); 2188 | } 2189 | 2190 | /** 2191 | * Adds a decimal to a decimal. 2192 | * 2193 | * \param [in] a The first operand. 2194 | * 2195 | * \param [in] b The second operand. 2196 | * 2197 | * \return A pointer to the value of the sum of \a a and \a b. 2198 | */ 2199 | ValueObject *opAddFloatFloat(ValueObject *a, 2200 | ValueObject *b) 2201 | { 2202 | return createFloatValueObject(getFloat(a) + getFloat(b)); 2203 | } 2204 | 2205 | /** 2206 | * Subtracts a decimal from a decimal. 2207 | * 2208 | * \param [in] a The first operand. 2209 | * 2210 | * \param [in] b The second operand. 2211 | * 2212 | * \return A pointer to the value of the difference of \a a and \a b. 2213 | */ 2214 | ValueObject *opSubFloatFloat(ValueObject *a, 2215 | ValueObject *b) 2216 | { 2217 | return createFloatValueObject(getFloat(a) - getFloat(b)); 2218 | } 2219 | 2220 | /** 2221 | * Multiplies a decimal by a decimal. 2222 | * 2223 | * \param [in] a The first operand. 2224 | * 2225 | * \param [in] b The second operand. 2226 | * 2227 | * \return A pointer to the value of the product of \a a and \a b. 2228 | */ 2229 | ValueObject *opMultFloatFloat(ValueObject *a, 2230 | ValueObject *b) 2231 | { 2232 | return createFloatValueObject(getFloat(a) * getFloat(b)); 2233 | } 2234 | 2235 | /** 2236 | * Divides a decimal by a decimal. 2237 | * 2238 | * \param [in] a The first operand. 2239 | * 2240 | * \param [in] b The second operand. 2241 | * 2242 | * \return A pointer to the value of the quotient of \a a and \a b. 2243 | * 2244 | * \retval NULL Division by zero. 2245 | */ 2246 | ValueObject *opDivFloatFloat(ValueObject *a, 2247 | ValueObject *b) 2248 | { 2249 | if (fabs(getFloat(b) - 0.0) < FLT_EPSILON) { 2250 | error(IN_DIVISION_BY_ZERO); 2251 | return NULL; 2252 | } 2253 | return createFloatValueObject(getFloat(a) / getFloat(b)); 2254 | } 2255 | 2256 | /** 2257 | * Finds the maximum of a decimal and a decimal. 2258 | * 2259 | * \param [in] a The first operand. 2260 | * 2261 | * \param [in] b The second operand. 2262 | * 2263 | * \return A pointer to the value of the maximum of \a a and \a b. 2264 | */ 2265 | ValueObject *opMaxFloatFloat(ValueObject *a, 2266 | ValueObject *b) 2267 | { 2268 | return createFloatValueObject(getFloat(a) > getFloat(b) ? getFloat(a) : getFloat(b)); 2269 | } 2270 | 2271 | /** 2272 | * Finds the minimum of a decimal and a decimal. 2273 | * 2274 | * \param [in] a The first operand. 2275 | * 2276 | * \param [in] b The second operand. 2277 | * 2278 | * \return A pointer to the value of the minimum of \a a and \a b. 2279 | */ 2280 | ValueObject *opMinFloatFloat(ValueObject *a, 2281 | ValueObject *b) 2282 | { 2283 | return createFloatValueObject(getFloat(a) < getFloat(b) ? getFloat(a) : getFloat(b)); 2284 | } 2285 | 2286 | /** 2287 | * Calculates the modulus of a decimal and a decimal. 2288 | * 2289 | * \param [in] a The first operand. 2290 | * 2291 | * \param [in] b The second operand. 2292 | * 2293 | * \return A pointer to the value of the modulus of \a a and \a b. 2294 | */ 2295 | ValueObject *opModFloatFloat(ValueObject *a, 2296 | ValueObject *b) 2297 | { 2298 | if (fabs(getFloat(b) - 0.0) < FLT_EPSILON) { 2299 | error(IN_DIVISION_BY_ZERO); 2300 | return NULL; 2301 | } 2302 | return createFloatValueObject((float)(fmod(getFloat(a), getFloat(b)))); 2303 | } 2304 | 2305 | /* 2306 | * A jump table for arithmetic operations. The first index determines the 2307 | * particular arithmetic operation to perform, the second index determines the 2308 | * type of the first argument, and the third index determines the type of the 2309 | * second object. 2310 | */ 2311 | static ValueObject *(*ArithOpJumpTable[7][2][2])(ValueObject *, ValueObject *) = { 2312 | { { opAddIntegerInteger, opAddIntegerFloat }, { opAddFloatInteger, opAddFloatFloat } }, 2313 | { { opSubIntegerInteger, opSubIntegerFloat }, { opSubFloatInteger, opSubFloatFloat } }, 2314 | { { opMultIntegerInteger, opMultIntegerFloat }, { opMultFloatInteger, opMultFloatFloat } }, 2315 | { { opDivIntegerInteger, opDivIntegerFloat }, { opDivFloatInteger, opDivFloatFloat } }, 2316 | { { opModIntegerInteger, opModIntegerFloat }, { opModFloatInteger, opModFloatFloat } }, 2317 | { { opMaxIntegerInteger, opMaxIntegerFloat }, { opMaxFloatInteger, opMaxFloatFloat } }, 2318 | { { opMinIntegerInteger, opMinIntegerFloat }, { opMinFloatInteger, opMinFloatFloat } } 2319 | }; 2320 | 2321 | /** 2322 | * Interprets an arithmetic operation. 2323 | * 2324 | * \param [in] expr The operation to interpret. 2325 | * 2326 | * \param [in] scope The scope to evaluate \a expr under. 2327 | * 2328 | * \note Only supports binary arithmetic operations. 2329 | * 2330 | * \return A pointer to the value of the arithmetic operation. 2331 | * 2332 | * \retval NULL An error occurred during interpretation. 2333 | */ 2334 | ValueObject *interpretArithOpExprNode(OpExprNode *expr, 2335 | ScopeObject *scope) 2336 | { 2337 | ValueObject *val1 = interpretExprNode(expr->args->exprs[0], scope); 2338 | ValueObject *val2 = interpretExprNode(expr->args->exprs[1], scope); 2339 | ValueObject *use1 = val1; 2340 | ValueObject *use2 = val2; 2341 | unsigned int cast1 = 0; 2342 | unsigned int cast2 = 0; 2343 | ValueObject *ret = NULL; 2344 | if (!val1 || !val2) { 2345 | deleteValueObject(val1); 2346 | deleteValueObject(val2); 2347 | return NULL; 2348 | } 2349 | /* Check if a floating point decimal string and cast */ 2350 | switch (val1->type) { 2351 | case VT_NIL: 2352 | case VT_BOOLEAN: 2353 | use1 = castIntegerImplicit(val1, scope); 2354 | if (!use1) { 2355 | deleteValueObject(val1); 2356 | deleteValueObject(val2); 2357 | return NULL; 2358 | } 2359 | cast1 = 1; 2360 | break; 2361 | case VT_INTEGER: 2362 | case VT_FLOAT: 2363 | break; 2364 | case VT_STRING: { 2365 | /* Perform interpolation */ 2366 | ValueObject *interp = castStringExplicit(val1, scope); 2367 | if (!interp) { 2368 | deleteValueObject(val1); 2369 | deleteValueObject(val2); 2370 | return NULL; 2371 | } 2372 | if (strchr(getString(interp), '.')) 2373 | use1 = castFloatImplicit(interp, scope); 2374 | else 2375 | use1 = castIntegerImplicit(interp, scope); 2376 | deleteValueObject(interp); 2377 | if (!use1) { 2378 | deleteValueObject(val1); 2379 | deleteValueObject(val2); 2380 | return NULL; 2381 | } 2382 | cast1 = 1; 2383 | break; 2384 | } 2385 | default: 2386 | error(IN_INVALID_OPERAND_TYPE); 2387 | } 2388 | switch (val2->type) { 2389 | case VT_NIL: 2390 | case VT_BOOLEAN: 2391 | use2 = castIntegerImplicit(val2, scope); 2392 | if (!use2) { 2393 | deleteValueObject(val1); 2394 | deleteValueObject(val2); 2395 | if (cast1) deleteValueObject(use1); 2396 | return NULL; 2397 | } 2398 | cast2 = 1; 2399 | break; 2400 | case VT_INTEGER: 2401 | case VT_FLOAT: 2402 | break; 2403 | case VT_STRING: { 2404 | /* Perform interpolation */ 2405 | ValueObject *interp = castStringExplicit(val2, scope); 2406 | if (!interp) { 2407 | deleteValueObject(val1); 2408 | deleteValueObject(val2); 2409 | if (cast1) deleteValueObject(use1); 2410 | return NULL; 2411 | } 2412 | if (strchr(getString(interp), '.')) 2413 | use2 = castFloatImplicit(interp, scope); 2414 | else 2415 | use2 = castIntegerImplicit(interp, scope); 2416 | deleteValueObject(interp); 2417 | if (!use2) { 2418 | deleteValueObject(val1); 2419 | deleteValueObject(val2); 2420 | if (cast1) deleteValueObject(use1); 2421 | return NULL; 2422 | } 2423 | cast2 = 1; 2424 | break; 2425 | } 2426 | default: 2427 | error(IN_INVALID_OPERAND_TYPE); 2428 | } 2429 | /* Do math depending on value types */ 2430 | ret = ArithOpJumpTable[expr->type][use1->type][use2->type](use1, use2); 2431 | /* Clean up after floating point decimal casts */ 2432 | if (cast1) deleteValueObject(use1); 2433 | if (cast2) deleteValueObject(use2); 2434 | deleteValueObject(val1); 2435 | deleteValueObject(val2); 2436 | return ret; 2437 | } 2438 | 2439 | /** 2440 | * Interprets a boolean operation. 2441 | * 2442 | * \param [in] expr The operation to interpret. 2443 | * 2444 | * \param [in] scope The scope to evaluate \a expr under. 2445 | * 2446 | * \return A pointer to the value of the boolean operation. 2447 | * 2448 | * \retval NULL An error occurred during interpretation. 2449 | */ 2450 | ValueObject *interpretBoolOpExprNode(OpExprNode *expr, 2451 | ScopeObject *scope) 2452 | { 2453 | unsigned int n; 2454 | int acc = 0; 2455 | /* 2456 | * Proceed to apply the same operation on the accumulator for the 2457 | * remaining arguments. 2458 | */ 2459 | for (n = 0; n < expr->args->num; n++) { 2460 | ValueObject *val = interpretExprNode(expr->args->exprs[n], scope); 2461 | ValueObject *use = val; 2462 | int temp; 2463 | unsigned int cast = 0; 2464 | if (!val) return NULL; 2465 | if (val->type != VT_BOOLEAN && val->type != VT_INTEGER) { 2466 | use = castBooleanImplicit(val, scope); 2467 | if (!use) { 2468 | deleteValueObject(val); 2469 | return NULL; 2470 | } 2471 | cast = 1; 2472 | } 2473 | temp = getInteger(use); 2474 | if (cast) deleteValueObject(use); 2475 | deleteValueObject(val); 2476 | if (n == 0) acc = temp; 2477 | else { 2478 | switch (expr->type) { 2479 | case OP_AND: 2480 | acc &= temp; 2481 | break; 2482 | case OP_OR: 2483 | acc |= temp; 2484 | break; 2485 | case OP_XOR: 2486 | acc ^= temp; 2487 | break; 2488 | default: 2489 | error(IN_INVALID_BOOLEAN_OPERATION_TYPE); 2490 | return NULL; 2491 | } 2492 | } 2493 | /** 2494 | * \note The specification does not say whether boolean logic 2495 | * short circuits or not. Here, we assume it does. 2496 | */ 2497 | if (expr->type == OP_AND && acc == 0) break; 2498 | else if (expr->type == OP_OR && acc == 1) break; 2499 | } 2500 | return createBooleanValueObject(acc); 2501 | } 2502 | 2503 | /** 2504 | * Checks if an integer value is equal to another integer value. 2505 | * 2506 | * \param [in] a The first value to check. 2507 | * 2508 | * \param [in] b The second value to check. 2509 | * 2510 | * \return A pointer to a boolean value indicating if \a is equal to \a b. 2511 | */ 2512 | ValueObject *opEqIntegerInteger(ValueObject *a, 2513 | ValueObject *b) 2514 | { 2515 | return createBooleanValueObject(getInteger(a) == getInteger(b)); 2516 | } 2517 | 2518 | /** 2519 | * Checks if an integer value is not equal to another integer value. 2520 | * 2521 | * \param [in] a The first value to check. 2522 | * 2523 | * \param [in] b The second value to check. 2524 | * 2525 | * \return A pointer to a boolean value indicating if \a is not equal to \a b. 2526 | */ 2527 | ValueObject *opNeqIntegerInteger(ValueObject *a, 2528 | ValueObject *b) 2529 | { 2530 | return createBooleanValueObject(getInteger(a) != getInteger(b)); 2531 | } 2532 | 2533 | /** 2534 | * Checks if an integer value is equal to a decimal value. 2535 | * 2536 | * \param [in] a The first value to check. 2537 | * 2538 | * \param [in] b The second value to check. 2539 | * 2540 | * \return A pointer to a boolean value indicating if \a is equal to \a b. 2541 | */ 2542 | ValueObject *opEqIntegerFloat(ValueObject *a, 2543 | ValueObject *b) 2544 | { 2545 | return createBooleanValueObject(fabs((float)(getInteger(a)) - getFloat(b)) < FLT_EPSILON); 2546 | } 2547 | 2548 | /** 2549 | * Checks if an integer value is not equal to a decimal value. 2550 | * 2551 | * \param [in] a The first value to check. 2552 | * 2553 | * \param [in] b The second value to check. 2554 | * 2555 | * \return A pointer to a boolean value indicating if \a is not equal to \a b. 2556 | */ 2557 | ValueObject *opNeqIntegerFloat(ValueObject *a, 2558 | ValueObject *b) 2559 | { 2560 | return createBooleanValueObject(fabs((float)(getInteger(a)) - getFloat(b)) > FLT_EPSILON); 2561 | } 2562 | 2563 | /** 2564 | * Checks if a decimal value is equal to an integer value. 2565 | * 2566 | * \param [in] a The first value to check. 2567 | * 2568 | * \param [in] b The second value to check. 2569 | * 2570 | * \return A pointer to a boolean value indicating if \a is equal to \a b. 2571 | */ 2572 | ValueObject *opEqFloatInteger(ValueObject *a, 2573 | ValueObject *b) 2574 | { 2575 | return createBooleanValueObject(fabs(getFloat(a) - (float)(getInteger(b))) < FLT_EPSILON); 2576 | } 2577 | 2578 | /** 2579 | * Checks if a decimal value is not equal to an integer value. 2580 | * 2581 | * \param [in] a The first value to check. 2582 | * 2583 | * \param [in] b The second value to check. 2584 | * 2585 | * \return A pointer to a boolean value indicating if \a is not equal to \a b. 2586 | */ 2587 | ValueObject *opNeqFloatInteger(ValueObject *a, 2588 | ValueObject *b) 2589 | { 2590 | return createBooleanValueObject(fabs(getFloat(a) - (float)(getInteger(b))) > FLT_EPSILON); 2591 | } 2592 | 2593 | /** 2594 | * Checks if a decimal value is equal to another decimal value. 2595 | * 2596 | * \param [in] a The first value to check. 2597 | * 2598 | * \param [in] b The second value to check. 2599 | * 2600 | * \return A pointer to a boolean value indicating if \a is equal to \a b. 2601 | */ 2602 | ValueObject *opEqFloatFloat(ValueObject *a, 2603 | ValueObject *b) 2604 | { 2605 | return createBooleanValueObject(fabs(getFloat(a) - getFloat(b)) < FLT_EPSILON); 2606 | } 2607 | 2608 | /** 2609 | * Checks if a decimal value is not equal to another decimal value. 2610 | * 2611 | * \param [in] a The first value to check. 2612 | * 2613 | * \param [in] b The second value to check. 2614 | * 2615 | * \return A pointer to a boolean value indicating if \a is not equal to \a b. 2616 | */ 2617 | ValueObject *opNeqFloatFloat(ValueObject *a, 2618 | ValueObject *b) 2619 | { 2620 | return createBooleanValueObject(fabs(getFloat(a) - getFloat(b)) > FLT_EPSILON); 2621 | } 2622 | 2623 | /** 2624 | * Checks if a boolean value is equal to another boolean value. 2625 | * 2626 | * \param [in] a The first value to check. 2627 | * 2628 | * \param [in] b The second value to check. 2629 | * 2630 | * \return A pointer to a boolean value indicating if \a is equal to \a b. 2631 | */ 2632 | ValueObject *opEqBooleanBoolean(ValueObject *a, 2633 | ValueObject *b) 2634 | { 2635 | return createBooleanValueObject(getInteger(a) == getInteger(b)); 2636 | } 2637 | 2638 | /** 2639 | * Checks if a boolean value is not equal to another boolean value. 2640 | * 2641 | * \param [in] a The first value to check. 2642 | * 2643 | * \param [in] b The second value to check. 2644 | * 2645 | * \return A pointer to a boolean value indicating if \a is not equal to \a b. 2646 | */ 2647 | ValueObject *opNeqBooleanBoolean(ValueObject *a, 2648 | ValueObject *b) 2649 | { 2650 | return createBooleanValueObject(getInteger(a) != getInteger(b)); 2651 | } 2652 | 2653 | /** 2654 | * Checks if a string value is equal to another string value. 2655 | * 2656 | * \param [in] a The first value to check. 2657 | * 2658 | * \param [in] b The second value to check. 2659 | * 2660 | * \return A pointer to a boolean value indicating if \a is equal to \a b. 2661 | */ 2662 | ValueObject *opEqStringString(ValueObject *a, 2663 | ValueObject *b) 2664 | { 2665 | return createBooleanValueObject(strcmp(getString(a), getString(b)) == 0); 2666 | } 2667 | 2668 | /** 2669 | * Checks if a string value is not equal to another string value. 2670 | * 2671 | * \param [in] a The first value to check. 2672 | * 2673 | * \param [in] b The second value to check. 2674 | * 2675 | * \return A pointer to a boolean value indicating if \a is not equal to \a b. 2676 | */ 2677 | ValueObject *opNeqStringString(ValueObject *a, 2678 | ValueObject *b) 2679 | { 2680 | return createBooleanValueObject(strcmp(getString(a), getString(b)) != 0); 2681 | } 2682 | 2683 | /** 2684 | * Returns true because two nil values are always equal. 2685 | * 2686 | * \param [in] a Not used. 2687 | * 2688 | * \param [in] b Not used. 2689 | * 2690 | * \return A true boolean value. 2691 | */ 2692 | ValueObject *opEqNilNil(ValueObject *a, 2693 | ValueObject *b) 2694 | { 2695 | a = NULL; 2696 | b = NULL; 2697 | return createBooleanValueObject(1); 2698 | } 2699 | 2700 | /** 2701 | * Returns false because two nil values are never not equal. 2702 | * 2703 | * \param [in] a Not used. 2704 | * 2705 | * \param [in] b Not used. 2706 | * 2707 | * \return A false boolean value. 2708 | */ 2709 | ValueObject *opNeqNilNil(ValueObject *a, 2710 | ValueObject *b) 2711 | { 2712 | a = NULL; 2713 | b = NULL; 2714 | return createBooleanValueObject(0); 2715 | } 2716 | 2717 | /* 2718 | * A jump table for boolean operations. The first index determines the 2719 | * particular boolean operation to perform, the second index determines the type 2720 | * of the first argument, and the third index determines the type of the second 2721 | * object. 2722 | */ 2723 | static ValueObject *(*BoolOpJumpTable[2][5][5])(ValueObject *, ValueObject *) = { 2724 | { /* OP_EQ */ 2725 | /* Integer, Float, Boolean, String, Nil */ 2726 | /* Integer */ { opEqIntegerInteger, opEqIntegerFloat, NULL, NULL, NULL }, 2727 | /* Float */ { opEqFloatInteger, opEqFloatFloat, NULL, NULL, NULL }, 2728 | /* Boolean */ { NULL, NULL, opEqBooleanBoolean, NULL, NULL }, 2729 | /* String */ { NULL, NULL, NULL, opEqStringString, NULL }, 2730 | /* Nil */ { NULL, NULL, NULL, NULL, opEqNilNil } 2731 | }, 2732 | { /* OP_NEQ */ 2733 | /* Integer, Float, Boolean, String, Nil */ 2734 | /* Integer */ { opNeqIntegerInteger, opNeqIntegerFloat, NULL, NULL, NULL }, 2735 | /* Float */ { opNeqFloatInteger, opNeqFloatFloat, NULL, NULL, NULL }, 2736 | /* Boolean */ { NULL, NULL, opNeqBooleanBoolean, NULL, NULL }, 2737 | /* String */ { NULL, NULL, NULL, opNeqStringString, NULL }, 2738 | /* Nil */ { NULL, NULL, NULL, NULL, opNeqNilNil } 2739 | } 2740 | }; 2741 | 2742 | /** 2743 | * Interprets an equality operation. 2744 | * 2745 | * \param [in] expr The operation to interpret. 2746 | * 2747 | * \param [in] scope The scope to evaluate \a expr under. 2748 | * 2749 | * \return A pointer to the resulting value of the equality operation. 2750 | * 2751 | * \retval NULL An error occurred during interpretation. 2752 | */ 2753 | ValueObject *interpretEqualityOpExprNode(OpExprNode *expr, 2754 | ScopeObject *scope) 2755 | { 2756 | ValueObject *val1 = interpretExprNode(expr->args->exprs[0], scope); 2757 | ValueObject *val2 = interpretExprNode(expr->args->exprs[1], scope); 2758 | ValueObject *ret = NULL; 2759 | if (!val1 || !val2) { 2760 | deleteValueObject(val1); 2761 | deleteValueObject(val2); 2762 | return NULL; 2763 | } 2764 | /* 2765 | * Since there is no automatic casting, an equality (inequality) test 2766 | * against a non-number type will always fail (succeed). 2767 | */ 2768 | if ((val1->type != val2->type) 2769 | && ((val1->type != VT_INTEGER && val1->type != VT_FLOAT) 2770 | || (val2->type != VT_INTEGER && val2->type != VT_FLOAT))) { 2771 | switch (expr->type) { 2772 | case OP_EQ: 2773 | ret = createBooleanValueObject(0); 2774 | break; 2775 | case OP_NEQ: 2776 | ret = createBooleanValueObject(1); 2777 | break; 2778 | default: 2779 | error(IN_INVALID_EQUALITY_OPERATION_TYPE); 2780 | deleteValueObject(val1); 2781 | deleteValueObject(val2); 2782 | return NULL; 2783 | } 2784 | } 2785 | else 2786 | ret = BoolOpJumpTable[expr->type - OP_EQ][val1->type][val2->type](val1, val2); 2787 | deleteValueObject(val1); 2788 | deleteValueObject(val2); 2789 | return ret; 2790 | } 2791 | 2792 | /** 2793 | * Interprets a concatenation operation. 2794 | * 2795 | * \param [in] expr The operation to interpret. 2796 | * 2797 | * \param [in] scope The scope to evaluate \a expr under. 2798 | * 2799 | * \return A pointer to the resulting value of the concatenation operation. 2800 | * 2801 | * \retval NULL An error occurred during interpretation. 2802 | */ 2803 | ValueObject *interpretConcatOpExprNode(OpExprNode *expr, 2804 | ScopeObject *scope) 2805 | { 2806 | unsigned int n; 2807 | /* Start out with the first string to concatenate. */ 2808 | ValueObject *val = interpretExprNode(expr->args->exprs[0], scope); 2809 | ValueObject *use = castStringImplicit(val, scope); 2810 | char *acc = NULL; 2811 | void *mem = NULL; 2812 | if (!val || !use) { 2813 | deleteValueObject(val); 2814 | deleteValueObject(use); 2815 | return NULL; 2816 | } 2817 | /* Start out an accumulator with the first string. */ 2818 | mem = realloc(acc, sizeof(char) * (strlen(getString(use)) + 1)); 2819 | if (!mem) { 2820 | perror("realloc"); 2821 | deleteValueObject(val); 2822 | deleteValueObject(use); 2823 | free(acc); 2824 | return NULL; 2825 | } 2826 | acc = mem; 2827 | acc[0] = '\0'; 2828 | strcat(acc, getString(use)); 2829 | deleteValueObject(val); 2830 | deleteValueObject(use); 2831 | for (n = 1; n < expr->args->num; n++) { 2832 | /* Grab the next string to concatenate. */ 2833 | val = interpretExprNode(expr->args->exprs[n], scope); 2834 | use = castStringImplicit(val, scope); 2835 | if (!val || !use) { 2836 | deleteValueObject(val); 2837 | deleteValueObject(use); 2838 | free(acc); 2839 | return NULL; 2840 | } 2841 | /* Add the next string to the accumulator. */ 2842 | mem = realloc(acc, sizeof(char) * (strlen(acc) + strlen(getString(use)) + 1)); 2843 | if (!mem) { 2844 | perror("realloc"); 2845 | deleteValueObject(val); 2846 | deleteValueObject(use); 2847 | free(acc); 2848 | return NULL; 2849 | } 2850 | acc = mem; 2851 | strcat(acc, getString(use)); 2852 | deleteValueObject(val); 2853 | deleteValueObject(use); 2854 | } 2855 | return createStringValueObject(acc); 2856 | } 2857 | 2858 | /* 2859 | * A jump table for operations. The index of a function in the table is given 2860 | * by its its index in the enumerated OpType type. 2861 | */ 2862 | static ValueObject *(*OpExprJumpTable[14])(OpExprNode *, ScopeObject *) = { 2863 | interpretArithOpExprNode, 2864 | interpretArithOpExprNode, 2865 | interpretArithOpExprNode, 2866 | interpretArithOpExprNode, 2867 | interpretArithOpExprNode, 2868 | interpretArithOpExprNode, 2869 | interpretArithOpExprNode, 2870 | interpretBoolOpExprNode, 2871 | interpretBoolOpExprNode, 2872 | interpretBoolOpExprNode, 2873 | interpretNotOpExprNode, 2874 | interpretEqualityOpExprNode, 2875 | interpretEqualityOpExprNode, 2876 | interpretConcatOpExprNode }; 2877 | 2878 | /** 2879 | * Interprets an operation. 2880 | * 2881 | * \param [in] node The operation to interpret. 2882 | * 2883 | * \param [in] scope The scope to evaluate \a expr under. 2884 | * 2885 | * \return A pointer to the resulting value of the operation. 2886 | * 2887 | * \retval NULL An error occurred during interpretation. 2888 | */ 2889 | ValueObject *interpretOpExprNode(ExprNode *node, 2890 | ScopeObject *scope) 2891 | { 2892 | OpExprNode *expr = (OpExprNode *)node->expr; 2893 | return OpExprJumpTable[expr->type](expr, scope); 2894 | } 2895 | 2896 | /* 2897 | * A jump table for expressions. The index of a function in the table is given 2898 | * by its its index in the enumerated ExprType type. 2899 | */ 2900 | static ValueObject *(*ExprJumpTable[6])(ExprNode *, ScopeObject *) = { 2901 | interpretCastExprNode, 2902 | interpretConstantExprNode, 2903 | interpretIdentifierExprNode, 2904 | interpretFuncCallExprNode, 2905 | interpretOpExprNode, 2906 | interpretImpVarExprNode }; 2907 | 2908 | /** 2909 | * Interprets an expression. 2910 | * 2911 | * \param [in] node The expression to interpret. 2912 | * 2913 | * \param [in] scope The scope to evaluate \a expr under. 2914 | * 2915 | * \return A pointer to the value of \a expr evaluated under \a scope. 2916 | * 2917 | * \retval NULL An error occurred during interpretation. 2918 | */ 2919 | ValueObject *interpretExprNode(ExprNode *node, 2920 | ScopeObject *scope) 2921 | { 2922 | return ExprJumpTable[node->type](node, scope); 2923 | } 2924 | 2925 | /** 2926 | * Interprets a cast statement. 2927 | * 2928 | * \param [in] node The statement to interpret. 2929 | * 2930 | * \param [in] scope The scope to evaluate \a node under. 2931 | * 2932 | * \pre \a node contains a statement created by createCastStmtNode(). 2933 | * 2934 | * \return A pointer to a default return value. 2935 | * 2936 | * \retval NULL An error occurred during interpretation. 2937 | */ 2938 | ReturnObject *interpretCastStmtNode(StmtNode *node, 2939 | ScopeObject *scope) 2940 | { 2941 | CastStmtNode *stmt = (CastStmtNode *)node->stmt; 2942 | ValueObject *val = getScopeValue(scope, scope, stmt->target); 2943 | ValueObject *cast = NULL; 2944 | if (!val) { 2945 | IdentifierNode *id = (IdentifierNode *)(stmt->target); 2946 | char *name = resolveIdentifierName(id, scope); 2947 | if (name) { 2948 | error(IN_VARIABLE_DOES_NOT_EXIST, id->fname, id->line, name); 2949 | free(name); 2950 | } 2951 | return NULL; 2952 | } 2953 | switch(stmt->newtype->type) { 2954 | case CT_NIL: 2955 | if (!(cast = createNilValueObject())) return NULL; 2956 | break; 2957 | case CT_BOOLEAN: 2958 | if (!(cast = castBooleanExplicit(val, scope))) return NULL; 2959 | break; 2960 | case CT_INTEGER: 2961 | if (!(cast = castIntegerExplicit(val, scope))) return NULL; 2962 | break; 2963 | case CT_FLOAT: 2964 | if (!(cast = castFloatExplicit(val, scope))) return NULL; 2965 | break; 2966 | case CT_STRING: 2967 | if (!(cast = castStringExplicit(val, scope))) return NULL; 2968 | break; 2969 | } 2970 | if (!updateScopeValue(scope, scope, stmt->target, cast)) { 2971 | deleteValueObject(cast); 2972 | return NULL; 2973 | } 2974 | return createReturnObject(RT_DEFAULT, NULL); 2975 | } 2976 | 2977 | /** 2978 | * Interprets a print statement. 2979 | * 2980 | * \param [in] node The statement to interpret. 2981 | * 2982 | * \param [in] scope The scope to evaluate \a node under. 2983 | * 2984 | * \pre \a node contains a statement created by createPrintStmtNode(). 2985 | * 2986 | * \return A pointer to a default return value. 2987 | * 2988 | * \retval NULL An error occurred during interpretation. 2989 | */ 2990 | ReturnObject *interpretPrintStmtNode(StmtNode *node, 2991 | ScopeObject *scope) 2992 | { 2993 | PrintStmtNode *stmt = (PrintStmtNode *)node->stmt; 2994 | unsigned int n; 2995 | for (n = 0; n < stmt->args->num; n++) { 2996 | ValueObject *val = interpretExprNode(stmt->args->exprs[n], scope); 2997 | ValueObject *use = castStringImplicit(val, scope); 2998 | if (!val || !use) { 2999 | deleteValueObject(val); 3000 | deleteValueObject(use); 3001 | return NULL; 3002 | } 3003 | printf("%s", getString(use)); 3004 | deleteValueObject(val); 3005 | deleteValueObject(use); 3006 | } 3007 | if (!stmt->nonl) 3008 | printf("\n"); 3009 | return createReturnObject(RT_DEFAULT, NULL); 3010 | } 3011 | 3012 | /** 3013 | * Interprets an input statement. 3014 | * 3015 | * \param [in] node The statement to interpret. 3016 | * 3017 | * \param [in] scope The scope to evaluate \a node under. 3018 | * 3019 | * \pre \a node contains a statement created by createInputStmtNode(). 3020 | * 3021 | * \return A pointer to a default return value. 3022 | * 3023 | * \retval NULL An error occurred during interpretation. 3024 | */ 3025 | ReturnObject *interpretInputStmtNode(StmtNode *node, 3026 | ScopeObject *scope) 3027 | { 3028 | unsigned int size = 16; 3029 | unsigned int cur = 0; 3030 | char *temp = malloc(sizeof(char) * size); 3031 | int c; 3032 | void *mem = NULL; 3033 | InputStmtNode *stmt = (InputStmtNode *)node->stmt; 3034 | ValueObject *val = NULL; 3035 | while ((c = getchar()) && !feof(stdin)) { 3036 | /** 3037 | * \note The specification is unclear as to the exact semantics 3038 | * of input. Here, we read up until the first newline or EOF 3039 | * but do not store it. 3040 | */ 3041 | if (c == EOF || c == (int)'\r' || c == (int)'\n') break; 3042 | if (cur > size - 1) { 3043 | /* Increasing buffer size. */ 3044 | size *= 2; 3045 | mem = realloc(temp, sizeof(char) * size); 3046 | if (!mem) { 3047 | perror("realloc"); 3048 | free(temp); 3049 | return NULL; 3050 | } 3051 | temp = mem; 3052 | } 3053 | temp[cur] = (char)c; 3054 | cur++; 3055 | } 3056 | temp[cur] = '\0'; 3057 | val = createStringValueObject(temp); 3058 | if (!val) { 3059 | free(temp); 3060 | return NULL; 3061 | } 3062 | if (!updateScopeValue(scope, scope, stmt->target, val)) { 3063 | deleteValueObject(val); 3064 | return NULL; 3065 | } 3066 | return createReturnObject(RT_DEFAULT, NULL); 3067 | } 3068 | 3069 | /** 3070 | * Interprets an assignment statement. 3071 | * 3072 | * \param [in] node The statement to interpret. 3073 | * 3074 | * \param [in] scope The scope to evaluate \a node under. 3075 | * 3076 | * \pre \a node contains a statement created by createAssignmentStmtNode(). 3077 | * 3078 | * \return A pointer to a default return value. 3079 | * 3080 | * \retval NULL An error occurred during interpretation. 3081 | */ 3082 | ReturnObject *interpretAssignmentStmtNode(StmtNode *node, 3083 | ScopeObject *scope) 3084 | { 3085 | AssignmentStmtNode *stmt = (AssignmentStmtNode *)node->stmt; 3086 | ValueObject *val = interpretExprNode(stmt->expr, scope); 3087 | if (!val) return NULL; 3088 | if (!updateScopeValue(scope, scope, stmt->target, val)) { 3089 | deleteValueObject(val); 3090 | return NULL; 3091 | } 3092 | return createReturnObject(RT_DEFAULT, NULL); 3093 | } 3094 | 3095 | /** 3096 | * Interprets a declaration statement. 3097 | * 3098 | * \param [in] node The statement to interpret. 3099 | * 3100 | * \param [in] scope The scope to evaluate \a node under. 3101 | * 3102 | * \pre \a node contains a statement created by createDeclarationStmtNode(). 3103 | * 3104 | * \return A pointer to a default return value. 3105 | * 3106 | * \retval NULL An error occurred during interpretation. 3107 | */ 3108 | ReturnObject *interpretDeclarationStmtNode(StmtNode *node, 3109 | ScopeObject *scope) 3110 | { 3111 | DeclarationStmtNode *stmt = (DeclarationStmtNode *)node->stmt; 3112 | ValueObject *init = NULL; 3113 | ScopeObject *dest = NULL; 3114 | dest = getScopeObject(scope, scope, stmt->scope); 3115 | if (!dest) return NULL; 3116 | if (getScopeValueLocal(scope, dest, stmt->target)) { 3117 | IdentifierNode *id = (IdentifierNode *)(stmt->target); 3118 | char *name = resolveIdentifierName(id, scope); 3119 | if (name) { 3120 | error(IN_REDEFINITION_OF_VARIABLE, id->fname, id->line, name); 3121 | free(name); 3122 | } 3123 | return NULL; 3124 | } 3125 | if (stmt->expr) 3126 | init = interpretExprNode(stmt->expr, scope); 3127 | else if (stmt->type) { 3128 | switch (stmt->type->type) { 3129 | case CT_NIL: 3130 | init = createNilValueObject(); 3131 | break; 3132 | case CT_BOOLEAN: 3133 | init = createBooleanValueObject(0); 3134 | break; 3135 | case CT_INTEGER: 3136 | init = createIntegerValueObject(0); 3137 | break; 3138 | case CT_FLOAT: 3139 | init = createFloatValueObject(0.0); 3140 | break; 3141 | case CT_STRING: 3142 | init = createStringValueObject(copyString("")); 3143 | break; 3144 | case CT_ARRAY: 3145 | init = createArrayValueObject(scope); 3146 | break; 3147 | default: 3148 | error(IN_INVALID_DECLARATION_TYPE); 3149 | return NULL; 3150 | } 3151 | } 3152 | else if (stmt->parent) { 3153 | ScopeObject *parent = getScopeObject(scope, scope, stmt->parent); 3154 | if (!parent) return NULL; 3155 | init = createArrayValueObject(parent); 3156 | } 3157 | else 3158 | init = createNilValueObject(); 3159 | if (!init) return NULL; 3160 | if (!createScopeValue(scope, dest, stmt->target)) { 3161 | deleteValueObject(init); 3162 | return NULL; 3163 | } 3164 | if (!updateScopeValue(scope, dest, stmt->target, init)) { 3165 | deleteValueObject(init); 3166 | return NULL; 3167 | } 3168 | return createReturnObject(RT_DEFAULT, NULL); 3169 | } 3170 | 3171 | /** 3172 | * Interprets an if/then/else statement. 3173 | * 3174 | * \param [in] node The statement to interpret. 3175 | * 3176 | * \param [in] scope The scope to evaluate \a node under. 3177 | * 3178 | * \pre \a node contains a statement created by createIfThenElseStmtNode(). 3179 | * 3180 | * \return A pointer to a default return value. 3181 | * 3182 | * \retval NULL An error occurred during interpretation. 3183 | */ 3184 | ReturnObject *interpretIfThenElseStmtNode(StmtNode *node, 3185 | ScopeObject *scope) 3186 | { 3187 | IfThenElseStmtNode *stmt = (IfThenElseStmtNode *)node->stmt; 3188 | ValueObject *use1 = scope->impvar; 3189 | int use1val; 3190 | unsigned int cast1 = 0; 3191 | BlockNode *path = NULL; 3192 | if (scope->impvar->type != VT_BOOLEAN && scope->impvar->type != VT_INTEGER) { 3193 | use1 = castBooleanImplicit(scope->impvar, scope); 3194 | if (!use1) return NULL; 3195 | cast1 = 1; 3196 | } 3197 | use1val = getInteger(use1); 3198 | if (cast1) deleteValueObject(use1); 3199 | /* Determine which block of code to execute */ 3200 | if (use1val) 3201 | path = stmt->yes; 3202 | else { 3203 | unsigned int n; 3204 | for (n = 0; n < stmt->guards->num; n++) { 3205 | ValueObject *val = interpretExprNode(stmt->guards->exprs[n], scope); 3206 | ValueObject *use2 = val; 3207 | int use2val; 3208 | unsigned int cast2 = 0; 3209 | if (!val) return NULL; 3210 | if (val->type != VT_BOOLEAN && val->type != VT_INTEGER) { 3211 | use2 = castBooleanImplicit(val, scope); 3212 | if (!use2) { 3213 | deleteValueObject(val); 3214 | return NULL; 3215 | } 3216 | cast2 = 1; 3217 | } 3218 | use2val = getInteger(use2); 3219 | deleteValueObject(val); 3220 | if (cast2) deleteValueObject(use2); 3221 | if (use2val) { 3222 | path = stmt->blocks->blocks[n]; 3223 | break; 3224 | } 3225 | } 3226 | /* Reached the end without satisfying any guard */ 3227 | if (n == stmt->guards->num) 3228 | path = stmt->no; 3229 | } 3230 | /* Interpret a path if one was reached */ 3231 | if (path) { 3232 | ReturnObject *r = interpretBlockNode(path, scope); 3233 | if (!r) 3234 | return NULL; 3235 | /* Pass this up to the outer block to handle. */ 3236 | else if (r->type == RT_BREAK || r->type == RT_RETURN) 3237 | return r; 3238 | else 3239 | deleteReturnObject(r); 3240 | } 3241 | return createReturnObject(RT_DEFAULT, NULL); 3242 | } 3243 | 3244 | /** 3245 | * Interprets a switch statement. 3246 | * 3247 | * \param [in] node The statement to interpret. 3248 | * 3249 | * \param [in] scope The scope to evaluate \a node under. 3250 | * 3251 | * \pre \a node contains a statement created by createSwitchStmtNode(). 3252 | * 3253 | * \note The specification is unclear as to whether guards are implicitly cast 3254 | * to the type of the implicit variable. This only matters in the case that 3255 | * mixed guard types are present, and in this code, the action that is performed 3256 | * is the same as the comparison operator, that is, in order for a guard to 3257 | * match, both its type and value must match the implicit variable. 3258 | * 3259 | * \return A pointer to a default return value. 3260 | * 3261 | * \retval NULL An error occurred during interpretation. 3262 | */ 3263 | ReturnObject *interpretSwitchStmtNode(StmtNode *node, 3264 | ScopeObject *scope) 3265 | { 3266 | SwitchStmtNode *stmt = (SwitchStmtNode *)node->stmt; 3267 | unsigned int n; 3268 | /* 3269 | * Loop over each of the guards, checking if any match the implicit 3270 | * variable. 3271 | */ 3272 | for (n = 0; n < stmt->guards->num; n++) { 3273 | ValueObject *use1 = scope->impvar; 3274 | ValueObject *use2 = interpretExprNode(stmt->guards->exprs[n], scope); 3275 | unsigned int done = 0; 3276 | if (!use2) return NULL; 3277 | if (use1->type == use2->type) { 3278 | switch (use1->type) { 3279 | case VT_NIL: 3280 | break; 3281 | case VT_BOOLEAN: 3282 | case VT_INTEGER: 3283 | if (getInteger(use1) == getInteger(use2)) 3284 | done = 1; 3285 | break; 3286 | case VT_FLOAT: 3287 | if (fabs(getFloat(use1) - getFloat(use2)) < FLT_EPSILON) 3288 | done = 1; 3289 | break; 3290 | case VT_STRING: 3291 | /** 3292 | * \note Strings with interpolation 3293 | * should have already been checked for. 3294 | */ 3295 | if (!strcmp(getString(use1), getString(use2))) 3296 | done = 1; 3297 | break; 3298 | default: 3299 | error(IN_INVALID_TYPE); 3300 | deleteValueObject(use2); 3301 | return NULL; 3302 | } 3303 | } 3304 | deleteValueObject(use2); 3305 | if (done) break; 3306 | } 3307 | /* If none of the guards match and a default block exists */ 3308 | if (n == stmt->blocks->num && stmt->def) { 3309 | ReturnObject *r = interpretBlockNode(stmt->def, scope); 3310 | if (!r) 3311 | return NULL; 3312 | else if (r->type == RT_RETURN) 3313 | return r; 3314 | else 3315 | deleteReturnObject(r); 3316 | } 3317 | else { 3318 | /* 3319 | * Keep interpreting blocks starting at n until a break or 3320 | * return is encountered. 3321 | */ 3322 | for (; n < stmt->blocks->num; n++) { 3323 | ReturnObject *r = interpretBlockNode(stmt->blocks->blocks[n], scope); 3324 | if (!r) 3325 | return NULL; 3326 | else if (r->type == RT_BREAK) { 3327 | deleteReturnObject(r); 3328 | break; 3329 | } 3330 | else if (r->type == RT_RETURN) 3331 | return r; 3332 | else 3333 | deleteReturnObject(r); 3334 | } 3335 | } 3336 | return createReturnObject(RT_DEFAULT, NULL); 3337 | } 3338 | 3339 | /** 3340 | * Interprets a break statement. 3341 | * 3342 | * \param [in] node Not used (see note). 3343 | * 3344 | * \param [in] scope Not used (see note). 3345 | * 3346 | * \pre \a node contains a statement created by createStmtNode() with arguments 3347 | * ST_BREAK and NULL. 3348 | * 3349 | * \note \a node and \a scope are not used by this function but are still 3350 | * included in its prototype to allow this function to be stored in a jump table 3351 | * for fast execution. 3352 | * 3353 | * \return A pointer to a break return value. 3354 | * 3355 | * \retval NULL An error occurred during interpretation. 3356 | */ 3357 | ReturnObject *interpretBreakStmtNode(StmtNode *node, 3358 | ScopeObject *scope) 3359 | { 3360 | node = NULL; 3361 | scope = NULL; 3362 | return createReturnObject(RT_BREAK, NULL); 3363 | } 3364 | 3365 | /** 3366 | * Interprets a return statement. 3367 | * 3368 | * \param [in] node The statement to interpret. 3369 | * 3370 | * \param [in] scope The scope to evaluate \a node under. 3371 | * 3372 | * \pre \a node contains a statement created by createReturnStmtNode(). 3373 | * 3374 | * \return A pointer to a return value of \a node interpreted under \a scope. 3375 | * 3376 | * \retval NULL An error occurred during interpretation. 3377 | */ 3378 | ReturnObject *interpretReturnStmtNode(StmtNode *node, 3379 | ScopeObject *scope) 3380 | { 3381 | /* Evaluate and return the expression. */ 3382 | ReturnStmtNode *stmt = (ReturnStmtNode *)node->stmt; 3383 | ValueObject *value = interpretExprNode(stmt->value, scope); 3384 | if (!value) return NULL; 3385 | return createReturnObject(RT_RETURN, value); 3386 | } 3387 | 3388 | /** 3389 | * Interprets a loop statement. 3390 | * 3391 | * \param [in] node The statement to interpret. 3392 | * 3393 | * \param [in] scope The scope to evaluate \a node under. 3394 | * 3395 | * \pre \a node contains a statement created by createLoopStmtNode(). 3396 | * 3397 | * \return A pointer to a return value of \a node interpreted under \a scope. 3398 | * 3399 | * \retval NULL An error occurred during interpretation. 3400 | */ 3401 | ReturnObject *interpretLoopStmtNode(StmtNode *node, 3402 | ScopeObject *scope) 3403 | { 3404 | LoopStmtNode *stmt = (LoopStmtNode *)node->stmt; 3405 | ScopeObject *outer = createScopeObject(scope); 3406 | ValueObject *var = NULL; 3407 | if (!outer) return NULL; 3408 | /* Create a temporary loop variable if required */ 3409 | if (stmt->var) { 3410 | var = createScopeValue(scope, outer, stmt->var); 3411 | if (!var) { 3412 | deleteScopeObject(outer); 3413 | return NULL; 3414 | } 3415 | var->type = VT_INTEGER; 3416 | var->data.i = 0; 3417 | var->semaphore = 1; 3418 | } 3419 | while (1) { 3420 | if (stmt->guard) { 3421 | ValueObject *val = interpretExprNode(stmt->guard, outer); 3422 | ValueObject *use = val; 3423 | unsigned short cast = 0; 3424 | int guardval; 3425 | if (val->type != VT_BOOLEAN && val->type != VT_INTEGER) { 3426 | use = castBooleanImplicit(val, scope); 3427 | if (!use) { 3428 | deleteScopeObject(outer); 3429 | deleteValueObject(val); 3430 | return NULL; 3431 | } 3432 | cast = 1; 3433 | } 3434 | guardval = getInteger(use); 3435 | if (cast) deleteValueObject(use); 3436 | deleteValueObject(val); 3437 | if (guardval == 0) break; 3438 | } 3439 | if (stmt->body) { 3440 | ReturnObject *result = interpretBlockNode(stmt->body, outer); 3441 | if (!result) { 3442 | deleteScopeObject(outer); 3443 | return NULL; 3444 | } 3445 | else if (result->type == RT_BREAK) { 3446 | deleteReturnObject(result); 3447 | break; 3448 | } 3449 | else if (result->type == RT_RETURN) { 3450 | deleteScopeObject(outer); 3451 | return result; 3452 | } 3453 | else 3454 | deleteReturnObject(result); 3455 | } 3456 | if (stmt->update) { 3457 | /* 3458 | * A little efficiency hack: if we know the operation to 3459 | * perform, don't bother evaluating the ExprNode 3460 | * structure, just go ahead and do it to the loop 3461 | * variable. 3462 | */ 3463 | if (stmt->update->type == ET_OP) { 3464 | var = getScopeValue(scope, outer, stmt->var); 3465 | OpExprNode *op = (OpExprNode *)stmt->update->expr; 3466 | if (op->type == OP_ADD) 3467 | var->data.i++; 3468 | else if (op->type == OP_SUB) 3469 | var->data.i--; 3470 | } 3471 | else { 3472 | ValueObject *update = interpretExprNode(stmt->update, outer); 3473 | if (!update) { 3474 | deleteScopeObject(outer); 3475 | return NULL; 3476 | } 3477 | if (!updateScopeValue(scope, outer, stmt->var, update)) { 3478 | deleteScopeObject(outer); 3479 | deleteValueObject(update); 3480 | return NULL; 3481 | } 3482 | } 3483 | } 3484 | } 3485 | deleteScopeObject(outer); 3486 | return createReturnObject(RT_DEFAULT, NULL); 3487 | } 3488 | 3489 | /** 3490 | * Interprets a deallocation statement. 3491 | * 3492 | * \param [in] node The statement to interpret. 3493 | * 3494 | * \param [in] scope The scope to evaluate \a node under. 3495 | * 3496 | * \pre \a node contains a statement created by createDeallocationStmtNode(). 3497 | * 3498 | * \return A pointer to a default return value. 3499 | * 3500 | * \retval NULL An error occurred during interpretation. 3501 | */ 3502 | ReturnObject *interpretDeallocationStmtNode(StmtNode *node, 3503 | ScopeObject *scope) 3504 | { 3505 | DeallocationStmtNode *stmt = (DeallocationStmtNode *)node->stmt; 3506 | if (!updateScopeValue(scope, scope, stmt->target, NULL)) return NULL; 3507 | /* If we want to completely remove the variable, use: 3508 | deleteScopeValue(scope, stmt->target); 3509 | */ 3510 | return createReturnObject(RT_DEFAULT, NULL); 3511 | } 3512 | 3513 | /** 3514 | * Interprets a function definition statement. 3515 | * 3516 | * \param [in] node The statement to interpret. 3517 | * 3518 | * \param [in] scope The scope to evaluate \a node under. 3519 | * 3520 | * \pre \a node contains a statement created by createFuncDefStmtNode(). 3521 | * 3522 | * \return A pointer to a default return value. 3523 | * 3524 | * \retval NULL An error occurred during interpretation. 3525 | */ 3526 | ReturnObject *interpretFuncDefStmtNode(StmtNode *node, 3527 | ScopeObject *scope) 3528 | { 3529 | /* Add the function to the current scope */ 3530 | FuncDefStmtNode *stmt = (FuncDefStmtNode *)node->stmt; 3531 | ValueObject *init = NULL; 3532 | ScopeObject *dest = NULL; 3533 | 3534 | dest = getScopeObject(scope, scope, stmt->scope); 3535 | if (!dest) return NULL; 3536 | if (getScopeValueLocal(scope, dest, stmt->name)) { 3537 | IdentifierNode *id = (IdentifierNode *)(stmt->name); 3538 | char *name = resolveIdentifierName(id, scope); 3539 | if (name) { 3540 | error(IN_FUNCTION_NAME_USED_BY_VARIABLE, id->fname, id->line, name); 3541 | free(name); 3542 | } 3543 | return NULL; 3544 | } 3545 | init = createFunctionValueObject(stmt); 3546 | if (!init) return NULL; 3547 | if (!createScopeValue(scope, dest, stmt->name)) { 3548 | deleteValueObject(init); 3549 | return NULL; 3550 | } 3551 | if (!updateScopeValue(scope, dest, stmt->name, init)) { 3552 | deleteValueObject(init); 3553 | return NULL; 3554 | } 3555 | return createReturnObject(RT_DEFAULT, NULL); 3556 | } 3557 | 3558 | /** 3559 | * Interprets an expression statement. 3560 | * 3561 | * \param [in] node The statement to interpret. 3562 | * 3563 | * \param [in] scope The scope to evaluate \a node under. 3564 | * 3565 | * \pre \a node contains a statement created by createExprNode(). 3566 | * 3567 | * \post The implicit variable of \a scope will be set the the value of \a node 3568 | * evaluated under \a scope. 3569 | * 3570 | * \return A pointer to a default return value. 3571 | * 3572 | * \retval NULL An error occurred during interpretation. 3573 | */ 3574 | ReturnObject *interpretExprStmtNode(StmtNode *node, 3575 | ScopeObject *scope) 3576 | { 3577 | /* Set the implicit variable to the result of the expression */ 3578 | ExprNode *expr = (ExprNode *)node->stmt; 3579 | deleteValueObject(scope->impvar); 3580 | scope->impvar = interpretExprNode(expr, scope); 3581 | if (!scope->impvar) return NULL; 3582 | return createReturnObject(RT_DEFAULT, NULL); 3583 | } 3584 | 3585 | /** 3586 | * Interprets an alternate array definition statement. 3587 | * 3588 | * \param [in] node The statement to interpret. 3589 | * 3590 | * \param [in] scope The scope to evaluate \a node under. 3591 | * 3592 | * \pre \a node contains a statement created by createAltArrayDefNode(). 3593 | * 3594 | * \return A pointer to a default return value. 3595 | * 3596 | * \retval NULL An error occurred during interpretation. 3597 | */ 3598 | ReturnObject *interpretAltArrayDefStmtNode(StmtNode *node, 3599 | ScopeObject *scope) 3600 | { 3601 | AltArrayDefStmtNode *stmt = (AltArrayDefStmtNode *)node->stmt; 3602 | ValueObject *init = NULL; 3603 | ScopeObject *dest = scope; 3604 | ReturnObject *ret = NULL; 3605 | if (getScopeValueLocal(scope, dest, stmt->name)) { 3606 | IdentifierNode *id = (IdentifierNode *)(stmt->name); 3607 | char *name = resolveIdentifierName(id, scope); 3608 | if (name) { 3609 | fprintf(stderr, "%s:%u: redefinition of existing variable at: %s\n", id->fname, id->line, name); 3610 | free(name); 3611 | } 3612 | return NULL; 3613 | } 3614 | if (stmt->parent) { 3615 | ScopeObject *parent = getScopeObject(scope, scope, stmt->parent); 3616 | if (!parent) return NULL; 3617 | init = createArrayValueObject(parent); 3618 | } 3619 | else { 3620 | init = createArrayValueObject(scope); 3621 | } 3622 | if (!init) return NULL; 3623 | 3624 | /* Populate the array body */ 3625 | ret = interpretStmtNodeList(stmt->body->stmts, getArray(init)); 3626 | if (!ret) { 3627 | deleteValueObject(init); 3628 | return NULL; 3629 | } 3630 | deleteReturnObject(ret); 3631 | if (!createScopeValue(scope, dest, stmt->name)) { 3632 | deleteValueObject(init); 3633 | return NULL; 3634 | } 3635 | if (!updateScopeValue(scope, dest, stmt->name, init)) { 3636 | deleteValueObject(init); 3637 | return NULL; 3638 | } 3639 | return createReturnObject(RT_DEFAULT, NULL); 3640 | } 3641 | 3642 | /* 3643 | * A jump table for statements. The index of a function in the table is given 3644 | * by its its index in the enumerated StmtType type. 3645 | */ 3646 | static ReturnObject *(*StmtJumpTable[14])(StmtNode *, ScopeObject *) = { 3647 | interpretCastStmtNode, 3648 | interpretPrintStmtNode, 3649 | interpretInputStmtNode, 3650 | interpretAssignmentStmtNode, 3651 | interpretDeclarationStmtNode, 3652 | interpretIfThenElseStmtNode, 3653 | interpretSwitchStmtNode, 3654 | interpretBreakStmtNode, 3655 | interpretReturnStmtNode, 3656 | interpretLoopStmtNode, 3657 | interpretDeallocationStmtNode, 3658 | interpretFuncDefStmtNode, 3659 | interpretExprStmtNode, 3660 | interpretAltArrayDefStmtNode }; 3661 | 3662 | /** 3663 | * Interprets a statement. 3664 | * 3665 | * \param [in] node The statement to interpret. 3666 | * 3667 | * \param [in] scope The scope to evaluate \a node under. 3668 | * 3669 | * \pre \a node contains a statement created by parseStmtNode(). 3670 | * 3671 | * \return A pointer to a return value set appropriately depending on the 3672 | * statement interpreted. 3673 | * 3674 | * \retval NULL An error occurred during interpretation. 3675 | */ 3676 | ReturnObject *interpretStmtNode(StmtNode *node, 3677 | ScopeObject *scope) 3678 | { 3679 | return StmtJumpTable[node->type](node, scope); 3680 | } 3681 | 3682 | /** 3683 | * Interprets a list of statements. 3684 | * 3685 | * \param [in] list The statements to interpret. 3686 | * 3687 | * \param [in] scope The scope to evaluate \a list under. 3688 | * 3689 | * \return A pointer to a return value set appropriately depending on the 3690 | * statements interpreted. 3691 | * 3692 | * \retval NULL An error occurred during interpretation. 3693 | */ 3694 | ReturnObject *interpretStmtNodeList(StmtNodeList *list, 3695 | ScopeObject *scope) 3696 | { 3697 | ReturnObject *ret = NULL; 3698 | unsigned int n; 3699 | for (n = 0; n < list->num; n++) { 3700 | ret = interpretStmtNode(list->stmts[n], scope); 3701 | if (!ret) 3702 | return NULL; 3703 | else if (ret->type == RT_BREAK || ret->type == RT_RETURN) 3704 | return ret; 3705 | else { 3706 | deleteReturnObject(ret); 3707 | ret = NULL; 3708 | } 3709 | } 3710 | if (!ret) ret = createReturnObject(RT_DEFAULT, NULL); 3711 | return ret; 3712 | } 3713 | 3714 | /** 3715 | * Interprets a block of code. 3716 | * 3717 | * \param [in] node The block of code to interpret. 3718 | * 3719 | * \param [in] scope The scope to evaluate \a block under. 3720 | * 3721 | * \pre \a block contains a block of code created by parseBlockNode(). 3722 | * 3723 | * \return A pointer to a return value set appropriately depending on the 3724 | * statements interpreted. 3725 | * 3726 | * \retval NULL An error occurred during interpretation. 3727 | */ 3728 | ReturnObject *interpretBlockNode(BlockNode *node, 3729 | ScopeObject *scope) 3730 | { 3731 | ReturnObject *ret = NULL; 3732 | ScopeObject *inner = createScopeObject(scope); 3733 | if (!inner) return NULL; 3734 | ret = interpretStmtNodeList(node->stmts, inner); 3735 | deleteScopeObject(inner); 3736 | return ret; 3737 | } 3738 | 3739 | /** 3740 | * Interprets a the main block of code. 3741 | * 3742 | * \param [in] main The main block of code to interpret. 3743 | * 3744 | * \pre \a main contains a block of code created by parseMainNode(). 3745 | * 3746 | * \return The final status of the program. 3747 | * 3748 | * \retval 0 \a main was interpreted without any errors. 3749 | * 3750 | * \retval 1 An error occurred while interpreting \a main. 3751 | */ 3752 | int interpretMainNode(MainNode *main) 3753 | { 3754 | ReturnObject *ret = NULL; 3755 | if (!main) return 1; 3756 | ret = interpretBlockNode(main->block, NULL); 3757 | if (!ret) return 1; 3758 | deleteReturnObject(ret); 3759 | return 0; 3760 | } 3761 | --------------------------------------------------------------------------------