├── .clang-format ├── .gitignore ├── LICENCE ├── README.md └── src ├── Makefile ├── common ├── bytecode.h ├── opcodes.c └── opcodes.h ├── compiler ├── README.md └── src │ ├── codegen.c │ ├── codegen.h │ ├── compiler.c │ ├── compiler.h │ ├── dot │ ├── .png │ ├── Vararg.png │ ├── adadadad.png │ ├── array.dot │ ├── array.png │ ├── arrays.dot │ ├── arrays.png │ ├── asdasd.png │ ├── classTest.png │ ├── compound_assignment.dot │ ├── compound_assignment.png │ ├── expression_group.png │ ├── func.png │ ├── function_definition.png │ ├── function_expression.dot │ ├── function_expression.png │ ├── function_expression_1.dot │ ├── function_expression_1.png │ ├── function_test1.png │ ├── function_type.png │ ├── generic_loop.png │ ├── local_assign.dot │ ├── local_assign.png │ ├── local_func.png │ ├── local_function.png │ ├── name_reference_test.dot │ ├── name_reference_test.png │ ├── print.dot │ ├── print.png │ ├── print_test.dot │ ├── print_test.png │ ├── simpleLocalTest.png │ ├── simpleVararg.png │ ├── singleass.png │ ├── table_constructor.dot │ ├── table_constructor.png │ ├── table_test.dot │ ├── table_test.png │ ├── tables.dot │ ├── tables.png │ ├── tt.png │ ├── type_annotations.dot │ ├── type_annotations.png │ ├── uneven_local_definition.dot │ └── uneven_local_definition.png │ ├── ir.c │ ├── ir.h │ ├── lexer.h │ ├── lexer.l │ ├── macro.c │ ├── macro.h │ ├── main.c │ ├── node.c │ ├── node.h │ ├── parser.h │ ├── parser.y │ ├── symbol.c │ ├── symbol.h │ ├── tests │ ├── graphviz.sh │ ├── ir │ │ ├── hello.lua │ │ └── helloworld.lua │ └── type │ │ ├── binary.lua │ │ ├── block.lua │ │ ├── call.lua │ │ ├── forgeneric.lua │ │ ├── fornumeric.lua │ │ ├── function.lua │ │ ├── functions.lua │ │ ├── if.lua │ │ ├── localassign.lua │ │ ├── locals.lua │ │ ├── tables.lua │ │ └── unary.lua │ ├── type.c │ ├── type.h │ └── util │ ├── flexstr.c │ ├── flexstr.h │ ├── hashmap.c │ └── hashmap.h ├── interpreter ├── main.c └── tests │ ├── arrays.lua │ ├── class.lua │ ├── compare.lua │ ├── compound.lua │ ├── function.lua │ ├── ifelse.lua │ ├── increment.lua │ ├── locals.lua │ ├── macros │ └── lenient.lua │ ├── return.lua │ ├── table.lua │ ├── test.lua │ └── userTest.lua └── vm ├── README.md ├── src ├── execute.c ├── load.c ├── lua │ ├── Makefile │ ├── lapi.c │ ├── lapi.h │ ├── lauxlib.c │ ├── lauxlib.h │ ├── lbaselib.c │ ├── ldblib.c │ ├── ldebug.c │ ├── ldebug.h │ ├── ldo.c │ ├── ldo.h │ ├── lfunc.c │ ├── lfunc.h │ ├── lgc.c │ ├── lgc.h │ ├── linit.c │ ├── liolib.c │ ├── llimits.h │ ├── lmathlib.c │ ├── lmem.c │ ├── lmem.h │ ├── lobject.c │ ├── lobject.h │ ├── lopcodes.c │ ├── lopcodes.h │ ├── loslib.c │ ├── lstate.c │ ├── lstate.h │ ├── lstring.c │ ├── lstring.h │ ├── lstrlib.c │ ├── ltable.c │ ├── ltable.h │ ├── ltablib.c │ ├── ltm.c │ ├── ltm.h │ ├── lua.h │ ├── luaconf.h │ ├── lualib.h │ ├── lvm.c │ ├── lvm.h │ ├── lzio.c │ ├── lzio.h │ └── print.c ├── main.c └── util │ ├── spooky.c │ └── spooky.h └── tests ├── incorrect_version.bin ├── negativenum.bin ├── string_table.bin └── test.bin /.clang-format: -------------------------------------------------------------------------------- 1 | # https://clang.llvm.org/docs/ClangFormatStyleOptions.html 2 | 3 | BasedOnStyle: LLVM 4 | IndentWidth: 4 5 | ColumnLimit: 100 6 | 7 | BreakBeforeBraces: Custom 8 | BraceWrapping: 9 | AfterFunction: true 10 | IndentCaseLabels: true -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore the directory for all of the binary and dot files 2 | src/bin 3 | src/compiler/src/dot/*.dot 4 | 5 | # Ignore all Flex generated files 6 | src/compiler/src/lexer.yy.c 7 | src/compiler/src/lexer.yy.h 8 | 9 | # Ignore all Bison generated files 10 | src/compiler/src/parser.tab.c 11 | src/compiler/src/parser.tab.h 12 | parser.output 13 | 14 | # Ignore all VS Code generated files 15 | .vscode/ -------------------------------------------------------------------------------- /LICENCE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Lua++ 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Lua++ programming language 2 | This is the Lua++ C lang build, currently in development but is soon to be completed. If you are interested in learning more about this project, please visit our website: [luaplusplus.org](https://www.luaplusplus.org). This codebase is not specifically tweaked to a certain compiler, so any C/C++ compiler should be able to build this project easily. Personally, I recommend building it with ```gcc``` although ```clang``` or ```MSVSC``` would also work fine. 3 | 4 | Disclamer 5 | > Lua++ is still under heavy development so when you are testing the programming language keep that in mind. There are a LOT of minor bugs spread around in the codebase so don't expect a production ready application. Otherwise, thank you for showing interest in Lua++. 6 | 7 | ### How to use 8 | 1. Make sure that you have ``make``, ``flex``, and ``bison`` installed. To install them on a Linux machine run the following commands: 9 | ``` 10 | sudo apt update 11 | sudo apt install flex 12 | sudo apt install bison 13 | sudo apt install make 14 | ``` 15 | 2. Enter the main source folder and build the desired project (e.g. ```make interpreter```) 16 | 3. Then run the binary that was produced by this command 17 | ``` 18 | ./bin/luapp 19 | ... 20 | ``` 21 | 22 | ### Compiler 23 | > Note: compiler development moved to [lorraine](https://github.com/luapp-org/lorraine). 24 | 25 | The current complier is very user friendly. It consists of four stages: ``lexer``, ``parser``, ``ir``, and ``codegen``. These are all toggable via the ``-s`` command line argument. This gives you the ability to inspect each stage of the compiler in detail. The usage for the compiler binary is provided below: 26 | ``` 27 | luappc -s [lexer|parser|type|symbol|ir|codgen] -o [outputfile] [inputfile] 28 | 29 | -s : indicates the name of the stage to stop after. 30 | Defaults to the last stage. 31 | -o : name of the output file. Defaults to "output.s" 32 | 33 | You should pass the name of the file to compile. 34 | ``` 35 | -------------------------------------------------------------------------------- /src/Makefile: -------------------------------------------------------------------------------- 1 | # Make out directory (bin/) 2 | OUTDIR = bin 3 | $(shell mkdir -p $(OUTDIR)) 4 | 5 | %.yy.c : %.l 6 | flex --header-file=$(subst .yy.c,.yy.h,$@) -o $@ $< 7 | 8 | %.tab.c : %.y 9 | bison -d $< 10 | 11 | mv parser.tab.h compiler/src 12 | mv parser.tab.c compiler/src 13 | 14 | COMPILER_CORE = compiler/src/lexer.yy.c compiler/src/parser.tab.c compiler/src/compiler.c compiler/src/node.c compiler/src/util/flexstr.c compiler/src/util/hashmap.c compiler/src/type.c compiler/src/symbol.c compiler/src/ir.c compiler/src/codegen.c compiler/src/macro.c common/opcodes.c 15 | VM_CORE = vm/src/load.c vm/src/execute.c vm/src/lua/*.c vm/src/util/*.c 16 | 17 | COMPILER_OBJS = compiler/src/main.c ${COMPILER_CORE} 18 | VM_OBJS = vm/src/main.c ${VM_CORE} common/opcodes.c 19 | INTERPRETER_OBJS = interpreter/main.c ${COMPILER_CORE} ${VM_CORE} 20 | 21 | compiler: $(COMPILER_OBJS) 22 | gcc -o ${OUTDIR}/luappc $^ -lm 23 | 24 | # runtime -> vm 25 | runtime: $(VM_OBJS) 26 | gcc -o ${OUTDIR}/luappvm $^ -lm 27 | 28 | interpreter: $(INTERPRETER_OBJS) 29 | gcc -o ${OUTDIR}/luapp $^ -lm 30 | 31 | 32 | .PHONY: interpreter runtime compiler -------------------------------------------------------------------------------- /src/common/bytecode.h: -------------------------------------------------------------------------------- 1 | #ifndef _BYTECODE_H 2 | #define _BYTECODE_H 3 | 4 | #include 5 | 6 | typedef enum bytecode_version 7 | { 8 | VERSION_0, 9 | VERSION_1 10 | } version_t; 11 | 12 | /* Max and min versions that will successfully run in the VM */ 13 | #define MAX_VERSION VERSION_1 14 | #define MIN_VERSION VERSION_1 15 | 16 | /* Acceptable bytecode version */ 17 | #define VERSION_ACCEPTABLE(version) (version >= MIN_VERSION && version <= MAX_VERSION) 18 | 19 | typedef enum constant_type 20 | { 21 | CONSTANT_NIL, 22 | CONSTANT_BOOLEAN, 23 | CONSTANT_NUMBER, 24 | CONSTANT_STRING, 25 | CONSTANT_ENVIRONMENT, 26 | CONSTANT_ARRAY 27 | } constant_t; 28 | 29 | #endif -------------------------------------------------------------------------------- /src/common/opcodes.c: -------------------------------------------------------------------------------- 1 | #include "opcodes.h" 2 | 3 | const char *const opcode_names[NUM_OPCODES + 1] = { 4 | "MOVE", "LOADPN", "LOADNN", "LOADK", "LOADKX", "LOADBOOL", "LOADNIL", 5 | "GETUPVAL", "GETENV", "GETGLOBAL", "GETTABLE", "GETTABLEN", "SETGLOBAL", "SETUPVAL", 6 | "SETTABLE", "NEWTABLE", "SELF", "ADD", "SUB", "MUL", "DIV", 7 | "MOD", "POW", "ADDK", "SUBK", "MULK", "DIVK", "MODK", 8 | "POWK", "UNM", "NOT", "LEN", "CONCAT", "JMPBACK", "TEST", 9 | "TESTSET", "CALL", "TAILCALL", "RETURN", "FORLOOP", "FORPREP", "TFORLOOP", 10 | "SETLIST", "CLOSE", "CLOSURE", "VARARGPREP", "NEJMP", "EQJMP", "LTJMP", 11 | "LEJMP", "JMPIF", "JMPIFNOT", "VARARG", "NOP", NULL}; 12 | -------------------------------------------------------------------------------- /src/common/opcodes.h: -------------------------------------------------------------------------------- 1 | #ifndef _OPCODES_H 2 | #define _OPCODES_H 3 | 4 | #include 5 | #include 6 | 7 | #if defined(luaall_c) 8 | #define LUAI_FUNC static 9 | #define LUAI_DATA /* empty */ 10 | 11 | #elif defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 302) && defined(__ELF__) 12 | #define LUAI_FUNC __attribute__((visibility("hidden"))) extern 13 | #define LUAI_DATA LUAI_FUNC 14 | 15 | #else 16 | #define LUAI_FUNC extern 17 | #define LUAI_DATA extern 18 | #endif 19 | 20 | /* Main file for instruction manipulation */ 21 | enum opcode { 22 | OP_MOVE, 23 | 24 | /* OP_LOADPN: sets a target register to a positive number literal 25 | * A: target register 26 | * D: the value (0 .. 65535) 27 | */ 28 | OP_LOADPN, 29 | 30 | /* OP_LOADNN: sets a target register to a negative number literal 31 | * A: target register 32 | * D: the value (65535 .. 0) 33 | * 34 | * Note: The D operand is represented as an unsigned 35 | */ 36 | OP_LOADNN, 37 | OP_LOADK, 38 | 39 | /* OP_LOADKX: loads a constant from the constant list into a register 40 | * A: target register 41 | * SUB: the index in the constant table 42 | */ 43 | OP_LOADKX, 44 | 45 | OP_LOADBOOL, 46 | OP_LOADNIL, 47 | OP_GETUPVAL, 48 | 49 | /* OP_GETENV: retrieves an object defined in the environment table. 50 | * A: target register 51 | * D: index in the constant table 52 | */ 53 | OP_GETENV, 54 | 55 | OP_GETGLOBAL, 56 | OP_GETTABLE, 57 | 58 | /* OP_GETTABLEN: gets a value in a table with key as number (arrays) 59 | * A: result register 60 | * B: table register 61 | * C: index number (0 .. 256) 62 | */ 63 | OP_GETTABLEN, 64 | 65 | OP_SETGLOBAL, 66 | OP_SETUPVAL, 67 | OP_SETTABLE, 68 | 69 | OP_NEWTABLE, 70 | 71 | OP_SELF, 72 | 73 | OP_ADD, 74 | OP_SUB, 75 | OP_MUL, 76 | OP_DIV, 77 | OP_MOD, 78 | OP_POW, 79 | 80 | /* OP_Ks: sets a target register to an arithmetic operation of two integers 81 | * A: target register 82 | * B: register containing first arg 83 | * C: constant index (0 to 255) 84 | */ 85 | OP_ADDK, 86 | OP_SUBK, 87 | OP_MULK, 88 | OP_DIVK, 89 | OP_MODK, 90 | OP_POWK, 91 | 92 | OP_UNM, 93 | OP_NOT, 94 | OP_LEN, 95 | 96 | OP_CONCAT, 97 | 98 | /* OP_JMPBACK: jumps back x instructions 99 | * E: amount of instructions to jump 100 | */ 101 | OP_JMPBACK, 102 | 103 | OP_TEST, 104 | OP_TESTSET, 105 | 106 | OP_CALL, 107 | OP_TAILCALL, 108 | OP_RETURN, 109 | 110 | OP_FORLOOP, 111 | OP_FORPREP, 112 | 113 | OP_TFORLOOP, 114 | OP_SETLIST, 115 | 116 | OP_CLOSE, 117 | OP_CLOSURE, 118 | 119 | /* OP_VARARGPREP: prepare stack for variadic functions 120 | * A: number of fixed arguments 121 | */ 122 | OP_VARARGPREP, 123 | 124 | /* OP_EQJMP: compares two registers, jumps if equal 125 | * A: result 126 | * B: first register 127 | * C: second register 128 | * SUB: pc jump size 129 | */ 130 | OP_NEJMP, 131 | OP_EQJMP, 132 | 133 | /* OP_LTJMP: compares two registers, jumps if less than 134 | * A: result 135 | * B: first register 136 | * C: second register 137 | * SUB: pc jump size 138 | */ 139 | OP_LTJMP, 140 | 141 | /* OP_LTJMP: compares two registers, jumps if less than or equals 142 | * A: result 143 | * B: first register 144 | * C: second register 145 | * SUB: pc jump size 146 | */ 147 | OP_LEJMP, 148 | 149 | /* OP_JMPIF: performs a jump if R(A) is true 150 | * A: register 151 | * D: jump 152 | */ 153 | OP_JMPIF, 154 | 155 | /* OP_JMPIFNOT: performs a jump if R(A) is not true 156 | * A: register 157 | * D: jump 158 | */ 159 | OP_JMPIFNOT, 160 | 161 | OP_VARARG, 162 | OP_NOP 163 | }; 164 | 165 | /* Retrieve the one byte instruction operation code */ 166 | #define GET_OPCODE(i) ((i)&0xFF) 167 | 168 | /* iABC 169 | * A: 8 bits 170 | * B: 8 bits 171 | * C: 8 bits 172 | */ 173 | #define GETARG_A(i) (((i) >> 8) & 0xFF) 174 | #define GETARG_B(i) (((i) >> 16) & 0xFF) 175 | #define GETARG_C(i) (((i) >> 24) & 0xFF) 176 | 177 | /* iAD 178 | * A: 8 bits 179 | * D: 16 bits 180 | */ 181 | #define GETARG_D(i) ((int32_t)i >> 16) 182 | 183 | /* iADu 184 | * A: 8 bits 185 | * D: 16 bits (unsigned) 186 | */ 187 | #define GETARG_Du(i) (((uint32_t)i >> 16)) 188 | 189 | /* iE 190 | * E: 24 bits 191 | */ 192 | #define GETARG_E(i) ((int32_t)i >> 8) 193 | 194 | #define CREATE_iABC(i, a, b, c) ((uint32_t)i | (a << 8) | (b << 16) | (c << 24)) 195 | #define CREATE_iAD(i, a, d) ((uint32_t)i | (a << 8) | ((uint16_t)d << 16)) 196 | #define CREATE_iADu(i, a, du) ((uint32_t)i | (a << 8) | ((int16_t)du << 16)) 197 | #define CREATE_iE(i, e) ((uint32_t)i | ((uint32_t)e << 8)) 198 | 199 | #define NUM_OPCODES (int32_t) OP_NOP + 1 200 | 201 | LUAI_DATA const char *const opcode_names[NUM_OPCODES + 1]; 202 | 203 | typedef enum opcode_mode { iABC, iAD, iADu, iE, SUB } opcode_t; 204 | 205 | /* Number of list items to accumulate before a SETLIST instruction */ 206 | #define LFIELDS_PER_FLUSH 50 207 | 208 | #endif -------------------------------------------------------------------------------- /src/compiler/README.md: -------------------------------------------------------------------------------- 1 | ## Lua++ Compiler 2 | The current folder contains all of the contents of the compiler (``luappc``). If you are interested in the codebase, take a look in ``src/``. 3 | 4 | > The current compiler will soon be replaced by lorraine. You can learn more about it [here](https://github.com/luapp-org/lorraine). 5 | 6 | ### Lua++ syntax in extented BNF 7 | Most of this is from [lua.org](https://www.lua.org/manual/5.1/manual.html#8), but I have added some modifications. Those are marked in the codebase. 8 | ``` 9 | chunk ::= {stat [`;´]} [laststat [`;´]] 10 | 11 | block ::= chunk 12 | 13 | stat ::= varlist assigntype explist | 14 | functioncall | 15 | do block end | 16 | while exp do block end | 17 | repeat block until exp | 18 | if exp then block {elseif exp then block} [else block] end | 19 | for var `=´ exp `,´ exp [`,´ exp] do block end | 20 | for namelist in explist do block end | 21 | function funcname funcbody | 22 | local function Name funcbody | 23 | local namelist [`=´ explist] 24 | 25 | laststat ::= return [explist] | break 26 | 27 | funcname ::= Name {`.´ Name} [`:´ Name] 28 | 29 | varlist ::= var {`,´ var} 30 | 31 | var ::= Name | prefixexp `[´ exp `]´ | prefixexp `.´ Name 32 | 33 | namelist ::= nametype {`,´ nametype} 34 | 35 | nametype ::= Name `:´ type 36 | 37 | type ::= number | string | boolean | Array `<´ type `>´ | Table `<´ type `,´ type `>´ 38 | 39 | explist ::= {exp `,´} exp 40 | 41 | exp ::= nil | false | true | Number | String | `...´ | function | 42 | prefixexp | tableconstructor | exp binop exp | unop exp 43 | 44 | prefixexp ::= var | functioncall | `(´ exp `)´ 45 | 46 | functioncall ::= prefixexp args | prefixexp `:´ Name args 47 | 48 | args ::= `(´ [explist] `)´ | tableconstructor | String 49 | 50 | function ::= function funcbody 51 | 52 | typelist ::= type {`,´ type} 53 | 54 | funcbody ::= `(´ [parlist] `)´ `:´ typelist block end 55 | 56 | parlist ::= namelist [`,´ `...´] | `...´ 57 | 58 | arrayconstructor = `{´ [exprlist] `}´ 59 | 60 | tableconstructor ::= `{´ [fieldlist] `}´ 61 | 62 | fieldlist ::= field {fieldsep field} [fieldsep] 63 | 64 | field ::= `[´ exp `]´ `=´ exp | Name `=´ exp | exp 65 | 66 | fieldsep ::= `,´ | `;´ 67 | 68 | binop ::= `+´ | `-´ | `*´ | `/´ | `^´ | `%´ | `..´ | 69 | `<´ | `<=´ | `>´ | `>=´ | `==´ | `~=´ | 70 | and | or 71 | 72 | unop ::= `-´ | not | `#´ 73 | 74 | assigntype ::= `=´ | `+=´ | `-=´ | `*=´ | `/=´ | `^=´ | `%=´ | `..=´ 75 | ``` 76 | -------------------------------------------------------------------------------- /src/compiler/src/codegen.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | /* Common includes */ 7 | #include "../../common/bytecode.h" 8 | 9 | #include "codegen.h" 10 | #include "ir.h" 11 | #include "symbol.h" 12 | #include "type.h" 13 | 14 | void codegen_write_byte(FILE *output, unsigned char value) 15 | { 16 | fwrite(&value, sizeof(value), 1, output); 17 | } 18 | 19 | void codegen_write_int(FILE *output, unsigned int value) 20 | { 21 | fwrite(&value, sizeof(value), 1, output); 22 | } 23 | 24 | void codegen_write_double(FILE *output, double value) { fwrite(&value, sizeof(value), 1, output); } 25 | 26 | void codegen_write_size(FILE *output, unsigned int value) 27 | { 28 | do { 29 | codegen_write_byte(output, (value & 127) | ((value > 127) << 7)); 30 | value >>= 7; 31 | } while (value); 32 | } 33 | 34 | void codegen_write_string(FILE *output, char *value) 35 | { 36 | int size = strlen(value); 37 | codegen_write_size(output, size); 38 | 39 | /* Write each character individually */ 40 | for (int i = 0; i < size; i++) 41 | codegen_write_byte(output, value[i]); 42 | } 43 | 44 | void codegen_write_symbol_table(FILE *output, struct symbol_table *table) 45 | { 46 | codegen_write_size(output, table->size); 47 | 48 | for (struct symbol_list *iter = table->first; iter != NULL; iter = iter->next) 49 | codegen_write_string(output, iter->symbol.name); 50 | } 51 | 52 | void codegen_write_proto(FILE *output, struct ir_proto *proto) 53 | { 54 | /* Write the important information about the function */ 55 | codegen_write_byte(output, proto->max_stack_size); 56 | codegen_write_byte(output, proto->parameters_size); 57 | codegen_write_byte(output, proto->upvalues_size); 58 | codegen_write_byte(output, proto->is_vararg); 59 | 60 | codegen_write_size(output, proto->code->size); 61 | 62 | /* Write all of the instructions to the stream */ 63 | for (struct ir_instruction *iter = proto->code->first; iter != NULL; iter = iter->next) 64 | codegen_write_int(output, iter->value); 65 | 66 | codegen_write_size(output, proto->constant_list->size); 67 | 68 | int id = 0; 69 | for (struct ir_constant *iter = proto->constant_list->first; iter != NULL; iter = iter->next) { 70 | codegen_write_byte(output, iter->type); 71 | /* Write individual constants */ 72 | switch (iter->type) { 73 | case CONSTANT_STRING: 74 | codegen_write_size(output, iter->data.symbol.symbol_id + 1); 75 | break; 76 | case CONSTANT_ENVIRONMENT: 77 | codegen_write_int(output, iter->data.env.index); 78 | break; 79 | case CONSTANT_NUMBER: 80 | codegen_write_double(output, iter->data.number.value); 81 | break; 82 | } 83 | } 84 | 85 | codegen_write_size(output, proto->proto_size); 86 | 87 | for (uint32_t i = 0; i < proto->proto_size; ++i) 88 | codegen_write_size(output, proto->protos[i]); 89 | } 90 | 91 | void codegen_write_program(FILE *output, struct ir_context *context) 92 | { 93 | /* Write bytecode version */ 94 | codegen_write_byte(output, VERSION_1); 95 | 96 | codegen_write_symbol_table(output, context->table); 97 | 98 | /* Write the proto list to the stream */ 99 | codegen_write_size(output, context->protos->size); 100 | 101 | for (struct ir_proto *iter = context->protos->first; iter != NULL; iter = iter->next) 102 | codegen_write_proto(output, iter); 103 | 104 | /* The main function is always the last in the list */ 105 | codegen_write_size(output, context->protos->size - 1); 106 | 107 | fprintf(output, "\n\n"); 108 | } -------------------------------------------------------------------------------- /src/compiler/src/codegen.h: -------------------------------------------------------------------------------- 1 | #ifndef _CODEGEN_H 2 | #define _CODEGEN_H 3 | 4 | #include 5 | 6 | struct ir_context; 7 | 8 | void codegen_write_program(FILE *output, struct ir_context *context); 9 | 10 | #endif -------------------------------------------------------------------------------- /src/compiler/src/compiler.c: -------------------------------------------------------------------------------- 1 | /* compiler.c - only version 2 | * all utilities used throughout the compiler 3 | */ 4 | 5 | #include "compiler.h" 6 | #include "codegen.h" 7 | #include "ir.h" 8 | #include "lexer.h" 9 | #include "macro.h" 10 | #include "node.h" 11 | #include "parser.h" 12 | #include "symbol.h" 13 | #include "type.h" 14 | 15 | #include 16 | 17 | /* compiler_error - prints a compiler error to stdout based on params 18 | * args: location of error, format, args 19 | * rets: none 20 | */ 21 | void compiler_error(YYLTYPE location, const char *format, ...) 22 | { 23 | va_list ap; 24 | 25 | if (location.first_line == location.last_line) 26 | printf("Error (%d, %d-%d): ", location.first_line, location.first_column, 27 | location.last_column); 28 | else 29 | printf("Error (%d-%d, %d-%d): ", location.first_line, location.last_line, 30 | location.first_column, location.last_column); 31 | 32 | va_start(ap, format); 33 | vprintf(format, ap); 34 | va_end(ap); 35 | printf("\n"); 36 | } 37 | 38 | /* lcompiler_error - prints a compiler error to stdout based on params (no location) 39 | * args: format, args 40 | * rets: none 41 | */ 42 | void lcompiler_error(const char *format, ...) 43 | { 44 | va_list ap; 45 | printf("Error: "); 46 | va_start(ap, format); 47 | vprintf(format, ap); 48 | va_end(ap); 49 | printf("\n"); 50 | } 51 | 52 | /* clear - clears the given string 53 | * args: string 54 | * rets: none 55 | */ 56 | void clear(char arr[]) 57 | { 58 | int length = strlen(arr); 59 | /* remove all of the characters in the string */ 60 | memmove(arr, arr + length, length + 1); 61 | } 62 | 63 | /* compile() - compiles a file pointer of lua++ bytecode 64 | * args: context, input file, output file 65 | * returns: 1 on success 0 on failure 66 | * 67 | * Note: If the compiler fails on a stage, it will be saved in context->stage. So will the elapsed 68 | * time_t for the entire compilation process. 69 | */ 70 | bool compile(compiler_context_t *context, FILE *input, FILE *output) 71 | { 72 | context->error_count = 0; 73 | context->time = clock(); 74 | 75 | /* Run macro check */ 76 | macro_init(context, input); 77 | 78 | if (context->error_count) { 79 | context->time = clock() - context->time; 80 | context->stage = "macro"; 81 | return false; 82 | } 83 | 84 | /* Stop at macro stage if provided */ 85 | if (strcmp(context->stage, "macro") == 0) { 86 | macro_print(context); 87 | return true; 88 | } 89 | 90 | yyscan_t lexer; 91 | lex_init(&lexer, context, input); 92 | 93 | /* Stop at lexer stage if provided */ 94 | if (strcmp(context->stage, "lexer") == 0) { 95 | context->error_count = 0; 96 | context->time = clock(); 97 | 98 | lex_print(lexer, &context->error_count, output); 99 | lex_destroy(&lexer); 100 | 101 | context->time = clock() - context->time; /* elapsed */ 102 | return context->error_count ? false : true; 103 | } 104 | 105 | struct node *tree = parser_parse(&context->error_count, lexer); 106 | lex_destroy(&lexer); 107 | 108 | if (!tree) { 109 | context->time = clock() - context->time; /* elapsed */ 110 | context->stage = "parser"; 111 | return false; 112 | } 113 | 114 | /* Stop at parser stage if provided */ 115 | if (strcmp("parser", context->stage) == 0) { 116 | print_ast(output, tree, true); 117 | 118 | context->time = clock() - context->time; 119 | return true; 120 | } 121 | 122 | struct type_context type_context = {context->is_strict, context->is_c_array, 0}; 123 | type_init(&type_context); 124 | 125 | /* Run the type checker, it's needed for all later passes */ 126 | type_ast_traversal(&type_context, tree, true); 127 | context->error_count = type_context.error_count; 128 | 129 | if (context->error_count) { 130 | context->time = clock() - context->time; 131 | context->stage = "type"; 132 | 133 | type_destroy(&type_context); 134 | return false; 135 | } 136 | 137 | /* Stop at type stage if provided */ 138 | if (strcmp("type", context->stage) == 0) { 139 | print_ast(output, tree, true); 140 | 141 | type_destroy(&type_context); 142 | 143 | context->time = clock() - context->time; 144 | return true; 145 | } 146 | 147 | type_destroy(&type_context); 148 | 149 | struct symbol_table symbol_table; 150 | symbol_initialize_table(&symbol_table); 151 | 152 | struct symbol_context symbol_context = {&symbol_table, 0}; 153 | 154 | symbol_ast_traversal(&symbol_context, tree); 155 | context->error_count = symbol_context.error_count; 156 | 157 | if (context->error_count) { 158 | context->time = clock() - context->time; 159 | context->stage = "symbol"; 160 | 161 | return false; 162 | } 163 | 164 | /* Stop at type symbol if provided */ 165 | if (strcmp("symbol", context->stage) == 0) { 166 | symbol_print_table(output, &symbol_table); 167 | 168 | context->time = clock() - context->time; 169 | return false; 170 | } 171 | 172 | struct ir_context ir_context = {0, &symbol_table}; 173 | ir_init(&ir_context); 174 | 175 | ir_context.protos = ir_build(&ir_context, tree); 176 | context->error_count = ir_context.error_count; 177 | 178 | ir_destroy(&ir_context); 179 | 180 | if (context->error_count) { 181 | context->time = clock() - context->time; 182 | context->stage = "ir"; 183 | 184 | return false; 185 | } 186 | 187 | if (strcmp("ir", context->stage) == 0) { 188 | ir_print_context(output, &ir_context); 189 | 190 | context->time = clock() - context->time; 191 | return tree; 192 | } 193 | 194 | codegen_write_program(output, &ir_context); 195 | return true; 196 | } 197 | 198 | /* usage - prints the usage for the program 199 | * args: none 200 | * rets: none 201 | */ 202 | void usage() 203 | { 204 | printf("luappc -s [lexer|parser|type|symbol|ir|codgen] -o [outputfile] [inputfile]\n\n"); 205 | printf(" -s : indicates the name of the stage to stop after.\n"); 206 | printf(" Defaults to the last stage.\n"); 207 | printf(" -o : name of the output file. Defaults to \"output.s\"\n\n"); 208 | printf("You should pass the name of the file to compile.\n"); 209 | } -------------------------------------------------------------------------------- /src/compiler/src/compiler.h: -------------------------------------------------------------------------------- 1 | #ifndef _COMPILER_H 2 | #define _COMPILER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "../../common/bytecode.h" 12 | #include "../../common/opcodes.h" 13 | 14 | #define COMPILER_VERSION "1.0" 15 | 16 | typedef struct node *YYSTYPE; 17 | #define YYSTYPE struct node * 18 | 19 | #if !defined YYLTYPE && !defined YYLTYPE_IS_DECLARED 20 | typedef struct YYLTYPE YYLTYPE; 21 | struct YYLTYPE { 22 | int first_line; 23 | int first_column; 24 | int last_line; 25 | int last_column; 26 | }; 27 | #define YYLTYPE_IS_DECLARED 1 28 | #define YYLTYPE_IS_TRIVIAL 1 29 | #endif 30 | 31 | typedef struct compiler_context { 32 | char *stage; 33 | int error_count; 34 | time_t time; 35 | 36 | /* Compiler settings */ 37 | bool is_strict; /* Strict type context */ 38 | bool is_c_array; /* Arrays start at 0 not 1 */ 39 | bool is_c_comment; /* C-style comments (//) */ 40 | } compiler_context_t; 41 | 42 | void compiler_error(YYLTYPE location, const char *format, ...); 43 | void lcompiler_error(const char *format, ...); 44 | 45 | bool compile(compiler_context_t *context, FILE *input, FILE *output); 46 | 47 | const char *token_to_string(int token); 48 | void clear(char arr[]); 49 | void usage(); 50 | 51 | #endif -------------------------------------------------------------------------------- /src/compiler/src/dot/.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luapp-org/luapp/9188cc373fdabd07161eb6d2acdd5156ebb2eb2a/src/compiler/src/dot/.png -------------------------------------------------------------------------------- /src/compiler/src/dot/Vararg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luapp-org/luapp/9188cc373fdabd07161eb6d2acdd5156ebb2eb2a/src/compiler/src/dot/Vararg.png -------------------------------------------------------------------------------- /src/compiler/src/dot/adadadad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luapp-org/luapp/9188cc373fdabd07161eb6d2acdd5156ebb2eb2a/src/compiler/src/dot/adadadad.png -------------------------------------------------------------------------------- /src/compiler/src/dot/array.dot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luapp-org/luapp/9188cc373fdabd07161eb6d2acdd5156ebb2eb2a/src/compiler/src/dot/array.dot -------------------------------------------------------------------------------- /src/compiler/src/dot/array.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luapp-org/luapp/9188cc373fdabd07161eb6d2acdd5156ebb2eb2a/src/compiler/src/dot/array.png -------------------------------------------------------------------------------- /src/compiler/src/dot/arrays.dot: -------------------------------------------------------------------------------- 1 | digraph G 2 | { 3 | node[fontname=Monospace] 4 | n0[label="program"] 5 | n1[label="local"] 6 | n0->n1 7 | n2[label="type annotation"] 8 | n1->n2 9 | n3[label="identifier\n\"a\""] 10 | n2->n3 11 | n4[label="Array"] 12 | n4[color=green3] 13 | n4[fontcolor=green3] 14 | n2->n4 15 | n5[label="array_constructor"] 16 | n1->n5 17 | n6[label="number\n\"3.000000\""] 18 | n5->n6 19 | n7[label="number\n\"2.000000\""] 20 | n5->n7 21 | n8[label="number\n\"1.000000\""] 22 | n5->n8 23 | } 24 | -------------------------------------------------------------------------------- /src/compiler/src/dot/arrays.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luapp-org/luapp/9188cc373fdabd07161eb6d2acdd5156ebb2eb2a/src/compiler/src/dot/arrays.png -------------------------------------------------------------------------------- /src/compiler/src/dot/asdasd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luapp-org/luapp/9188cc373fdabd07161eb6d2acdd5156ebb2eb2a/src/compiler/src/dot/asdasd.png -------------------------------------------------------------------------------- /src/compiler/src/dot/classTest.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luapp-org/luapp/9188cc373fdabd07161eb6d2acdd5156ebb2eb2a/src/compiler/src/dot/classTest.png -------------------------------------------------------------------------------- /src/compiler/src/dot/compound_assignment.dot: -------------------------------------------------------------------------------- 1 | digraph G 2 | { 3 | node[fontname=Monospace] 4 | n0[label="program"] 5 | n8[label="local"] 6 | n0->n8 7 | n9[label="type annotation"] 8 | n8->n9 9 | n10[label="identifier\n\"a\""] 10 | n9->n10 11 | n11[label="number"] 12 | n11[color=green3] 13 | n11[fontcolor=green3] 14 | n9->n11 15 | n12[label="number\n\"12.000000\""] 16 | n8->n12 17 | n13[label="assignment\n+="] 18 | n0->n13 19 | n14[label="identifier\n\"a\""] 20 | n13->n14 21 | n15[label="number\n\"12.000000\""] 22 | n13->n15 23 | n16[label="assignment\n-="] 24 | n0->n16 25 | n17[label="identifier\n\"a\""] 26 | n16->n17 27 | n18[label="number\n\"12.000000\""] 28 | n16->n18 29 | n19[label="assignment\n*="] 30 | n0->n19 31 | n20[label="identifier\n\"a\""] 32 | n19->n20 33 | n21[label="number\n\"2.000000\""] 34 | n19->n21 35 | n22[label="assignment\n/="] 36 | n0->n22 37 | n23[label="identifier\n\"a\""] 38 | n22->n23 39 | n24[label="number\n\"2.000000\""] 40 | n22->n24 41 | n25[label="assignment\n%="] 42 | n0->n25 43 | n26[label="identifier\n\"a\""] 44 | n25->n26 45 | n27[label="number\n\"4.000000\""] 46 | n25->n27 47 | n28[label="assignment\n^="] 48 | n0->n28 49 | n29[label="identifier\n\"a\""] 50 | n28->n29 51 | n30[label="number\n\"33333.000000\""] 52 | n28->n30 53 | n31[label="assignment\n..="] 54 | n0->n31 55 | n32[label="identifier\n\"a\""] 56 | n31->n32 57 | n33[label="string\n\"concat hahaha\""] 58 | n31->n33 59 | } 60 | -------------------------------------------------------------------------------- /src/compiler/src/dot/compound_assignment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luapp-org/luapp/9188cc373fdabd07161eb6d2acdd5156ebb2eb2a/src/compiler/src/dot/compound_assignment.png -------------------------------------------------------------------------------- /src/compiler/src/dot/expression_group.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luapp-org/luapp/9188cc373fdabd07161eb6d2acdd5156ebb2eb2a/src/compiler/src/dot/expression_group.png -------------------------------------------------------------------------------- /src/compiler/src/dot/func.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luapp-org/luapp/9188cc373fdabd07161eb6d2acdd5156ebb2eb2a/src/compiler/src/dot/func.png -------------------------------------------------------------------------------- /src/compiler/src/dot/function_definition.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luapp-org/luapp/9188cc373fdabd07161eb6d2acdd5156ebb2eb2a/src/compiler/src/dot/function_definition.png -------------------------------------------------------------------------------- /src/compiler/src/dot/function_expression.dot: -------------------------------------------------------------------------------- 1 | digraph G 2 | { 3 | node[fontname=Monospace] 4 | n0[label="program"] 5 | n1[label="call"] 6 | n0->n1 7 | n2[label="identifier\n\"print\""] 8 | n1->n2 9 | n3[label="function_body"] 10 | n1->n3 11 | n4[label="parameter_list"] 12 | n3->n4 13 | n5[label="type annotation"] 14 | n4->n5 15 | n6[label="identifier\n\"a\""] 16 | n5->n6 17 | n7[label="number"] 18 | n7[color=green3] 19 | n7[fontcolor=green3] 20 | n5->n7 21 | n8[label="type annotation"] 22 | n4->n8 23 | n9[label="identifier\n\"b\""] 24 | n8->n9 25 | n10[label="string"] 26 | n10[color=green3] 27 | n10[fontcolor=green3] 28 | n8->n10 29 | n12[label="call"] 30 | n3->n12 31 | n13[label="identifier\n\"print\""] 32 | n12->n13 33 | n14[label="string\n\"body\""] 34 | n12->n14 35 | } 36 | -------------------------------------------------------------------------------- /src/compiler/src/dot/function_expression.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luapp-org/luapp/9188cc373fdabd07161eb6d2acdd5156ebb2eb2a/src/compiler/src/dot/function_expression.png -------------------------------------------------------------------------------- /src/compiler/src/dot/function_expression_1.dot: -------------------------------------------------------------------------------- 1 | digraph G 2 | { 3 | node[fontname=Monospace] 4 | n0[label="program"] 5 | n1[label="call"] 6 | n0->n1 7 | n2[label="identifier\n\"print\""] 8 | n1->n2 9 | n3[label="function_body"] 10 | n1->n3 11 | n4[label="identifier\n\"a\""] 12 | n3->n4 13 | n5[label="identifier\n\"b\""] 14 | n3->n5 15 | n6[label="identifier\n\"c\""] 16 | n3->n6 17 | n7[label="identifier\n\"c\""] 18 | n3->n7 19 | } 20 | -------------------------------------------------------------------------------- /src/compiler/src/dot/function_expression_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luapp-org/luapp/9188cc373fdabd07161eb6d2acdd5156ebb2eb2a/src/compiler/src/dot/function_expression_1.png -------------------------------------------------------------------------------- /src/compiler/src/dot/function_test1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luapp-org/luapp/9188cc373fdabd07161eb6d2acdd5156ebb2eb2a/src/compiler/src/dot/function_test1.png -------------------------------------------------------------------------------- /src/compiler/src/dot/function_type.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luapp-org/luapp/9188cc373fdabd07161eb6d2acdd5156ebb2eb2a/src/compiler/src/dot/function_type.png -------------------------------------------------------------------------------- /src/compiler/src/dot/generic_loop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luapp-org/luapp/9188cc373fdabd07161eb6d2acdd5156ebb2eb2a/src/compiler/src/dot/generic_loop.png -------------------------------------------------------------------------------- /src/compiler/src/dot/local_assign.dot: -------------------------------------------------------------------------------- 1 | digraph G 2 | { 3 | node[fontname=Monospace] 4 | n0[label="program"] 5 | n1[label="local"] 6 | n0->n1 7 | n2[label="type annotation"] 8 | n1->n2 9 | n3[label="identifier\n\"a\""] 10 | n2->n3 11 | n4[label="number"] 12 | n4[color=green3] 13 | n4[fontcolor=green3] 14 | n2->n4 15 | n5[label="type annotation"] 16 | n1->n5 17 | n6[label="identifier\n\"b\""] 18 | n5->n6 19 | n7[label="string"] 20 | n7[color=green3] 21 | n7[fontcolor=green3] 22 | n5->n7 23 | n8[label="number\n\"12.000000\""] 24 | n1->n8 25 | n9[label="string\n\"hello\""] 26 | n1->n9 27 | } 28 | -------------------------------------------------------------------------------- /src/compiler/src/dot/local_assign.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luapp-org/luapp/9188cc373fdabd07161eb6d2acdd5156ebb2eb2a/src/compiler/src/dot/local_assign.png -------------------------------------------------------------------------------- /src/compiler/src/dot/local_func.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luapp-org/luapp/9188cc373fdabd07161eb6d2acdd5156ebb2eb2a/src/compiler/src/dot/local_func.png -------------------------------------------------------------------------------- /src/compiler/src/dot/local_function.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luapp-org/luapp/9188cc373fdabd07161eb6d2acdd5156ebb2eb2a/src/compiler/src/dot/local_function.png -------------------------------------------------------------------------------- /src/compiler/src/dot/name_reference_test.dot: -------------------------------------------------------------------------------- 1 | digraph G 2 | { 3 | node[fontname=Monospace] 4 | n0[label="program"] 5 | n1[label="call"] 6 | n0->n1 7 | n2[label="name_reference"] 8 | n1->n2 9 | n3[label="identifier\n\"print\""] 10 | n2->n3 11 | n4[label="name_reference"] 12 | n1->n4 13 | n5[label="identifier\n\"thisShouldBeANameReference\""] 14 | n4->n5 15 | } 16 | -------------------------------------------------------------------------------- /src/compiler/src/dot/name_reference_test.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luapp-org/luapp/9188cc373fdabd07161eb6d2acdd5156ebb2eb2a/src/compiler/src/dot/name_reference_test.png -------------------------------------------------------------------------------- /src/compiler/src/dot/print.dot: -------------------------------------------------------------------------------- 1 | digraph G 2 | { 3 | node[fontname=Monospace] 4 | n0[label="program"] 5 | n1[label="call"] 6 | n0->n1 7 | n2[label="identifier\n\"print\""] 8 | n1->n2 9 | } 10 | -------------------------------------------------------------------------------- /src/compiler/src/dot/print.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luapp-org/luapp/9188cc373fdabd07161eb6d2acdd5156ebb2eb2a/src/compiler/src/dot/print.png -------------------------------------------------------------------------------- /src/compiler/src/dot/print_test.dot: -------------------------------------------------------------------------------- 1 | digraph G 2 | { 3 | node[fontname=Monospace] 4 | n0[label="program"] 5 | n1[label="call"] 6 | n0->n1 7 | n2[label="identifier\n\"print\""] 8 | n1->n2 9 | n3[label="string\n\"a\""] 10 | n1->n3 11 | n4[label="string\n\"b\""] 12 | n1->n4 13 | n5[label="string\n\"c\""] 14 | n1->n5 15 | } 16 | -------------------------------------------------------------------------------- /src/compiler/src/dot/print_test.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luapp-org/luapp/9188cc373fdabd07161eb6d2acdd5156ebb2eb2a/src/compiler/src/dot/print_test.png -------------------------------------------------------------------------------- /src/compiler/src/dot/simpleLocalTest.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luapp-org/luapp/9188cc373fdabd07161eb6d2acdd5156ebb2eb2a/src/compiler/src/dot/simpleLocalTest.png -------------------------------------------------------------------------------- /src/compiler/src/dot/simpleVararg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luapp-org/luapp/9188cc373fdabd07161eb6d2acdd5156ebb2eb2a/src/compiler/src/dot/simpleVararg.png -------------------------------------------------------------------------------- /src/compiler/src/dot/singleass.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luapp-org/luapp/9188cc373fdabd07161eb6d2acdd5156ebb2eb2a/src/compiler/src/dot/singleass.png -------------------------------------------------------------------------------- /src/compiler/src/dot/table_constructor.dot: -------------------------------------------------------------------------------- 1 | digraph G 2 | { 3 | node[fontname=Monospace] 4 | n0[label="program"] 5 | n1[label="local"] 6 | n0->n1 7 | n2[label="type annotation"] 8 | n1->n2 9 | n3[label="identifier\n\"a\""] 10 | n2->n3 11 | n4[label="Table"] 12 | n4[color=green3] 13 | n4[fontcolor=green3] 14 | n2->n4 15 | n5[label="table_constructor"] 16 | n1->n5 17 | n6[label="key_value_pair"] 18 | n5->n6 19 | n7[label="string\n\"key\""] 20 | n6->n7 21 | n8[label="number\n\"123.000000\""] 22 | n6->n8 23 | } 24 | -------------------------------------------------------------------------------- /src/compiler/src/dot/table_constructor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luapp-org/luapp/9188cc373fdabd07161eb6d2acdd5156ebb2eb2a/src/compiler/src/dot/table_constructor.png -------------------------------------------------------------------------------- /src/compiler/src/dot/table_test.dot: -------------------------------------------------------------------------------- 1 | digraph G 2 | { 3 | node[fontname=Monospace] 4 | n0[label="program"] 5 | n1[label="local"] 6 | n0->n1 7 | n2[label="type annotation"] 8 | n1->n2 9 | n3[label="identifier\n\"a\""] 10 | n2->n3 11 | n4[label="Table"] 12 | n4[color=green3] 13 | n4[fontcolor=green3] 14 | n2->n4 15 | n5[label="nil"] 16 | n1->n5 17 | } 18 | -------------------------------------------------------------------------------- /src/compiler/src/dot/table_test.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luapp-org/luapp/9188cc373fdabd07161eb6d2acdd5156ebb2eb2a/src/compiler/src/dot/table_test.png -------------------------------------------------------------------------------- /src/compiler/src/dot/tables.dot: -------------------------------------------------------------------------------- 1 | digraph G 2 | { 3 | node[fontname=Monospace] 4 | n0[label="program"] 5 | n1[label="local"] 6 | n0->n1 7 | n2[label="type annotation"] 8 | n1->n2 9 | n3[label="identifier\n\"myTable\""] 10 | n2->n3 11 | n4[label="Table"] 12 | n4[color=green3] 13 | n4[fontcolor=green3] 14 | n2->n4 15 | n5[label="table_constructor"] 16 | n1->n5 17 | n6[label="key_value_pair"] 18 | n5->n6 19 | n7[label="string\n\"key\""] 20 | n6->n7 21 | n8[label="number\n\"123.000000\""] 22 | n6->n8 23 | n9[label="key_value_pair"] 24 | n5->n9 25 | n10[label="string\n\"val\""] 26 | n9->n10 27 | n11[label="number\n\"334.000000\""] 28 | n9->n11 29 | } 30 | -------------------------------------------------------------------------------- /src/compiler/src/dot/tables.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luapp-org/luapp/9188cc373fdabd07161eb6d2acdd5156ebb2eb2a/src/compiler/src/dot/tables.png -------------------------------------------------------------------------------- /src/compiler/src/dot/tt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luapp-org/luapp/9188cc373fdabd07161eb6d2acdd5156ebb2eb2a/src/compiler/src/dot/tt.png -------------------------------------------------------------------------------- /src/compiler/src/dot/type_annotations.dot: -------------------------------------------------------------------------------- 1 | digraph G 2 | { 3 | node[fontname=Monospace] 4 | n0[label="program"] 5 | n3[label="local"] 6 | n0->n3 7 | n4[label="type annotation"] 8 | n3->n4 9 | n5[label="identifier\n\"Number\""] 10 | n4->n5 11 | n6[label="number"] 12 | n6[color=green3] 13 | n6[fontcolor=green3] 14 | n4->n6 15 | n7[label="number\n\"1234.000000\""] 16 | n3->n7 17 | n8[label="local"] 18 | n0->n8 19 | n9[label="type annotation"] 20 | n8->n9 21 | n10[label="identifier\n\"String\""] 22 | n9->n10 23 | n11[label="string"] 24 | n11[color=green3] 25 | n11[fontcolor=green3] 26 | n9->n11 27 | n12[label="string\n\"Hello!\""] 28 | n8->n12 29 | n13[label="local"] 30 | n0->n13 31 | n14[label="type annotation"] 32 | n13->n14 33 | n15[label="identifier\n\"Boolean\""] 34 | n14->n15 35 | n16[label="boolean"] 36 | n16[color=green3] 37 | n16[fontcolor=green3] 38 | n14->n16 39 | n17[label="boolean\n\"true\""] 40 | n13->n17 41 | } 42 | -------------------------------------------------------------------------------- /src/compiler/src/dot/type_annotations.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luapp-org/luapp/9188cc373fdabd07161eb6d2acdd5156ebb2eb2a/src/compiler/src/dot/type_annotations.png -------------------------------------------------------------------------------- /src/compiler/src/dot/uneven_local_definition.dot: -------------------------------------------------------------------------------- 1 | digraph G 2 | { 3 | node[fontname=Monospace] 4 | n0[label="program"] 5 | n1[label="local"] 6 | n0->n1 7 | n2[label="identifier\n\"c\""] 8 | n1->n2 9 | n3[label="identifier\n\"b\""] 10 | n1->n3 11 | n4[label="identifier\n\"a\""] 12 | n1->n4 13 | n5[label="number\n\"1.000000\""] 14 | n1->n5 15 | } 16 | -------------------------------------------------------------------------------- /src/compiler/src/dot/uneven_local_definition.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luapp-org/luapp/9188cc373fdabd07161eb6d2acdd5156ebb2eb2a/src/compiler/src/dot/uneven_local_definition.png -------------------------------------------------------------------------------- /src/compiler/src/ir.h: -------------------------------------------------------------------------------- 1 | #ifndef _IR_H 2 | #define _IR_H 3 | 4 | #include 5 | #include 6 | 7 | #include "compiler.h" 8 | #include "util/hashmap.h" 9 | 10 | /* Blind definitions */ 11 | struct node; 12 | struct symbol; 13 | struct symbol_table; 14 | 15 | struct ir_instruction { 16 | uint32_t value; 17 | 18 | enum opcode_mode mode; 19 | struct ir_instruction *prev, *next; 20 | }; 21 | 22 | struct ir_section { 23 | struct ir_instruction *first, *last; 24 | int size; 25 | }; 26 | 27 | struct ir_constant { 28 | constant_t type; 29 | union { 30 | struct { 31 | uint32_t symbol_id; 32 | } symbol; 33 | struct { 34 | double value; 35 | } number; 36 | struct { 37 | uint32_t index; 38 | } env; 39 | struct { 40 | int size; 41 | uint32_t *indicies; 42 | } array; 43 | } data; 44 | 45 | struct ir_constant *prev, *next; 46 | }; 47 | 48 | struct ir_constant_list { 49 | struct ir_constant *first, *last; 50 | int size; 51 | }; 52 | 53 | struct ir_proto_list; 54 | 55 | /* IR function prototypes */ 56 | struct ir_proto { 57 | /* Information variables */ 58 | uint8_t max_stack_size; 59 | uint8_t parameters_size; 60 | uint8_t upvalues_size; 61 | bool is_vararg; 62 | 63 | uint32_t proto_size; 64 | uint32_t protos[BUFSIZ]; 65 | 66 | struct ir_constant_list *constant_list; 67 | struct ir_section *code; 68 | 69 | /* Variables used within the IR */ 70 | uint8_t top_register; 71 | int32_t target_register; 72 | bool mult_ret; 73 | struct ir_proto *prev, *next; 74 | }; 75 | 76 | struct ir_proto_list { 77 | struct ir_proto *first, *last; 78 | int size; 79 | }; 80 | 81 | struct ir_context { 82 | /* Variables the IR uses */ 83 | int error_count; 84 | 85 | /* What will be serialized */ 86 | struct symbol_table *table; 87 | struct ir_proto_list *protos; 88 | 89 | /* IR 'local' register map */ 90 | map_t local_map; 91 | }; 92 | 93 | void ir_init(struct ir_context *context); 94 | void ir_destroy(struct ir_context *context); 95 | 96 | void ir_print_context(FILE *output, struct ir_context *context); 97 | struct ir_proto_list *ir_build(struct ir_context *context, struct node *node); 98 | struct ir_proto *ir_build_proto(struct ir_context *context, struct ir_proto *proto, 99 | struct node *node); 100 | 101 | #endif -------------------------------------------------------------------------------- /src/compiler/src/lexer.h: -------------------------------------------------------------------------------- 1 | #ifndef _LEXER_H 2 | #define _LEXER_H 3 | 4 | #include "lexer.yy.h" 5 | 6 | typedef struct compiler_context compiler_context_t; 7 | 8 | void lex_init(yyscan_t *lexer, compiler_context_t *context, FILE *input); 9 | void lex_destroy(yyscan_t *lexer); 10 | void lex_print(yyscan_t lexer, int *error_count, FILE *output); 11 | 12 | #endif -------------------------------------------------------------------------------- /src/compiler/src/lexer.l: -------------------------------------------------------------------------------- 1 | %option yylineno 2 | %option reentrant 3 | %option bison-bridge 4 | %option bison-locations 5 | %option noyywrap noinput nounput nodefault 6 | 7 | 8 | %{ 9 | #include 10 | #include 11 | #include 12 | 13 | #include "compiler.h" 14 | #include "parser.tab.h" 15 | #include "node.h" 16 | #include "util/flexstr.h" 17 | 18 | /* Tell GCC to ignore the warning for now (must be a bug) */ 19 | #pragma GCC diagnostic ignored "-Wstringop-overflow=" 20 | 21 | /* Track locations. */ 22 | #define YY_EXTRA_TYPE int 23 | #define YY_USER_ACTION { yylloc->first_line = yylloc->last_line = yylineno; \ 24 | yylloc->first_column = yyextra; \ 25 | yylloc->last_column = yyextra + yyleng - 1; \ 26 | yyextra += yyleng; } 27 | 28 | flexstr_t s; 29 | int first_line, first_col; 30 | bool comment; 31 | %} 32 | 33 | %x LCOMMENT 34 | %x COMMENT 35 | %x LSTRING 36 | 37 | newline \n 38 | ws [ \t\v\f] 39 | 40 | digit [[:digit:]] 41 | letter [[:alpha:]] 42 | 43 | identifier {letter}({letter}|{digit})* 44 | number [+-]?([0-9]+\.?[0-9]*|\.[0-9]+) 45 | string \"([^"\\\n]|\\(.|\n))*\"|'([^"\\\n]|\\(.|\n))*' 46 | lstring \[\[(.*?|\n|\r)\]\] 47 | 48 | %% 49 | 50 | 51 | "--[[" { BEGIN(LCOMMENT); } 52 | "]]--" { BEGIN(INITIAL); } 53 | \n { yyextra = 1; } 54 | . { } 55 | 56 | "[[" { 57 | BEGIN(LSTRING); 58 | first_line = yylineno; 59 | first_col = yyextra; 60 | } 61 | "]]" { 62 | BEGIN(INITIAL); 63 | 64 | /* Hacky method of updating line positions over multiple lines. */ 65 | yylloc->first_line = first_line; 66 | yylloc->last_line = yylineno; 67 | yylloc->first_column = first_col; 68 | yylloc->last_column = yyextra; 69 | 70 | *yylval = node_string(*yylloc, fs_getstr(&s)); 71 | return STRING_T; 72 | } 73 | . { fs_addch(&s, yytext[0]); } 74 | \n { fs_addch(&s, '\n'); yyextra = 1; } 75 | <> { compiler_error(*yylloc_param, "unexpected EOF", yytext); yyterminate(); } 76 | 77 | "--" { if (!comment) 78 | BEGIN(COMMENT); 79 | else 80 | return DECREMENT_T; 81 | } 82 | "//" { if (comment) 83 | BEGIN(COMMENT); 84 | else { 85 | compiler_error(*yylloc_param, "use '--!comment' if c-style comments are perferred"); 86 | yyterminate(); 87 | } 88 | } 89 | \n { yyextra = 1; BEGIN(INITIAL); } 90 | . { } 91 | 92 | "and" return AND_T; 93 | "break" return BREAK_T; 94 | "do" return DO_T; 95 | "else" return ELSE_T; 96 | "elseif" return ELSEIF_T; 97 | "end" return END_T; 98 | "false" { *yylval = node_boolean(*yylloc, false); return FALSE_T; } 99 | "true" { *yylval = node_boolean(*yylloc, true); return TRUE_T; } 100 | "for" return FOR_T; 101 | "function" return FUNCTION_T; 102 | "if" return IF_T; 103 | "in" return IN_T; 104 | "local" return LOCAL_T; 105 | "nil" return NIL_T; 106 | "not" return NOT_T; 107 | "or" return OR_T; 108 | "repeat" return REPEAT_T; 109 | "return" return RETURN_T; 110 | "then" return THEN_T; 111 | "until" return UNTIL_T; 112 | "while" return WHILE_T; 113 | "class" return CLASS_T; 114 | "constructor" return CONSTRUCTOR_T; 115 | 116 | "number" return TNUMBER_T; 117 | "string" return TSTRING_T; 118 | "boolean" return TBOOLEAN_T; 119 | "any" return TANY_T; 120 | "void" return TVOID_T; 121 | "Array" return TARRAY_T; 122 | "Table" return TTABLE_T; 123 | 124 | \[ return LEFT_SQUARE_T; 125 | \] return RIGHT_SQUARE_T; 126 | \+ return PLUS_T; 127 | - return MINUS_T; 128 | \* return ASTERISK_T; 129 | \/ { 130 | slash_label: 131 | return SLASH_T; 132 | } 133 | \= return EQUAL_T; 134 | \) return RIGHT_PARAN_T; 135 | \( return LEFT_PARAN_T; 136 | \^ return CARROT_T; 137 | \> return GREATER_THAN_T; 138 | \< return LESS_THAN_T; 139 | \~ return SQUIGGLE_T; 140 | \: return COLON_T; 141 | \# return POUND_T; 142 | \% return PERCENT_T; 143 | \, return COMMA_T; 144 | "." return DOT_T; 145 | \{ return LEFT_BRACKET_T; 146 | \} return RIGHT_BRACKET_T; 147 | \; /* do nothing */ 148 | 149 | "==" return DOUBLE_EQUAL_T; 150 | "~=" return NOT_EQUAL_T; 151 | ">=" return GREATER_EQUAL_T; 152 | "<=" return LESS_EQUAL_T; 153 | ".." return CONCAT_T; 154 | "..." { *yylval = node_vararg(*yylloc); return VARARG_T; } 155 | "+=" return PLUS_EQUAL_T; 156 | "-=" return MINUS_EQUAL_T; 157 | "*=" return ASTERISK_EQUAL_T; 158 | "/=" return SLASH_EQUAL_T; 159 | "%=" return MOD_EQUAL_T; 160 | "^=" return CARROT_EQUAL_T; 161 | "..=" return CONCAT_EQUAL_T; 162 | "++" return INCREMENT_T; 163 | 164 | {identifier} { *yylval = node_identifier(*yylloc, yytext); return IDENTIFIER_T; } 165 | {number} { *yylval = node_number(*yylloc, yytext); return NUMBER_T; } 166 | {string} { 167 | /* Hacky: remove quotes only for single line strings */ 168 | char *res = yytext + 1; 169 | res[strlen(res) - 1] = '\0'; 170 | 171 | *yylval = node_string(*yylloc, res); return STRING_T; 172 | } 173 | 174 | 175 | {newline} { yyextra = 1; } 176 | {ws} 177 | . { compiler_error(*yylloc_param, "unrecognized character %s", yytext); yyterminate(); } 178 | %% 179 | 180 | /* lex_init - initializes the flex lexer 181 | * args: lexer, file 182 | * rets: none 183 | */ 184 | void lex_init(yyscan_t *lexer, compiler_context_t *context, FILE *input) { 185 | yylex_init(lexer); 186 | yyset_in(input, *lexer); 187 | yyset_extra(1, *lexer); 188 | 189 | fs_init(&s, 0); 190 | comment = context->is_c_comment; 191 | } 192 | 193 | /* lex_destroy - frees the lexer instance 194 | * args: lexer 195 | * rets: none 196 | */ 197 | void lex_destroy(yyscan_t *lexer) { 198 | yylex_destroy(*lexer); 199 | lexer = NULL; 200 | } 201 | 202 | /* lex_print - prints all of the tokens generated by the lexer 203 | * args: lexer, number of errors, output file 204 | * rets: none 205 | */ 206 | void lex_print(yyscan_t *lexer, int *error_count, FILE *output) { 207 | YYSTYPE val; 208 | YYLTYPE loc; 209 | int token; 210 | 211 | while ((token = yylex(&val, &loc, lexer)) != 0) { 212 | if (token < 0) { 213 | (*error_count)++; 214 | return; 215 | } else { 216 | fprintf(output, "%-20s", token_to_string(token)); 217 | } 218 | 219 | switch (token) { 220 | case NUMBER_T: 221 | fprintf(output, "%-20lf", val->data.number.value); 222 | break; 223 | case STRING_T: 224 | fprintf(output, "%-20s", val->data.string.value); 225 | break; 226 | case IDENTIFIER_T: 227 | fprintf(output, "%-20s", val->data.identifier.name); 228 | break; 229 | default: 230 | fprintf(output, "%-20s", ""); 231 | break; 232 | } 233 | 234 | fprintf(output, "%04d:%04d-%04d:%04d", 235 | loc.first_line, loc.first_column, loc.last_line, loc.last_column); 236 | 237 | fputc('\n', output); 238 | } 239 | } 240 | -------------------------------------------------------------------------------- /src/compiler/src/macro.c: -------------------------------------------------------------------------------- 1 | #include "macro.h" 2 | #include "ctype.h" 3 | 4 | #include "util/flexstr.h" 5 | 6 | #define is_newline(c) (c == '\n') 7 | #define is_whitespace(c) (c == ' ' || c == '\t' || c == '\v' || c == '\f') 8 | 9 | static char *read_macro(FILE *input); 10 | static int fpeek(FILE *stream); 11 | static bool set_macro(compiler_context_t *context, char *name); 12 | static char *trim(char *str); 13 | static void init_default(compiler_context_t *context); 14 | 15 | /* macro_init() - initialized compiler context based on the macros used. 16 | * args: compiler context, input file 17 | * returns: none 18 | * 19 | * Node: Sets the file pointer after the last definition of a macro and doesn't close the stream. 20 | */ 21 | void macro_init(compiler_context_t *context, FILE *input) 22 | { 23 | char c, next; 24 | fpos_t p; 25 | 26 | init_default(context); 27 | 28 | do { 29 | c = (char)fgetc(input); 30 | next = (char)fpeek(input); 31 | 32 | if (is_newline(c) || is_whitespace(c)) 33 | continue; 34 | else if (c == '-' && next == '-') { 35 | fgetc(input); 36 | 37 | if ((c = (char)fgetc(input)) != '!') { 38 | rewind(input); 39 | break; 40 | } 41 | 42 | char *m = read_macro(input); 43 | 44 | if (!set_macro(context, m)) { 45 | lcompiler_error("unknown macro reference \"--!%s\"", m); 46 | context->error_count++; 47 | } 48 | 49 | free(m); 50 | } else { 51 | ungetc(c, input); 52 | break; 53 | } 54 | } while (c != EOF); 55 | } 56 | 57 | /* macro_print() - prints all macro values for debug purposes. 58 | * args: compiler context 59 | * returns: none 60 | */ 61 | void macro_print(compiler_context_t *context) 62 | { 63 | printf("--!lenient: %s\n", context->is_strict ? "false" : "true"); 64 | printf("--!carrays: %s\n", context->is_c_array ? "true" : "false"); 65 | printf("--!comment: %s\n", context->is_c_comment ? "true" : "false"); 66 | } 67 | 68 | static char *read_macro(FILE *input) 69 | { 70 | flexstr_t s; 71 | char c; 72 | 73 | fs_init(&s, 0); 74 | 75 | while (!is_newline((c = (char)fgetc(input)))) 76 | fs_addch(&s, c); 77 | 78 | return fs_getstr(&s); 79 | } 80 | 81 | static bool set_macro(compiler_context_t *context, char *name) 82 | { 83 | name = trim(name); 84 | 85 | if (strcmp(name, "lenient") == 0) 86 | context->is_strict = false; 87 | else if (strcmp(name, "carrays") == 0) 88 | context->is_c_array = true; 89 | else if (strcmp(name, "comment") == 0) 90 | context->is_c_comment = true; 91 | else 92 | return false; 93 | 94 | return true; 95 | } 96 | 97 | int fpeek(FILE *stream) 98 | { 99 | int c; 100 | 101 | c = fgetc(stream); 102 | ungetc(c, stream); 103 | 104 | return c; 105 | } 106 | 107 | char *trim(char *str) 108 | { 109 | char *end; 110 | 111 | // Trim leading space 112 | while (isspace((unsigned char)*str)) 113 | str++; 114 | 115 | if (*str == 0) // All spaces? 116 | return str; 117 | 118 | // Trim trailing space 119 | end = str + strlen(str) - 1; 120 | while (end > str && isspace((unsigned char)*end)) 121 | end--; 122 | 123 | // Write new null terminator character 124 | end[1] = '\0'; 125 | 126 | return str; 127 | } 128 | 129 | static void init_default(compiler_context_t *context) 130 | { 131 | context->is_strict = true; 132 | context->is_c_array = false; 133 | context->is_c_comment = false; 134 | } -------------------------------------------------------------------------------- /src/compiler/src/macro.h: -------------------------------------------------------------------------------- 1 | #ifndef _MACRO_H 2 | #define _MACRO_H 3 | 4 | #include "compiler.h" 5 | 6 | /* WARNING! This function does not close the file pointer. */ 7 | void macro_init(compiler_context_t *context, FILE *input); 8 | void macro_print(compiler_context_t* context); 9 | #endif -------------------------------------------------------------------------------- /src/compiler/src/main.c: -------------------------------------------------------------------------------- 1 | /* luapp.c - only version 2 | * main entry point for the compiler 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "codegen.h" 13 | #include "compiler.h" 14 | #include "ir.h" 15 | #include "lexer.h" 16 | #include "macro.h" 17 | #include "node.h" 18 | #include "parser.h" 19 | #include "symbol.h" 20 | #include "type.h" 21 | 22 | /* print_summary - prints a quick summary of a pass (elapsed time and number of 23 | * errors) 24 | * args: pass name, numer of errors, elapsed time 25 | * rets: none 26 | */ 27 | static void print_summary(char *pass, int error_count, clock_t elapsed) 28 | { 29 | /* Calculate the total time that the pass took (seconds) */ 30 | double sec = (elapsed * 1000); 31 | 32 | printf("\n%s encountered %d %s, elapsed time: %lf second(s).\n", pass, error_count, 33 | (error_count == 1 ? "error" : "errors"), (sec / 1000000) / 1000); 34 | } 35 | 36 | /* 37 | * Entrypoint for the compiler. 38 | * 39 | * luapp -s [lexer|parser|type|ir|codgen] -o [outputfile] [inputfile] 40 | * 41 | * -s : indicates the name of the stage to stop after. 42 | * Defaults to the last stage. 43 | * -o : name of the output file. Defaults to "output.s" 44 | * 45 | * You should pass the name of the file to compile. 46 | */ 47 | int main(int argc, char **argv) 48 | { 49 | int opt, error_count; 50 | char *stage, *dot; 51 | FILE *input, *output; 52 | struct symbol_table symbol_table; 53 | yyscan_t lexer; 54 | time_t start; 55 | struct node *tree; 56 | 57 | stage = "codegen"; 58 | output = stdout; 59 | /* Parse the command line args and store them in their corresponding vars */ 60 | while ((opt = getopt(argc, argv, "o:s:")) != -1) { 61 | switch (opt) { 62 | case 'o': 63 | if (!(output = fopen(optarg, "w"))) { 64 | fprintf(stdout, "Error: Unable to open output file %s: %s\n", optarg, 65 | strerror(errno)); 66 | return 1; 67 | } 68 | break; 69 | case 's': 70 | stage = optarg; 71 | break; 72 | case ':': 73 | default: 74 | putchar('\n'); 75 | usage(); 76 | return 0; 77 | } 78 | } 79 | 80 | /* Determine if we are using stdin or file in. */ 81 | if (optind == argc - 1) { 82 | /* Check if the input file is a .lpp or .lua file */ 83 | dot = strrchr(argv[optind], '.'); 84 | 85 | /* If the given file is of the correct type, init the lexer */ 86 | if (dot && !strcmp(dot, ".lpp") || !strcmp(dot, ".lua")) { 87 | input = fopen(argv[optind], "r"); 88 | } else { 89 | printf("Incorrect file type.\n"); 90 | return 1; 91 | } 92 | } else if (optind >= argc) 93 | input = stdin; 94 | else { 95 | printf("Expected 1 input file, found %d.\n", argc - optind); 96 | return 1; 97 | } 98 | 99 | compiler_context_t context = {stage, 0, 0, false, false, false}; 100 | 101 | bool result = compile(&context, input, output); 102 | 103 | print_summary(context.stage, context.error_count, context.time); 104 | 105 | return result; 106 | } -------------------------------------------------------------------------------- /src/compiler/src/parser.h: -------------------------------------------------------------------------------- 1 | #ifndef _PARSER_H 2 | #define _PARSER_H 3 | 4 | #include "lexer.yy.h" 5 | 6 | struct node *parser_parse(int *error_count, yyscan_t lexer); 7 | 8 | #endif -------------------------------------------------------------------------------- /src/compiler/src/symbol.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "compiler.h" 7 | #include "node.h" 8 | #include "symbol.h" 9 | #include "util/flexstr.h" 10 | 11 | static unsigned int nextSymbolId; 12 | 13 | /* symbol_initialize_table() -- initializes the symbol table 14 | * args: table that we will init 15 | * returns: none 16 | */ 17 | void symbol_initialize_table(struct symbol_table *table) 18 | { 19 | table->first = NULL; 20 | table->last = NULL; 21 | } 22 | 23 | /* symbol_get() -- get a symbol from the symbol table 24 | * args: table, the name of the symbol 25 | * returns: new symbol 26 | */ 27 | static struct symbol *symbol_get(struct symbol_table *table, char *name) 28 | { 29 | struct symbol_list *iter; 30 | for (iter = table->first; NULL != iter; iter = iter->next) { 31 | if (!strcmp(name, iter->symbol.name)) { 32 | return &iter->symbol; 33 | } 34 | } 35 | return NULL; 36 | } 37 | 38 | /* symbol_put() -- add a symbol to the symbol table 39 | * args: table, the name of the symbol 40 | * returns: new symbol 41 | */ 42 | static struct symbol *symbol_put(struct symbol_table *table, char *name) 43 | { 44 | struct symbol *s; 45 | if ((s = symbol_get(table, name))) 46 | return s; 47 | 48 | struct symbol_list *symbol_list; 49 | 50 | symbol_list = smalloc(sizeof(struct symbol_list)); 51 | 52 | symbol_list->symbol.name = strdup(name); 53 | symbol_list->symbol.id = nextSymbolId++; 54 | 55 | if (table->first == NULL && table->last == NULL) { 56 | table->first = symbol_list; 57 | table->last = symbol_list; 58 | 59 | symbol_list->prev = NULL; 60 | symbol_list->next = NULL; 61 | } else { 62 | symbol_list->next = table->last->next; 63 | if (symbol_list->next != NULL) 64 | symbol_list->next->prev = symbol_list; 65 | table->last->next = symbol_list; 66 | 67 | symbol_list->prev = table->last; 68 | table->last = symbol_list; 69 | } 70 | 71 | table->size = nextSymbolId; 72 | 73 | return &symbol_list->symbol; 74 | } 75 | 76 | /* symbol_ast_traversal() -- traverse through the AST and build symbol tree 77 | * args: context, and AST 78 | * returns: none 79 | */ 80 | void symbol_ast_traversal(struct symbol_context *context, struct node *node) 81 | { 82 | if (!node) 83 | return; 84 | 85 | /* We have to have a context and table */ 86 | assert(context); 87 | assert(context->table); 88 | 89 | switch (node->type) { 90 | case NODE_IDENTIFIER: 91 | node->data.identifier.s = symbol_put(context->table, node->data.identifier.name); 92 | break; 93 | case NODE_STRING: 94 | node->data.string.s = symbol_put(context->table, node->data.string.value); 95 | break; 96 | case NODE_BLOCK: 97 | symbol_ast_traversal(context, node->data.block.init); 98 | symbol_ast_traversal(context, node->data.block.statement); 99 | break; 100 | case NODE_TYPE_ANNOTATION: 101 | symbol_ast_traversal(context, node->data.type_annotation.identifier); 102 | symbol_ast_traversal(context, node->data.type_annotation.type); 103 | break; 104 | case NODE_BINARY_OPERATION: 105 | symbol_ast_traversal(context, node->data.binary_operation.left); 106 | symbol_ast_traversal(context, node->data.binary_operation.right); 107 | break; 108 | case NODE_UNARY_OPERATION: 109 | symbol_ast_traversal(context, node->data.unary_operation.expression); 110 | break; 111 | case NODE_EXPRESSION_LIST: 112 | symbol_ast_traversal(context, node->data.expression_list.expression); 113 | symbol_ast_traversal(context, node->data.expression_list.init); 114 | break; 115 | case NODE_NAME_LIST: 116 | symbol_ast_traversal(context, node->data.name_list.init); 117 | symbol_ast_traversal(context, node->data.name_list.name); 118 | break; 119 | case NODE_VARIABLE_LIST: 120 | symbol_ast_traversal(context, node->data.variable_list.init); 121 | symbol_ast_traversal(context, node->data.variable_list.variable); 122 | break; 123 | case NODE_PARAMETER_LIST: 124 | symbol_ast_traversal(context, node->data.parameter_list.namelist); 125 | symbol_ast_traversal(context, node->data.parameter_list.vararg); 126 | break; 127 | case NODE_CALL: 128 | symbol_ast_traversal(context, node->data.call.args); 129 | symbol_ast_traversal(context, node->data.call.prefix_expression); 130 | break; 131 | case NODE_EXPRESSION_GROUP: 132 | symbol_ast_traversal(context, node->data.expression_group.expression); 133 | break; 134 | case NODE_NAME_INDEX: 135 | symbol_ast_traversal(context, node->data.name_index.expression); 136 | symbol_ast_traversal(context, node->data.name_index.index); 137 | break; 138 | case NODE_EXPRESSION_INDEX: 139 | symbol_ast_traversal(context, node->data.expression_index.expression); 140 | symbol_ast_traversal(context, node->data.expression_index.index); 141 | break; 142 | case NODE_EXPRESSION_STATEMENT: 143 | symbol_ast_traversal(context, node->data.expression_statement.expression); 144 | break; 145 | case NODE_ASSIGNMENT: 146 | symbol_ast_traversal(context, node->data.assignment.values); 147 | symbol_ast_traversal(context, node->data.assignment.variables); 148 | break; 149 | case NODE_WHILELOOP: 150 | symbol_ast_traversal(context, node->data.while_loop.body); 151 | symbol_ast_traversal(context, node->data.while_loop.condition); 152 | break; 153 | case NODE_REPEATLOOP: 154 | symbol_ast_traversal(context, node->data.repeat_loop.body); 155 | symbol_ast_traversal(context, node->data.repeat_loop.condition); 156 | break; 157 | case NODE_IF: 158 | symbol_ast_traversal(context, node->data.if_statement.body); 159 | symbol_ast_traversal(context, node->data.if_statement.condition); 160 | symbol_ast_traversal(context, node->data.if_statement.else_body); 161 | break; 162 | case NODE_NUMERICFORLOOP: 163 | symbol_ast_traversal(context, node->data.numerical_for_loop.body); 164 | symbol_ast_traversal(context, node->data.numerical_for_loop.increment); 165 | symbol_ast_traversal(context, node->data.numerical_for_loop.init); 166 | break; 167 | case NODE_GENERICFORLOOP: 168 | symbol_ast_traversal(context, node->data.generic_for_loop.body); 169 | symbol_ast_traversal(context, node->data.generic_for_loop.local); 170 | break; 171 | case NODE_LOCAL: 172 | symbol_ast_traversal(context, node->data.local.exprlist); 173 | symbol_ast_traversal(context, node->data.local.namelist); 174 | break; 175 | case NODE_RETURN: 176 | symbol_ast_traversal(context, node->data.return_statement.exprlist); 177 | break; 178 | case NODE_FUNCTION_BODY: 179 | symbol_ast_traversal(context, node->data.function_body.body); 180 | symbol_ast_traversal(context, node->data.function_body.exprlist); 181 | symbol_ast_traversal(context, node->data.function_body.type_list); 182 | break; 183 | case NODE_NAME_REFERENCE: 184 | symbol_ast_traversal(context, node->data.name_reference.identifier); 185 | break; 186 | case NODE_KEY_VALUE_PAIR: 187 | symbol_ast_traversal(context, node->data.key_value_pair.key); 188 | symbol_ast_traversal(context, node->data.key_value_pair.value); 189 | break; 190 | case NODE_ARRAY_CONSTRUCTOR: 191 | symbol_ast_traversal(context, node->data.array_constructor.exprlist); 192 | break; 193 | case NODE_TABLE_CONSTRUCTOR: 194 | symbol_ast_traversal(context, node->data.table_constructor.pairlist); 195 | break; 196 | } 197 | } 198 | 199 | /* symbol_print_table() -- dumps all the contents of the symbol table to the screen 200 | * args: output stream, symbol table 201 | * returns: none 202 | */ 203 | void symbol_print_table(FILE *output, struct symbol_table *table) 204 | { 205 | struct symbol_list *iter; 206 | 207 | fputs("symbol table:\n", output); 208 | 209 | for (iter = table->first; NULL != iter; iter = iter->next) { 210 | fprintf(output, " %-10s\t%10u\n", iter->symbol.name, iter->symbol.id); 211 | } 212 | 213 | fputc('\n', output); 214 | } -------------------------------------------------------------------------------- /src/compiler/src/symbol.h: -------------------------------------------------------------------------------- 1 | /* 2 | * symbol.h 3 | * 4 | * Usually, symbol tables are constructed before the type checker is launched. In this compiler, 5 | * symbols are a little different than ones you may find in a traditional symbol table. Since Lua++ 6 | * bytecode actually contains a list of constants used within the codebase, the symbol traversal 7 | * should simply just find constants and store them so that you could just throw them at the IR pass 8 | * and be done. 9 | */ 10 | 11 | #ifndef _SYMBOL_H 12 | #define _SYMBOL_H 13 | 14 | #include 15 | 16 | #include "compiler.h" 17 | struct node; 18 | struct type; 19 | 20 | struct symbol { 21 | char *name; 22 | unsigned int id; 23 | }; 24 | 25 | struct symbol_list { 26 | struct symbol symbol; 27 | struct symbol_list *next, *prev; 28 | }; 29 | 30 | struct symbol_table { 31 | struct symbol_list *first, *last; 32 | unsigned int size; 33 | }; 34 | 35 | struct symbol_context { 36 | struct symbol_table *table; 37 | int error_count; 38 | }; 39 | 40 | void symbol_initialize_table(struct symbol_table *table); 41 | void symbol_table_destroy(struct symbol_table *table); 42 | 43 | void symbol_ast_traversal(struct symbol_context *context, struct node *node); 44 | void symbol_print_table(FILE *output, struct symbol_table *table); 45 | 46 | #endif -------------------------------------------------------------------------------- /src/compiler/src/tests/graphviz.sh: -------------------------------------------------------------------------------- 1 | cd src 2 | 3 | ../../bin/luappc -s parser -o dot/$1.dot 4 | dot -Tpng dot/$1.dot > dot/$1.png 5 | -------------------------------------------------------------------------------- /src/compiler/src/tests/ir/hello.lua: -------------------------------------------------------------------------------- 1 | print("Hello, world!") 2 | print(12) -------------------------------------------------------------------------------- /src/compiler/src/tests/ir/helloworld.lua: -------------------------------------------------------------------------------- 1 | print("Hello, world") 2 | -------------------------------------------------------------------------------- /src/compiler/src/tests/type/binary.lua: -------------------------------------------------------------------------------- 1 | local a: number = 12 2 | 3 | -- Arithmetic 4 | local add: string = a + 1 -- This should be an error 5 | local sub: number = a - 1 6 | local mul: number = a * 1 7 | local div: number = a / 1 8 | local pow: number = a ^ 1 9 | local mod: number = a % 1 10 | 11 | -- Concat 12 | local str1: string = 1 .. 1 13 | local str2: string = "adad" .. 1223 14 | local str3: boolean = 1 .. 1 -- There should be an error 15 | 16 | -- Comparisons 17 | local eq: boolean = 1 == 1 18 | local ne: boolean = 1 ~= 1 19 | local ge: boolean = 1 >= 1 20 | local le: boolean = 1 <= "a" -- There should be an error 21 | 22 | -- And + Or operations 23 | local andTest1: number = 1 and 2 24 | local andTest2: number = 1 and "string" -- This should error 25 | 26 | local orTest1: number = 1 or 2 27 | local orTest2: number = "string" or 1 -- This should error -------------------------------------------------------------------------------- /src/compiler/src/tests/type/block.lua: -------------------------------------------------------------------------------- 1 | -- Testing scopes within a simple block 2 | local highestScope: number = 1 3 | 4 | do 5 | local lowestScope: number = highestScope 6 | end 7 | 8 | lowestScope = 123 -------------------------------------------------------------------------------- /src/compiler/src/tests/type/call.lua: -------------------------------------------------------------------------------- 1 | -- This should work 2 | print("text", "text", "text") 3 | 4 | -- This should also work 5 | print() 6 | 7 | -- This should not work 8 | somefunction() 9 | 10 | local function myFunction(a: number): any 11 | 12 | end 13 | 14 | myFunction("a") -------------------------------------------------------------------------------- /src/compiler/src/tests/type/forgeneric.lua: -------------------------------------------------------------------------------- 1 | local test: boolean = false 2 | 3 | for a: number in { 1, 2, 3 } do 4 | -- This should work 5 | local secondTest: boolean = test 6 | end 7 | 8 | -- This should not work 9 | local canIReference: number = secondTest -------------------------------------------------------------------------------- /src/compiler/src/tests/type/fornumeric.lua: -------------------------------------------------------------------------------- 1 | --[[ First type of numeric forloop test ]]-- 2 | 3 | -- ERROR (no type annotation) 4 | for i = 0, 10, -1 do 5 | -- stuff 6 | end 7 | 8 | -- This should work fine 9 | for i: number = 0, 10 do 10 | -- do stuff 11 | end 12 | 13 | local array: Array = { "" } 14 | 15 | for array[0] = 1, 10, 2 do 16 | -- do stuff 17 | end -------------------------------------------------------------------------------- /src/compiler/src/tests/type/function.lua: -------------------------------------------------------------------------------- 1 | -- Legal function definition 2 | local function f(a: number, b: string): boolean 3 | print(a) 4 | end 5 | -------------------------------------------------------------------------------- /src/compiler/src/tests/type/functions.lua: -------------------------------------------------------------------------------- 1 | -- The function definition is legal 2 | local function func(a: number, b: string): boolean 3 | -- Error --> type mismatch 4 | local c: boolean = a 5 | end -------------------------------------------------------------------------------- /src/compiler/src/tests/type/if.lua: -------------------------------------------------------------------------------- 1 | local a: boolean = true 2 | local b: string = "test" 3 | local c: number = 1 4 | 5 | if a then 6 | -- Do stuff 7 | elseif b then 8 | -- again, do stuff 9 | else 10 | -- do stuff 11 | end 12 | 13 | if c == 1 then 14 | -- print some stuff or make some calculations 15 | -- idk 16 | end 17 | -------------------------------------------------------------------------------- /src/compiler/src/tests/type/localassign.lua: -------------------------------------------------------------------------------- 1 | local a: number = 1 2 | print(a) -------------------------------------------------------------------------------- /src/compiler/src/tests/type/locals.lua: -------------------------------------------------------------------------------- 1 | local a = "" -- Error: strict mode 2 | local b: number = "str" -- Error: type mismatch 3 | local c: numberS -------------------------------------------------------------------------------- /src/compiler/src/tests/type/tables.lua: -------------------------------------------------------------------------------- 1 | local a: Table = { 2 | ["key"] = 123, 3 | ["key2"] = 124 4 | } 5 | 6 | -- This should work, since table has all values as any type 7 | a["key"] = true -------------------------------------------------------------------------------- /src/compiler/src/tests/type/unary.lua: -------------------------------------------------------------------------------- 1 | local num: number = 1 2 | local str: string = "value" 3 | local boo: boolean = false 4 | 5 | -- Length 6 | local a: string = #num -- ERROR 7 | local b: string = #str 8 | 9 | -- Minus 10 | local c: number = -str -- ERROR 11 | local d: number = -num 12 | 13 | -- Not 14 | local e: boolean = not boo -------------------------------------------------------------------------------- /src/compiler/src/type.h: -------------------------------------------------------------------------------- 1 | #ifndef _TYPE_H 2 | #define _TYPE_H 3 | 4 | #include 5 | #include 6 | 7 | #include "util/hashmap.h" 8 | 9 | struct node; 10 | 11 | enum type_kind { 12 | TYPE_PRIMITIVE, 13 | TYPE_ARRAY, 14 | TYPE_TABLE, 15 | TYPE_FUNCTION, 16 | TYPE_CUSTOM /* Custom types are userdefined types */ 17 | }; 18 | 19 | /* Maybe add other types..? */ 20 | enum type_primitive_kind { 21 | TYPE_BASIC_NUMBER, 22 | TYPE_BASIC_STRING, 23 | TYPE_BASIC_BOOLEAN, 24 | TYPE_BASIC_NIL, 25 | TYPE_BASIC_VARARG, /* Special type, it's type definition is the exact same as the grammar: 26 | * 27 | * local print: (format: string, ...): any = function(format: string, ...) 28 | * -- do stuff 29 | * end 30 | * 31 | * This may seem quite strange at first, but this makes it a lot 32 | * easier for the compiler to type check in general. The code above may seem 33 | * quite ugly so here is a nicer function definition for printf: 34 | * 35 | * function printf(format: string, ...): any 36 | * -- system does stuff 37 | * end 38 | */ 39 | TYPE_BASIC_ANY, 40 | TYPE_BASIC_VOID 41 | }; 42 | 43 | struct type { 44 | enum type_kind kind; 45 | 46 | /* Data stored below */ 47 | union { 48 | struct { 49 | /* Kind of basic data type */ 50 | enum type_primitive_kind kind; 51 | } primitive; 52 | struct { 53 | /* Array kind --> Array */ 54 | struct type *type; 55 | 56 | struct node *node; /* Pointer to node constructor */ 57 | } array; 58 | struct { 59 | /* Table kind --> Table */ 60 | struct type *key; 61 | struct type *value; 62 | } table; 63 | struct { 64 | struct node *args_list; 65 | struct node *rets_list; 66 | } function; 67 | struct { 68 | struct node *name; 69 | struct node *node; /* node defining this type */ 70 | } custom; 71 | } data; 72 | }; 73 | 74 | struct type_context { 75 | bool is_strict; /* Strict context flag */ 76 | bool use_c_arrays; 77 | int error_count; /* Number of errors */ 78 | 79 | map_t type_map; /* Hashmap of all identifiers and types */ 80 | map_t global_type_map; /* Hashmap of all globals and their types */ 81 | }; 82 | 83 | void type_init(struct type_context *context); 84 | void type_destroy(struct type_context *context); 85 | 86 | struct type *type_basic(enum type_primitive_kind kind); 87 | struct type *type_array(struct type *type); 88 | struct type *type_table(struct type *key, struct type *value); 89 | struct type *type_function(struct node *args_list, struct node *rets_list); 90 | 91 | /* TODO: Add slots for types in classes (templates and inheritance) */ 92 | struct type *type_custom(struct node *name, struct node *node); 93 | 94 | bool type_is(struct type *first, struct type *second); 95 | void type_ast_traversal(struct type_context *context, struct node *node, bool main); 96 | 97 | char *type_to_string(struct type *type); 98 | 99 | #endif -------------------------------------------------------------------------------- /src/compiler/src/util/flexstr.c: -------------------------------------------------------------------------------- 1 | /* flexstr.c - 1.0 2 | * dynamic string library 3 | */ 4 | 5 | #include "flexstr.h" 6 | 7 | #include 8 | #include 9 | 10 | /* fs_init() -- initializes a new flex string instance 11 | * args: instance, amount to grow by 12 | * 13 | * Note: If `amt` is 0 then the string will grow by CHUNKSIZE 14 | */ 15 | void fs_init(flexstr_t *p, int amt) 16 | { 17 | p->fs_str = NULL; 18 | p->fs_space = p->fs_used = 0; 19 | p->fs_growby = (amt > 0 ? amt : CHUNKSIZE); 20 | } 21 | 22 | /* fs_free() -- free a flex string instance 23 | * args: instance 24 | */ 25 | void fs_free(flexstr_t *p) { free(p->fs_str); } 26 | 27 | /* fs_getstr() -- returns the string in the flex string instance 28 | * args: instance 29 | * returns: the string 30 | * 31 | * Note: The function terminates the string for you. 32 | */ 33 | char *fs_getstr(flexstr_t *p) 34 | { 35 | /* First make sure there's room for the '\0' */ 36 | if (p->fs_used == p->fs_space) { /* string is full, add room for one more char */ 37 | p->fs_str = srealloc(p->fs_str, ++p->fs_space); 38 | } 39 | 40 | /* Add terminating '\0'. Don't increment fs_used -- the '\0' is not part of 41 | * the string, and shouldn't be counted if someone wants to continue adding 42 | * characters to the string later. 43 | */ 44 | p->fs_str[p->fs_used] = '\0'; 45 | 46 | /* Now return the (terminated) string. */ 47 | return p->fs_str; 48 | } 49 | 50 | /* fs_addch() -- adds a character to the flex string 51 | * args: flex string, character 52 | * 53 | * Note: Invokes smalloc() if fs_str hasn't been alloced yet. Invokes srealloc to resize fs_str. 54 | */ 55 | void fs_addch(flexstr_t *p, char c) 56 | { 57 | /* Call smalloc() if we haven't allocated any memory yet */ 58 | if (p->fs_space == 0) { 59 | p->fs_str = smalloc(p->fs_growby); 60 | p->fs_used = 0; 61 | p->fs_space = p->fs_growby; 62 | } else if (p->fs_used + 1 >= p->fs_space) { /* +1 for \0 */ 63 | p->fs_space += p->fs_growby; 64 | p->fs_str = srealloc(p->fs_str, p->fs_space); 65 | } 66 | p->fs_str[p->fs_used++] = c; 67 | } 68 | 69 | void fs_addstr(flexstr_t *p, char *s) 70 | { 71 | int c; 72 | 73 | /* Add each character individually */ 74 | while ((c = *s++) != '\0') 75 | fs_addch(p, c); 76 | } 77 | 78 | /* smalloc() -- safely allocates memory for an object 79 | * args: number of bytes 80 | * returns: newly allocated memory 81 | * 82 | * Note: This function handles malloc() errors. 83 | */ 84 | void *smalloc(size_t n) 85 | { 86 | void *res; 87 | 88 | if ((res = malloc(n)) == NULL) { 89 | fprintf(stderr, "malloc(): out of memory\n"); 90 | exit(1); 91 | } 92 | return res; 93 | } 94 | 95 | /* srealloc() -- safely allocates additional memory for an object 96 | * args: object, number of bytes 97 | * returns: newly allocated memory 98 | * 99 | * Note: This function handles realloc() errors. 100 | */ 101 | void *srealloc(void *p, size_t n) 102 | { 103 | void *res; 104 | 105 | if ((res = realloc(p, n)) == NULL) { 106 | fprintf(stderr, "realloc(): unexpected failure\n"); 107 | exit(1); 108 | } 109 | return res; 110 | } -------------------------------------------------------------------------------- /src/compiler/src/util/flexstr.h: -------------------------------------------------------------------------------- 1 | #ifndef FLEXSTR_H 2 | #define FLEXSTR_H 3 | 4 | #include 5 | 6 | #define CHUNKSIZE 20 7 | 8 | struct flexstring { 9 | int fs_space; /* Total space allocated */ 10 | int fs_used; /* Total space used */ 11 | char *fs_str; /* String */ 12 | int fs_growby; /* Amount of byted fs_str will increase by */ 13 | }; 14 | 15 | typedef struct flexstring flexstr_t; 16 | 17 | /* Construction and destruction methods */ 18 | void fs_init(flexstr_t *p, int amt); 19 | void fs_free(flexstr_t *p); 20 | 21 | /* Other methods */ 22 | char *fs_getstr(flexstr_t *p); 23 | void fs_addch(flexstr_t *p, char c); 24 | void fs_addstr(flexstr_t *p, char *s); 25 | 26 | /* Safe malloc and realloc */ 27 | void *smalloc(size_t n); 28 | void *srealloc(void *p, size_t n); 29 | 30 | #endif -------------------------------------------------------------------------------- /src/compiler/src/util/hashmap.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Generic hashmap manipulation functions 3 | * 4 | * Originally by Elliot C Back - http://elliottback.com/wp/hashmap-implementation-in-c/ 5 | * 6 | * Modified by Pete Warden to fix a serious performance problem, support strings as keys 7 | * and removed thread synchronization - http://petewarden.typepad.com 8 | */ 9 | #ifndef __HASHMAP_H__ 10 | #define __HASHMAP_H__ 11 | 12 | #define MAP_MISSING -3 /* No such element */ 13 | #define MAP_FULL -2 /* Hashmap is full */ 14 | #define MAP_OMEM -1 /* Out of Memory */ 15 | #define MAP_OK 0 /* OK */ 16 | 17 | /* 18 | * any_t is a pointer. This allows you to put arbitrary structures in 19 | * the hashmap. 20 | */ 21 | typedef void *any_t; 22 | 23 | /* 24 | * PFany is a pointer to a function that can take two any_t arguments 25 | * and return an integer. Returns status code.. 26 | */ 27 | typedef int (*PFany)(any_t, any_t); 28 | 29 | /* 30 | * map_t is a pointer to an internally maintained data structure. 31 | * Clients of this package do not need to know how hashmaps are 32 | * represented. They see and manipulate only map_t's. 33 | */ 34 | typedef any_t map_t; 35 | 36 | /* 37 | * Return an empty hashmap. Returns NULL if empty. 38 | */ 39 | extern map_t hashmap_new(); 40 | 41 | /* 42 | * Iteratively call f with argument (item, data) for 43 | * each element data in the hashmap. The function must 44 | * return a map status code. If it returns anything other 45 | * than MAP_OK the traversal is terminated. f must 46 | * not reenter any hashmap functions, or deadlock may arise. 47 | */ 48 | extern int hashmap_iterate(map_t in, PFany f, any_t item); 49 | 50 | /* 51 | * Add an element to the hashmap. Return MAP_OK or MAP_OMEM. 52 | */ 53 | extern int hashmap_put(map_t in, char *key, any_t value); 54 | 55 | /* 56 | * Get an element from the hashmap. Return MAP_OK or MAP_MISSING. 57 | */ 58 | extern int hashmap_get(map_t in, char *key, any_t *arg); 59 | 60 | /* 61 | * Remove an element from the hashmap. Return MAP_OK or MAP_MISSING. 62 | */ 63 | extern int hashmap_remove(map_t in, char *key); 64 | 65 | /* 66 | * Get any element. Return MAP_OK or MAP_MISSING. 67 | * remove - should the element be removed from the hashmap 68 | */ 69 | extern int hashmap_get_one(map_t in, any_t *arg, int remove); 70 | 71 | /* 72 | * Free the hashmap 73 | */ 74 | extern void hashmap_free(map_t in); 75 | 76 | extern map_t hashmap_duplicate(map_t src); 77 | extern void hashmap_print(map_t map); 78 | 79 | /* 80 | * Get the current size of a hashmap 81 | */ 82 | extern int hashmap_length(map_t in); 83 | 84 | extern int hashmap_get_struct_size(); 85 | 86 | #endif -------------------------------------------------------------------------------- /src/interpreter/main.c: -------------------------------------------------------------------------------- 1 | /* main.c - entrypoint for the interpreter (combines VM and compiler) 2 | */ 3 | 4 | /* compiler dependencies */ 5 | #include "../compiler/src/compiler.h" 6 | 7 | #include "../vm/src/lua/lauxlib.h" 8 | #include "../vm/src/lua/lua.h" 9 | #include "../vm/src/lua/lualib.h" 10 | 11 | #include 12 | 13 | /* print_summary - prints a quick summary of a pass (elapsed time and number of 14 | * errors) 15 | * args: pass name, numer of errors, start time 16 | * rets: none 17 | */ 18 | static void print_summary(char *pass, int error_count) 19 | { 20 | printf("\n%s encountered %d %s.\n", pass, error_count, (error_count == 1 ? "error" : "errors")); 21 | } 22 | 23 | int main(int argc, char **argv) 24 | { 25 | int opt, error_count; 26 | size_t bufsize; 27 | char *dot, *buff; 28 | FILE *input, *output; 29 | 30 | time_t start; 31 | struct node *tree; 32 | 33 | /* Determine if we are using stdin or file in. */ 34 | if (optind == argc - 1) { 35 | /* Check if the input file is a .lpp or .lua file */ 36 | dot = strrchr(argv[optind], '.'); 37 | 38 | /* If the given file is of the correct type, init the lexer */ 39 | if (dot && !strcmp(dot, ".lpp") || !strcmp(dot, ".lua")) { 40 | if (!(input = fopen(argv[optind], "r"))) { 41 | printf("Error: unable to open file '%s'\n", argv[optind]); 42 | return 1; 43 | } 44 | } else { 45 | printf("Incorrect file type.\n"); 46 | return 1; 47 | } 48 | } else if (optind >= argc) 49 | input = stdin; 50 | else { 51 | printf("Expected 1 input file, found %d.\n", argc - optind); 52 | return 1; 53 | } 54 | 55 | if (!(output = open_memstream(&buff, &bufsize))) { 56 | printf("Error: unable to write to memory stream.\n"); 57 | return 1; 58 | } 59 | 60 | compiler_context_t context = {"codegen", 0}; 61 | if (!compile(&context, input, output)) 62 | return 1; 63 | 64 | fclose(output); 65 | 66 | if (!(input = fmemopen(buff, bufsize, "r"))) { 67 | printf("Error: unable to read memory stream.\n"); 68 | return 1; 69 | } 70 | 71 | lua_State *L = luaL_newstate(); 72 | luaL_openlibs(L); 73 | 74 | if (luapp_loadfile(L, "=lua++", input)) { 75 | /* An error occured, display it and pop it from the stack */ 76 | printf("Error: %s\n", lua_tostring(L, -1)); 77 | lua_pop(L, 1); 78 | 79 | /* Close everything and return */ 80 | lua_close(L); 81 | return 1; 82 | } 83 | 84 | /* Run the closure at L->top + 0 */ 85 | lua_resume(L, 0); 86 | lua_close(L); 87 | 88 | fclose(input); 89 | free(buff); 90 | return 0; 91 | } -------------------------------------------------------------------------------- /src/interpreter/tests/arrays.lua: -------------------------------------------------------------------------------- 1 | --!carrays 2 | local v: number = 1 3 | local array: Array = { 1, 2, 3, v } 4 | 5 | print(array["string"]) -------------------------------------------------------------------------------- /src/interpreter/tests/class.lua: -------------------------------------------------------------------------------- 1 | class MyClass { 2 | a: number, 3 | 4 | constructor(arg: number) 5 | end 6 | } -------------------------------------------------------------------------------- /src/interpreter/tests/compare.lua: -------------------------------------------------------------------------------- 1 | print("expected true; got:", 1 == 1) 2 | print("expected false; got:", 1 ~= 1) 3 | 4 | print("expected false; got:", 1 > 2) 5 | print("expected true; got:", 1 < 2) 6 | 7 | print("expected true; got:", 1 <= 2) 8 | print("expected false; got:", 1 >= 2) -------------------------------------------------------------------------------- /src/interpreter/tests/compound.lua: -------------------------------------------------------------------------------- 1 | local n: number = 1 2 | n += 2 3 | 4 | print("test1 -> sucess?", n == 3) 5 | 6 | local s: string = "test" 7 | s ..= "11" 8 | 9 | print("test2 -> sucess?", s == "test11") -------------------------------------------------------------------------------- /src/interpreter/tests/function.lua: -------------------------------------------------------------------------------- 1 | local function func(a: number, b: string): boolean 2 | print("some random print") 3 | print(a, b) 4 | return true 5 | end 6 | 7 | local function voidFun(): string 8 | return "str" 9 | end 10 | 11 | print("output: ", func(1, "a")) 12 | print(voidFun()) -------------------------------------------------------------------------------- /src/interpreter/tests/ifelse.lua: -------------------------------------------------------------------------------- 1 | local var: boolean = false 2 | 3 | if var then 4 | print("this should not happen") 5 | else 6 | print("this will happen") 7 | end -------------------------------------------------------------------------------- /src/interpreter/tests/increment.lua: -------------------------------------------------------------------------------- 1 | --!comment 2 | 3 | local a: number = 1 4 | print(a--) 5 | print(a) -------------------------------------------------------------------------------- /src/interpreter/tests/locals.lua: -------------------------------------------------------------------------------- 1 | -- Local assignments work in the VM now! 2 | local a: number = 12 3 | 4 | local b: string = "hello!" 5 | 6 | print(a, b) -------------------------------------------------------------------------------- /src/interpreter/tests/macros/lenient.lua: -------------------------------------------------------------------------------- 1 | --!lenient 2 | local legalAssignment = 1 3 | 4 | print(legalAssignment) 5 | 6 | randomCall(1, 2, 3, 4, 5) -------------------------------------------------------------------------------- /src/interpreter/tests/return.lua: -------------------------------------------------------------------------------- 1 | local function func(a: number): void 2 | return 3 | end -------------------------------------------------------------------------------- /src/interpreter/tests/table.lua: -------------------------------------------------------------------------------- 1 | local t: Table = { 2 | ["a"] = 1, 3 | ["aadad"] = 12 4 | } 5 | 6 | print(t["aadad"]) -------------------------------------------------------------------------------- /src/interpreter/tests/test.lua: -------------------------------------------------------------------------------- 1 | print("hello") 2 | print(100) 3 | print(100000000000000000000000000) -------------------------------------------------------------------------------- /src/interpreter/tests/userTest.lua: -------------------------------------------------------------------------------- 1 | --Helo world 2 | local function HW(): void 3 | print(1) 4 | end 5 | 6 | --local a = HW 7 | 8 | HW() 9 | print = nil 10 | --HW() 11 | 12 | -------------------------------------------------------------------------------- /src/vm/README.md: -------------------------------------------------------------------------------- 1 | ## Lua++ VM 2 | The current folder contains all of the contents of the runtime executable (```luappvm```). The VM has been designed to use little to no external dependencies making it as compact and efficient as possible. I apologize for any illegible or messy code, I still need to revise much of it. 3 | 4 | ### Runnning the VM 5 | To run the vm use the following command: 6 | ``` 7 | ./bin/luappvm input.bin 8 | ``` 9 | -------------------------------------------------------------------------------- /src/vm/src/load.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "../../common/bytecode.h" 7 | 8 | #include "lua/ldebug.h" 9 | #include "lua/lfunc.h" 10 | #include "lua/lstate.h" 11 | #include "lua/lstring.h" 12 | #include "lua/luaconf.h" 13 | #include "lua/lvm.h" 14 | 15 | /* Use global offset as we will need for Lua functions (luaS_newlstr) */ 16 | static size_t offset = 0; 17 | 18 | #define read_type(data, type) \ 19 | ({ \ 20 | type value; \ 21 | fread(&value, sizeof(value), 1, data); \ 22 | \ 23 | value; \ 24 | }) 25 | 26 | static uint32_t read_size(FILE *data) 27 | { 28 | uint32_t result = 0, shift = 0; 29 | uint8_t byte; 30 | 31 | do { 32 | byte = read_type(data, uint8_t); 33 | result |= (byte & 127) << shift; 34 | shift += 7; 35 | } while (byte & 128); 36 | 37 | return result; 38 | } 39 | 40 | static TString *read_string(lua_State *L, FILE *input) 41 | { 42 | uint32_t count = read_size(input); 43 | 44 | /* Very hacky but it works! */ 45 | char str[LUAL_BUFFERSIZE]; 46 | 47 | for (int32_t i = 0; i < count; i++) 48 | str[i] = read_type(input, uint8_t); 49 | 50 | return luaS_newlstr(L, str, count); 51 | } 52 | 53 | static TString **read_strings(lua_State *L, FILE *input, uint32_t count) 54 | { 55 | /* Create new strings vector */ 56 | TString **strings = luaM_newvector(L, count, TString *); 57 | 58 | for (int32_t i = 0; i < count; i++) 59 | strings[i] = read_string(L, input); 60 | 61 | return strings; 62 | } 63 | 64 | static Proto *read_proto(lua_State *L, FILE *input, Proto **protos, TString **strings, TString *source) 65 | { 66 | Proto *p = luaF_newproto(L); 67 | 68 | /* Read important proto information */ 69 | p->source = source; 70 | p->maxstacksize = read_type(input, uint8_t); 71 | p->numparams = read_type(input, uint8_t); 72 | p->nups = read_type(input, uint8_t); 73 | p->is_vararg = read_type(input, uint8_t); 74 | 75 | /* Create our new instruction array */ 76 | p->sizecode = read_size(input); 77 | p->code = luaM_newvector(L, p->sizecode, Instruction); 78 | 79 | /* Read the instruction array */ 80 | for (int i = 0; i < p->sizecode; i++) 81 | p->code[i] = read_type(input, uint32_t); 82 | 83 | /* Read the constant pool */ 84 | p->sizek = read_size(input); 85 | p->k = luaM_newvector(L, p->sizek, TValue); 86 | 87 | /* Process all the constants in the pool */ 88 | for (int32_t i = 0; i < p->sizek; i++) { 89 | constant_t c = read_type(input, uint8_t); 90 | /* Handle each type individually */ 91 | switch (c) { 92 | case CONSTANT_NIL: 93 | setnilvalue(&p->k[i]); 94 | break; 95 | case CONSTANT_BOOLEAN: { 96 | uint8_t value = read_type(input, uint8_t); 97 | setbvalue(&p->k[i], value); 98 | break; 99 | } 100 | case CONSTANT_NUMBER: { 101 | double value = read_type(input, double); 102 | setnvalue(&p->k[i], value); 103 | break; 104 | } 105 | case CONSTANT_STRING: { 106 | uint32_t index = read_size(input); 107 | setsvalue(L, &p->k[i], strings[index - 1]); 108 | break; 109 | } 110 | case CONSTANT_ENVIRONMENT: { 111 | /* For environment constants we need to load them before execution (so invoke 112 | * luaV_gettable, etc.). This will make execution speeds much faster as these 113 | * hashtable lookups don't need to be done during execution. */ 114 | uint32_t index = read_type(input, uint32_t); 115 | 116 | luaV_getenv(L, hvalue(gt(L)), &p->k[index]); 117 | setobj(L, &p->k[i], L->top - 1); 118 | L->top--; 119 | break; 120 | } 121 | } 122 | } 123 | 124 | /* Load closures into the function prototype */ 125 | p->sizep = read_size(input); 126 | p->p = luaM_newvector(L, p->sizep, Proto*); 127 | 128 | for (uint32_t i = 0; i < p->sizep; ++i) { 129 | const uint32_t idx = read_size(input); 130 | 131 | p->p[i] = protos[idx]; 132 | } 133 | 134 | return p; 135 | } 136 | 137 | static Proto **read_protos(lua_State *L, FILE *input, uint32_t count, TString **strings, 138 | TString *source) 139 | { 140 | /* Create new protos vector */ 141 | Proto **protos = luaM_newvector(L, count, Proto *); 142 | 143 | for (int32_t i = 0; i < count; i++) { 144 | protos[i] = read_proto(L, input, protos, strings, source); 145 | } 146 | 147 | return protos; 148 | } 149 | 150 | int32_t luapp_loadfile(lua_State *L, const char *chunkname, FILE *input) 151 | { 152 | /* Read version number */ 153 | version_t version = read_type(input, uint8_t); 154 | 155 | /* Make sure the VM can process this bytecode version */ 156 | if (!VERSION_ACCEPTABLE(version)) { 157 | lua_pushfstring(L, "incorrect version: expected version [%d..%d], got %d", MIN_VERSION, 158 | MAX_VERSION, version); 159 | return 1; 160 | } 161 | 162 | TString *source = luaS_new(L, chunkname); 163 | 164 | /* Read the string table */ 165 | uint32_t string_count = read_size(input); 166 | TString **strings = read_strings(L, input, string_count); 167 | 168 | /* Read function prototypes */ 169 | uint32_t proto_count = read_size(input); 170 | Proto **protos = read_protos(L, input, proto_count, strings, source); 171 | 172 | /* Create and push a closure onto the stack */ 173 | Closure *cl = luaF_newLclosure(L, 0, hvalue(gt(L))); 174 | cl->l.p = protos[read_size(input)]; 175 | setclvalue(L, L->top, cl); 176 | incr_top(L); 177 | 178 | /* Dispose of the string array as we don't need it anymore */ 179 | luaM_free(L, strings); 180 | return 0; 181 | } -------------------------------------------------------------------------------- /src/vm/src/lua/Makefile: -------------------------------------------------------------------------------- 1 | # makefile for building Lua 2 | # see ../INSTALL for installation instructions 3 | # see ../Makefile and luaconf.h for further customization 4 | 5 | # == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT ======================= 6 | 7 | # Your platform. See PLATS for possible values. 8 | PLAT= none 9 | 10 | CC= gcc 11 | CFLAGS= -O2 -Wall $(MYCFLAGS) 12 | AR= ar rcu 13 | RANLIB= ranlib 14 | RM= rm -f 15 | LIBS= -lm $(MYLIBS) 16 | 17 | MYCFLAGS= 18 | MYLDFLAGS= 19 | MYLIBS= 20 | 21 | # == END OF USER SETTINGS. NO NEED TO CHANGE ANYTHING BELOW THIS LINE ========= 22 | 23 | PLATS= aix ansi bsd freebsd generic linux macosx mingw posix solaris 24 | 25 | LUA_A= liblua.a 26 | CORE_O= lapi.o lcode.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o lmem.o \ 27 | lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o ltm.o \ 28 | lundump.o lvm.o lzio.o 29 | LIB_O= lauxlib.o lbaselib.o ldblib.o liolib.o lmathlib.o loslib.o ltablib.o \ 30 | lstrlib.o loadlib.o linit.o 31 | 32 | LUA_T= lua 33 | LUA_O= lua.o 34 | 35 | LUAC_T= luac 36 | LUAC_O= luac.o print.o 37 | 38 | ALL_O= $(CORE_O) $(LIB_O) $(LUA_O) $(LUAC_O) 39 | ALL_T= $(LUA_A) $(LUA_T) $(LUAC_T) 40 | ALL_A= $(LUA_A) 41 | 42 | default: $(PLAT) 43 | 44 | all: $(ALL_T) 45 | 46 | o: $(ALL_O) 47 | 48 | a: $(ALL_A) 49 | 50 | $(LUA_A): $(CORE_O) $(LIB_O) 51 | $(AR) $@ $(CORE_O) $(LIB_O) # DLL needs all object files 52 | $(RANLIB) $@ 53 | 54 | $(LUA_T): $(LUA_O) $(LUA_A) 55 | $(CC) -o $@ $(MYLDFLAGS) $(LUA_O) $(LUA_A) $(LIBS) 56 | 57 | $(LUAC_T): $(LUAC_O) $(LUA_A) 58 | $(CC) -o $@ $(MYLDFLAGS) $(LUAC_O) $(LUA_A) $(LIBS) 59 | 60 | clean: 61 | $(RM) $(ALL_T) $(ALL_O) 62 | 63 | depend: 64 | @$(CC) $(CFLAGS) -MM l*.c print.c 65 | 66 | echo: 67 | @echo "PLAT = $(PLAT)" 68 | @echo "CC = $(CC)" 69 | @echo "CFLAGS = $(CFLAGS)" 70 | @echo "AR = $(AR)" 71 | @echo "RANLIB = $(RANLIB)" 72 | @echo "RM = $(RM)" 73 | @echo "MYCFLAGS = $(MYCFLAGS)" 74 | @echo "MYLDFLAGS = $(MYLDFLAGS)" 75 | @echo "MYLIBS = $(MYLIBS)" 76 | 77 | # convenience targets for popular platforms 78 | 79 | none: 80 | @echo "Please choose a platform:" 81 | @echo " $(PLATS)" 82 | 83 | aix: 84 | $(MAKE) all CC="xlc" CFLAGS="-O2 -DLUA_USE_POSIX -DLUA_USE_DLOPEN" MYLIBS="-ldl" MYLDFLAGS="-brtl -bexpall" 85 | 86 | ansi: 87 | $(MAKE) all MYCFLAGS=-DLUA_ANSI 88 | 89 | bsd: 90 | $(MAKE) all MYCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN" MYLIBS="-Wl,-E" 91 | 92 | freebsd: 93 | $(MAKE) all MYCFLAGS="-DLUA_USE_LINUX" MYLIBS="-Wl,-E -lreadline" 94 | 95 | generic: 96 | $(MAKE) all MYCFLAGS= 97 | 98 | linux: 99 | $(MAKE) all MYCFLAGS=-DLUA_USE_LINUX MYLIBS="-Wl,-E -ldl -lreadline -lhistory -lncurses" 100 | 101 | macosx: 102 | $(MAKE) all MYCFLAGS=-DLUA_USE_LINUX MYLIBS="-lreadline" 103 | # use this on Mac OS X 10.3- 104 | # $(MAKE) all MYCFLAGS=-DLUA_USE_MACOSX 105 | 106 | mingw: 107 | $(MAKE) "LUA_A=lua51.dll" "LUA_T=lua.exe" \ 108 | "AR=$(CC) -shared -o" "RANLIB=strip --strip-unneeded" \ 109 | "MYCFLAGS=-DLUA_BUILD_AS_DLL" "MYLIBS=" "MYLDFLAGS=-s" lua.exe 110 | $(MAKE) "LUAC_T=luac.exe" luac.exe 111 | 112 | posix: 113 | $(MAKE) all MYCFLAGS=-DLUA_USE_POSIX 114 | 115 | solaris: 116 | $(MAKE) all MYCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN" MYLIBS="-ldl" 117 | 118 | # list targets that do not create files (but not all makes understand .PHONY) 119 | .PHONY: all $(PLATS) default o a clean depend echo none 120 | 121 | # DO NOT DELETE 122 | 123 | lapi.o: lapi.c lua.h luaconf.h lapi.h lobject.h llimits.h ldebug.h \ 124 | lstate.h ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h lstring.h ltable.h \ 125 | lundump.h lvm.h 126 | lauxlib.o: lauxlib.c lua.h luaconf.h lauxlib.h 127 | lbaselib.o: lbaselib.c lua.h luaconf.h lauxlib.h lualib.h 128 | lcode.o: lcode.c lua.h luaconf.h lcode.h llex.h lobject.h llimits.h \ 129 | lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h ldo.h lgc.h \ 130 | ltable.h 131 | ldblib.o: ldblib.c lua.h luaconf.h lauxlib.h lualib.h 132 | ldebug.o: ldebug.c lua.h luaconf.h lapi.h lobject.h llimits.h lcode.h \ 133 | llex.h lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h ldo.h \ 134 | lfunc.h lstring.h lgc.h ltable.h lvm.h 135 | ldo.o: ldo.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h ltm.h \ 136 | lzio.h lmem.h ldo.h lfunc.h lgc.h lopcodes.h lparser.h lstring.h \ 137 | ltable.h lundump.h lvm.h 138 | ldump.o: ldump.c lua.h luaconf.h lobject.h llimits.h lstate.h ltm.h \ 139 | lzio.h lmem.h lundump.h 140 | lfunc.o: lfunc.c lua.h luaconf.h lfunc.h lobject.h llimits.h lgc.h lmem.h \ 141 | lstate.h ltm.h lzio.h 142 | lgc.o: lgc.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h ltm.h \ 143 | lzio.h lmem.h ldo.h lfunc.h lgc.h lstring.h ltable.h 144 | linit.o: linit.c lua.h luaconf.h lualib.h lauxlib.h 145 | liolib.o: liolib.c lua.h luaconf.h lauxlib.h lualib.h 146 | llex.o: llex.c lua.h luaconf.h ldo.h lobject.h llimits.h lstate.h ltm.h \ 147 | lzio.h lmem.h llex.h lparser.h lstring.h lgc.h ltable.h 148 | lmathlib.o: lmathlib.c lua.h luaconf.h lauxlib.h lualib.h 149 | lmem.o: lmem.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \ 150 | ltm.h lzio.h lmem.h ldo.h 151 | loadlib.o: loadlib.c lua.h luaconf.h lauxlib.h lualib.h 152 | lobject.o: lobject.c lua.h luaconf.h ldo.h lobject.h llimits.h lstate.h \ 153 | ltm.h lzio.h lmem.h lstring.h lgc.h lvm.h 154 | lopcodes.o: lopcodes.c lopcodes.h llimits.h lua.h luaconf.h 155 | loslib.o: loslib.c lua.h luaconf.h lauxlib.h lualib.h 156 | lparser.o: lparser.c lua.h luaconf.h lcode.h llex.h lobject.h llimits.h \ 157 | lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h ldo.h \ 158 | lfunc.h lstring.h lgc.h ltable.h 159 | lstate.o: lstate.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \ 160 | ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h llex.h lstring.h ltable.h 161 | lstring.o: lstring.c lua.h luaconf.h lmem.h llimits.h lobject.h lstate.h \ 162 | ltm.h lzio.h lstring.h lgc.h 163 | lstrlib.o: lstrlib.c lua.h luaconf.h lauxlib.h lualib.h 164 | ltable.o: ltable.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \ 165 | ltm.h lzio.h lmem.h ldo.h lgc.h ltable.h 166 | ltablib.o: ltablib.c lua.h luaconf.h lauxlib.h lualib.h 167 | ltm.o: ltm.c lua.h luaconf.h lobject.h llimits.h lstate.h ltm.h lzio.h \ 168 | lmem.h lstring.h lgc.h ltable.h 169 | lua.o: lua.c lua.h luaconf.h lauxlib.h lualib.h 170 | luac.o: luac.c lua.h luaconf.h lauxlib.h ldo.h lobject.h llimits.h \ 171 | lstate.h ltm.h lzio.h lmem.h lfunc.h lopcodes.h lstring.h lgc.h \ 172 | lundump.h 173 | lundump.o: lundump.c lua.h luaconf.h ldebug.h lstate.h lobject.h \ 174 | llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lstring.h lgc.h lundump.h 175 | lvm.o: lvm.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h ltm.h \ 176 | lzio.h lmem.h ldo.h lfunc.h lgc.h lopcodes.h lstring.h ltable.h lvm.h 177 | lzio.o: lzio.c lua.h luaconf.h llimits.h lmem.h lstate.h lobject.h ltm.h \ 178 | lzio.h 179 | print.o: print.c ldebug.h lstate.h lua.h luaconf.h lobject.h llimits.h \ 180 | ltm.h lzio.h lmem.h lopcodes.h lundump.h 181 | 182 | # (end of Makefile) 183 | -------------------------------------------------------------------------------- /src/vm/src/lua/lapi.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lapi.h,v 2.2.1.1 2007/12/27 13:02:25 roberto Exp $ 3 | ** Auxiliary functions from Lua API 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef lapi_h 8 | #define lapi_h 9 | 10 | #include "lobject.h" 11 | 12 | LUAI_FUNC void luaA_pushobject(lua_State *L, const TValue *o); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /src/vm/src/lua/lauxlib.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lauxlib.h,v 1.88.1.1 2007/12/27 13:02:25 roberto Exp $ 3 | ** Auxiliary functions for building Lua libraries 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef lauxlib_h 8 | #define lauxlib_h 9 | 10 | #include 11 | #include 12 | 13 | #include "lua.h" 14 | 15 | #if defined(LUA_COMPAT_GETN) 16 | LUALIB_API int(luaL_getn)(lua_State *L, int t); 17 | LUALIB_API void(luaL_setn)(lua_State *L, int t, int n); 18 | #else 19 | #define luaL_getn(L, i) ((int)lua_objlen(L, i)) 20 | #define luaL_setn(L, i, j) ((void)0) /* no op! */ 21 | #endif 22 | 23 | #if defined(LUA_COMPAT_OPENLIB) 24 | #define luaI_openlib luaL_openlib 25 | #endif 26 | 27 | /* extra error code for `luaL_load' */ 28 | #define LUA_ERRFILE (LUA_ERRERR + 1) 29 | 30 | typedef struct luaL_Reg { 31 | const char *name; 32 | lua_CFunction func; 33 | } luaL_Reg; 34 | 35 | LUALIB_API void(luaI_openlib)(lua_State *L, const char *libname, const luaL_Reg *l, int nup); 36 | LUALIB_API void(luaL_register)(lua_State *L, const char *libname, const luaL_Reg *l); 37 | LUALIB_API int(luaL_getmetafield)(lua_State *L, int obj, const char *e); 38 | LUALIB_API int(luaL_callmeta)(lua_State *L, int obj, const char *e); 39 | LUALIB_API int(luaL_typerror)(lua_State *L, int narg, const char *tname); 40 | LUALIB_API int(luaL_argerror)(lua_State *L, int numarg, const char *extramsg); 41 | LUALIB_API const char *(luaL_checklstring)(lua_State *L, int numArg, size_t *l); 42 | LUALIB_API const char *(luaL_optlstring)(lua_State *L, int numArg, const char *def, size_t *l); 43 | LUALIB_API lua_Number(luaL_checknumber)(lua_State *L, int numArg); 44 | LUALIB_API lua_Number(luaL_optnumber)(lua_State *L, int nArg, lua_Number def); 45 | 46 | LUALIB_API lua_Integer(luaL_checkinteger)(lua_State *L, int numArg); 47 | LUALIB_API lua_Integer(luaL_optinteger)(lua_State *L, int nArg, lua_Integer def); 48 | 49 | LUALIB_API void(luaL_checkstack)(lua_State *L, int sz, const char *msg); 50 | LUALIB_API void(luaL_checktype)(lua_State *L, int narg, int t); 51 | LUALIB_API void(luaL_checkany)(lua_State *L, int narg); 52 | 53 | LUALIB_API int(luaL_newmetatable)(lua_State *L, const char *tname); 54 | LUALIB_API void *(luaL_checkudata)(lua_State *L, int ud, const char *tname); 55 | 56 | LUALIB_API void(luaL_where)(lua_State *L, int lvl); 57 | LUALIB_API int(luaL_error)(lua_State *L, const char *fmt, ...); 58 | 59 | LUALIB_API int(luaL_checkoption)(lua_State *L, int narg, const char *def, const char *const lst[]); 60 | 61 | LUALIB_API int(luaL_ref)(lua_State *L, int t); 62 | LUALIB_API void(luaL_unref)(lua_State *L, int t, int ref); 63 | 64 | LUALIB_API int(luaL_loadfile)(lua_State *L, const char *filename); 65 | LUALIB_API int(luaL_loadbuffer)(lua_State *L, const char *buff, size_t sz, const char *name); 66 | LUALIB_API int(luaL_loadstring)(lua_State *L, const char *s); 67 | 68 | LUALIB_API lua_State *(luaL_newstate)(void); 69 | 70 | LUALIB_API const char *(luaL_gsub)(lua_State *L, const char *s, const char *p, const char *r); 71 | 72 | LUALIB_API const char *(luaL_findtable)(lua_State *L, int idx, const char *fname, int szhint); 73 | 74 | /* 75 | ** =============================================================== 76 | ** some useful macros 77 | ** =============================================================== 78 | */ 79 | 80 | #define luaL_argcheck(L, cond, numarg, extramsg) \ 81 | ((void)((cond) || luaL_argerror(L, (numarg), (extramsg)))) 82 | #define luaL_checkstring(L, n) (luaL_checklstring(L, (n), NULL)) 83 | #define luaL_optstring(L, n, d) (luaL_optlstring(L, (n), (d), NULL)) 84 | #define luaL_checkint(L, n) ((int)luaL_checkinteger(L, (n))) 85 | #define luaL_optint(L, n, d) ((int)luaL_optinteger(L, (n), (d))) 86 | #define luaL_checklong(L, n) ((long)luaL_checkinteger(L, (n))) 87 | #define luaL_optlong(L, n, d) ((long)luaL_optinteger(L, (n), (d))) 88 | 89 | #define luaL_typename(L, i) lua_typename(L, lua_type(L, (i))) 90 | 91 | #define luaL_dofile(L, fn) (luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0)) 92 | 93 | #define luaL_dostring(L, s) (luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0)) 94 | 95 | #define luaL_getmetatable(L, n) (lua_getfield(L, LUA_REGISTRYINDEX, (n))) 96 | 97 | #define luaL_opt(L, f, n, d) (lua_isnoneornil(L, (n)) ? (d) : f(L, (n))) 98 | 99 | /* 100 | ** {====================================================== 101 | ** Generic Buffer manipulation 102 | ** ======================================================= 103 | */ 104 | 105 | typedef struct luaL_Buffer { 106 | char *p; /* current position in buffer */ 107 | int lvl; /* number of strings in the stack (level) */ 108 | lua_State *L; 109 | char buffer[LUAL_BUFFERSIZE]; 110 | } luaL_Buffer; 111 | 112 | #define luaL_addchar(B, c) \ 113 | ((void)((B)->p < ((B)->buffer + LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \ 114 | (*(B)->p++ = (char)(c))) 115 | 116 | /* compatibility only */ 117 | #define luaL_putchar(B, c) luaL_addchar(B, c) 118 | 119 | #define luaL_addsize(B, n) ((B)->p += (n)) 120 | 121 | LUALIB_API void(luaL_buffinit)(lua_State *L, luaL_Buffer *B); 122 | LUALIB_API char *(luaL_prepbuffer)(luaL_Buffer *B); 123 | LUALIB_API void(luaL_addlstring)(luaL_Buffer *B, const char *s, size_t l); 124 | LUALIB_API void(luaL_addstring)(luaL_Buffer *B, const char *s); 125 | LUALIB_API void(luaL_addvalue)(luaL_Buffer *B); 126 | LUALIB_API void(luaL_pushresult)(luaL_Buffer *B); 127 | 128 | /* }====================================================== */ 129 | 130 | /* compatibility with ref system */ 131 | 132 | /* pre-defined references */ 133 | #define LUA_NOREF (-2) 134 | #define LUA_REFNIL (-1) 135 | 136 | #define lua_ref(L, lock) \ 137 | ((lock) ? luaL_ref(L, LUA_REGISTRYINDEX) \ 138 | : (lua_pushstring(L, "unlocked references are obsolete"), lua_error(L), 0)) 139 | 140 | #define lua_unref(L, ref) luaL_unref(L, LUA_REGISTRYINDEX, (ref)) 141 | 142 | #define lua_getref(L, ref) lua_rawgeti(L, LUA_REGISTRYINDEX, (ref)) 143 | 144 | #define luaL_reg luaL_Reg 145 | 146 | #endif 147 | -------------------------------------------------------------------------------- /src/vm/src/lua/ldebug.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: ldebug.h,v 2.3.1.1 2007/12/27 13:02:25 roberto Exp $ 3 | ** Auxiliary functions from Debug Interface module 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef ldebug_h 8 | #define ldebug_h 9 | 10 | #include "lstate.h" 11 | 12 | #define pcRel(pc, p) (cast(int, (pc) - (p)->code) - 1) 13 | 14 | #define getline(f, pc) (((f)->lineinfo) ? (f)->lineinfo[pc] : 0) 15 | 16 | #define resethookcount(L) (L->hookcount = L->basehookcount) 17 | 18 | LUAI_FUNC void luaG_typeerror(lua_State *L, const TValue *o, const char *opname); 19 | LUAI_FUNC void luaG_concaterror(lua_State *L, StkId p1, StkId p2); 20 | LUAI_FUNC void luaG_aritherror(lua_State *L, const TValue *p1, const TValue *p2); 21 | LUAI_FUNC int luaG_ordererror(lua_State *L, const TValue *p1, const TValue *p2); 22 | LUAI_FUNC void luaG_runerror(lua_State *L, const char *fmt, ...); 23 | LUAI_FUNC void luaG_errormsg(lua_State *L); 24 | LUAI_FUNC int luaG_checkcode(const Proto *pt); 25 | LUAI_FUNC int luaG_checkopenop(Instruction i); 26 | 27 | LUA_API void luaU_print(const Proto *f, int full); 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /src/vm/src/lua/ldo.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: ldo.h,v 2.7.1.1 2007/12/27 13:02:25 roberto Exp $ 3 | ** Stack and Call structure of Lua 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef ldo_h 8 | #define ldo_h 9 | 10 | #include "lobject.h" 11 | #include "lstate.h" 12 | #include "lzio.h" 13 | 14 | #define luaD_checkstack(L, n) \ 15 | if ((char *)L->stack_last - (char *)L->top <= (n) * (int)sizeof(TValue)) \ 16 | luaD_growstack(L, n); \ 17 | else \ 18 | condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); 19 | 20 | #define incr_top(L) \ 21 | { \ 22 | luaD_checkstack(L, 1); \ 23 | L->top++; \ 24 | } 25 | 26 | #define savestack(L, p) ((char *)(p) - (char *)L->stack) 27 | #define restorestack(L, n) ((TValue *)((char *)L->stack + (n))) 28 | 29 | #define saveci(L, p) ((char *)(p) - (char *)L->base_ci) 30 | #define restoreci(L, n) ((CallInfo *)((char *)L->base_ci + (n))) 31 | 32 | /* results from luaD_precall */ 33 | #define PCRLUA 0 /* initiated a call to a Lua function */ 34 | #define PCRC 1 /* did a call to a C function */ 35 | #define PCRYIELD 2 /* C funtion yielded */ 36 | 37 | /* type of protected functions, to be ran by `runprotected' */ 38 | typedef void (*Pfunc)(lua_State *L, void *ud); 39 | 40 | LUAI_FUNC int luaD_protectedparser(lua_State *L, ZIO *z, const char *name); 41 | LUAI_FUNC void luaD_callhook(lua_State *L, int event, int line); 42 | LUAI_FUNC int luaD_precall(lua_State *L, StkId func, int nresults); 43 | LUAI_FUNC void luaD_call(lua_State *L, StkId func, int nResults); 44 | LUAI_FUNC int luaD_pcall(lua_State *L, Pfunc func, void *u, ptrdiff_t oldtop, ptrdiff_t ef); 45 | LUAI_FUNC int luaD_poscall(lua_State *L, StkId firstResult); 46 | LUAI_FUNC void luaD_reallocCI(lua_State *L, int newsize); 47 | LUAI_FUNC void luaD_reallocstack(lua_State *L, int newsize); 48 | LUAI_FUNC void luaD_growstack(lua_State *L, int n); 49 | 50 | LUAI_FUNC void luaD_throw(lua_State *L, int errcode); 51 | LUAI_FUNC int luaD_rawrunprotected(lua_State *L, Pfunc f, void *ud); 52 | 53 | LUAI_FUNC void luaD_seterrorobj(lua_State *L, int errcode, StkId oldtop); 54 | 55 | #endif 56 | -------------------------------------------------------------------------------- /src/vm/src/lua/lfunc.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lfunc.c,v 2.12.1.2 2007/12/28 14:58:43 roberto Exp $ 3 | ** Auxiliary functions to manipulate prototypes and closures 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #include 8 | 9 | #define lfunc_c 10 | #define LUA_CORE 11 | 12 | #include "lua.h" 13 | 14 | #include "lfunc.h" 15 | #include "lgc.h" 16 | #include "lmem.h" 17 | #include "lobject.h" 18 | #include "lstate.h" 19 | 20 | Closure *luaF_newCclosure(lua_State *L, int nelems, Table *e) 21 | { 22 | Closure *c = cast(Closure *, luaM_malloc(L, sizeCclosure(nelems))); 23 | luaC_link(L, obj2gco(c), LUA_TFUNCTION); 24 | c->c.isC = 1; 25 | c->c.env = e; 26 | c->c.nupvalues = cast_byte(nelems); 27 | return c; 28 | } 29 | 30 | Closure *luaF_newLclosure(lua_State *L, int nelems, Table *e) 31 | { 32 | Closure *c = cast(Closure *, luaM_malloc(L, sizeLclosure(nelems))); 33 | luaC_link(L, obj2gco(c), LUA_TFUNCTION); 34 | c->l.isC = 0; 35 | c->l.env = e; 36 | c->l.nupvalues = cast_byte(nelems); 37 | while (nelems--) 38 | c->l.upvals[nelems] = NULL; 39 | return c; 40 | } 41 | 42 | UpVal *luaF_newupval(lua_State *L) 43 | { 44 | UpVal *uv = luaM_new(L, UpVal); 45 | luaC_link(L, obj2gco(uv), LUA_TUPVAL); 46 | uv->v = &uv->u.value; 47 | setnilvalue(uv->v); 48 | return uv; 49 | } 50 | 51 | UpVal *luaF_findupval(lua_State *L, StkId level) 52 | { 53 | global_State *g = G(L); 54 | GCObject **pp = &L->openupval; 55 | UpVal *p; 56 | UpVal *uv; 57 | while (*pp != NULL && (p = ngcotouv(*pp))->v >= level) { 58 | lua_assert(p->v != &p->u.value); 59 | if (p->v == level) { /* found a corresponding upvalue? */ 60 | if (isdead(g, obj2gco(p))) /* is it dead? */ 61 | changewhite(obj2gco(p)); /* ressurect it */ 62 | return p; 63 | } 64 | pp = &p->next; 65 | } 66 | uv = luaM_new(L, UpVal); /* not found: create a new one */ 67 | uv->tt = LUA_TUPVAL; 68 | uv->marked = luaC_white(g); 69 | uv->v = level; /* current value lives in the stack */ 70 | uv->next = *pp; /* chain it in the proper position */ 71 | *pp = obj2gco(uv); 72 | uv->u.l.prev = &g->uvhead; /* double link it in `uvhead' list */ 73 | uv->u.l.next = g->uvhead.u.l.next; 74 | uv->u.l.next->u.l.prev = uv; 75 | g->uvhead.u.l.next = uv; 76 | lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); 77 | return uv; 78 | } 79 | 80 | static void unlinkupval(UpVal *uv) 81 | { 82 | lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); 83 | uv->u.l.next->u.l.prev = uv->u.l.prev; /* remove from `uvhead' list */ 84 | uv->u.l.prev->u.l.next = uv->u.l.next; 85 | } 86 | 87 | void luaF_freeupval(lua_State *L, UpVal *uv) 88 | { 89 | if (uv->v != &uv->u.value) /* is it open? */ 90 | unlinkupval(uv); /* remove from open list */ 91 | luaM_free(L, uv); /* free upvalue */ 92 | } 93 | 94 | void luaF_close(lua_State *L, StkId level) 95 | { 96 | UpVal *uv; 97 | global_State *g = G(L); 98 | while (L->openupval != NULL && (uv = ngcotouv(L->openupval))->v >= level) { 99 | GCObject *o = obj2gco(uv); 100 | lua_assert(!isblack(o) && uv->v != &uv->u.value); 101 | L->openupval = uv->next; /* remove from `open' list */ 102 | if (isdead(g, o)) 103 | luaF_freeupval(L, uv); /* free upvalue */ 104 | else { 105 | unlinkupval(uv); 106 | setobj(L, &uv->u.value, uv->v); 107 | uv->v = &uv->u.value; /* now current value lives here */ 108 | luaC_linkupval(L, uv); /* link upvalue into `gcroot' list */ 109 | } 110 | } 111 | } 112 | 113 | Proto *luaF_newproto(lua_State *L) 114 | { 115 | Proto *f = luaM_new(L, Proto); 116 | luaC_link(L, obj2gco(f), LUA_TPROTO); 117 | f->k = NULL; 118 | f->sizek = 0; 119 | f->p = NULL; 120 | f->sizep = 0; 121 | f->code = NULL; 122 | f->sizecode = 0; 123 | f->sizelineinfo = 0; 124 | f->sizeupvalues = 0; 125 | f->nups = 0; 126 | f->upvalues = NULL; 127 | f->numparams = 0; 128 | f->is_vararg = 0; 129 | f->maxstacksize = 0; 130 | f->lineinfo = NULL; 131 | f->sizelocvars = 0; 132 | f->locvars = NULL; 133 | f->linedefined = 0; 134 | f->lastlinedefined = 0; 135 | f->source = NULL; 136 | return f; 137 | } 138 | 139 | void luaF_freeproto(lua_State *L, Proto *f) 140 | { 141 | luaM_freearray(L, f->code, f->sizecode, Instruction); 142 | luaM_freearray(L, f->p, f->sizep, Proto *); 143 | luaM_freearray(L, f->k, f->sizek, TValue); 144 | luaM_freearray(L, f->lineinfo, f->sizelineinfo, int); 145 | luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar); 146 | luaM_freearray(L, f->upvalues, f->sizeupvalues, TString *); 147 | luaM_free(L, f); 148 | } 149 | 150 | void luaF_freeclosure(lua_State *L, Closure *c) 151 | { 152 | int size = (c->c.isC) ? sizeCclosure(c->c.nupvalues) : sizeLclosure(c->l.nupvalues); 153 | luaM_freemem(L, c, size); 154 | } 155 | 156 | /* 157 | ** Look for n-th local variable at line `line' in function `func'. 158 | ** Returns NULL if not found. 159 | */ 160 | const char *luaF_getlocalname(const Proto *f, int local_number, int pc) 161 | { 162 | int i; 163 | for (i = 0; i < f->sizelocvars && f->locvars[i].startpc <= pc; i++) { 164 | if (pc < f->locvars[i].endpc) { /* is variable active? */ 165 | local_number--; 166 | if (local_number == 0) 167 | return getstr(f->locvars[i].varname); 168 | } 169 | } 170 | return NULL; /* not found */ 171 | } 172 | -------------------------------------------------------------------------------- /src/vm/src/lua/lfunc.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lfunc.h,v 2.4.1.1 2007/12/27 13:02:25 roberto Exp $ 3 | ** Auxiliary functions to manipulate prototypes and closures 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef lfunc_h 8 | #define lfunc_h 9 | 10 | #include "lobject.h" 11 | 12 | #define sizeCclosure(n) (cast(int, sizeof(CClosure)) + cast(int, sizeof(TValue) * ((n)-1))) 13 | 14 | #define sizeLclosure(n) (cast(int, sizeof(LClosure)) + cast(int, sizeof(TValue *) * ((n)-1))) 15 | 16 | LUAI_FUNC Proto *luaF_newproto(lua_State *L); 17 | LUAI_FUNC Closure *luaF_newCclosure(lua_State *L, int nelems, Table *e); 18 | LUAI_FUNC Closure *luaF_newLclosure(lua_State *L, int nelems, Table *e); 19 | LUAI_FUNC UpVal *luaF_newupval(lua_State *L); 20 | LUAI_FUNC UpVal *luaF_findupval(lua_State *L, StkId level); 21 | LUAI_FUNC void luaF_close(lua_State *L, StkId level); 22 | LUAI_FUNC void luaF_freeproto(lua_State *L, Proto *f); 23 | LUAI_FUNC void luaF_freeclosure(lua_State *L, Closure *c); 24 | LUAI_FUNC void luaF_freeupval(lua_State *L, UpVal *uv); 25 | LUAI_FUNC const char *luaF_getlocalname(const Proto *func, int local_number, int pc); 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /src/vm/src/lua/lgc.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lgc.h,v 2.15.1.1 2007/12/27 13:02:25 roberto Exp $ 3 | ** Garbage Collector 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef lgc_h 8 | #define lgc_h 9 | 10 | #include "lobject.h" 11 | 12 | /* 13 | ** Possible states of the Garbage Collector 14 | */ 15 | #define GCSpause 0 16 | #define GCSpropagate 1 17 | #define GCSsweepstring 2 18 | #define GCSsweep 3 19 | #define GCSfinalize 4 20 | 21 | /* 22 | ** some userful bit tricks 23 | */ 24 | #define resetbits(x, m) ((x) &= cast(lu_byte, ~(m))) 25 | #define setbits(x, m) ((x) |= (m)) 26 | #define testbits(x, m) ((x) & (m)) 27 | #define bitmask(b) (1 << (b)) 28 | #define bit2mask(b1, b2) (bitmask(b1) | bitmask(b2)) 29 | #define l_setbit(x, b) setbits(x, bitmask(b)) 30 | #define resetbit(x, b) resetbits(x, bitmask(b)) 31 | #define testbit(x, b) testbits(x, bitmask(b)) 32 | #define set2bits(x, b1, b2) setbits(x, (bit2mask(b1, b2))) 33 | #define reset2bits(x, b1, b2) resetbits(x, (bit2mask(b1, b2))) 34 | #define test2bits(x, b1, b2) testbits(x, (bit2mask(b1, b2))) 35 | 36 | /* 37 | ** Layout for bit use in `marked' field: 38 | ** bit 0 - object is white (type 0) 39 | ** bit 1 - object is white (type 1) 40 | ** bit 2 - object is black 41 | ** bit 3 - for userdata: has been finalized 42 | ** bit 3 - for tables: has weak keys 43 | ** bit 4 - for tables: has weak values 44 | ** bit 5 - object is fixed (should not be collected) 45 | ** bit 6 - object is "super" fixed (only the main thread) 46 | */ 47 | 48 | #define WHITE0BIT 0 49 | #define WHITE1BIT 1 50 | #define BLACKBIT 2 51 | #define FINALIZEDBIT 3 52 | #define KEYWEAKBIT 3 53 | #define VALUEWEAKBIT 4 54 | #define FIXEDBIT 5 55 | #define SFIXEDBIT 6 56 | #define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) 57 | 58 | #define iswhite(x) test2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT) 59 | #define isblack(x) testbit((x)->gch.marked, BLACKBIT) 60 | #define isgray(x) (!isblack(x) && !iswhite(x)) 61 | 62 | #define otherwhite(g) (g->currentwhite ^ WHITEBITS) 63 | #define isdead(g, v) ((v)->gch.marked & otherwhite(g) & WHITEBITS) 64 | 65 | #define changewhite(x) ((x)->gch.marked ^= WHITEBITS) 66 | #define gray2black(x) l_setbit((x)->gch.marked, BLACKBIT) 67 | 68 | #define valiswhite(x) (iscollectable(x) && iswhite(gcvalue(x))) 69 | 70 | #define luaC_white(g) cast(lu_byte, (g)->currentwhite &WHITEBITS) 71 | 72 | #define luaC_checkGC(L) \ 73 | { \ 74 | condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); \ 75 | if (G(L)->totalbytes >= G(L)->GCthreshold) \ 76 | luaC_step(L); \ 77 | } 78 | 79 | #define luaC_barrier(L, p, v) \ 80 | { \ 81 | if (valiswhite(v) && isblack(obj2gco(p))) \ 82 | luaC_barrierf(L, obj2gco(p), gcvalue(v)); \ 83 | } 84 | 85 | #define luaC_barriert(L, t, v) \ 86 | { \ 87 | if (valiswhite(v) && isblack(obj2gco(t))) \ 88 | luaC_barrierback(L, t); \ 89 | } 90 | 91 | #define luaC_objbarrier(L, p, o) \ 92 | { \ 93 | if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) \ 94 | luaC_barrierf(L, obj2gco(p), obj2gco(o)); \ 95 | } 96 | 97 | #define luaC_objbarriert(L, t, o) \ 98 | { \ 99 | if (iswhite(obj2gco(o)) && isblack(obj2gco(t))) \ 100 | luaC_barrierback(L, t); \ 101 | } 102 | 103 | LUAI_FUNC size_t luaC_separateudata(lua_State *L, int all); 104 | LUAI_FUNC void luaC_callGCTM(lua_State *L); 105 | LUAI_FUNC void luaC_freeall(lua_State *L); 106 | LUAI_FUNC void luaC_step(lua_State *L); 107 | LUAI_FUNC void luaC_fullgc(lua_State *L); 108 | LUAI_FUNC void luaC_link(lua_State *L, GCObject *o, lu_byte tt); 109 | LUAI_FUNC void luaC_linkupval(lua_State *L, UpVal *uv); 110 | LUAI_FUNC void luaC_barrierf(lua_State *L, GCObject *o, GCObject *v); 111 | LUAI_FUNC void luaC_barrierback(lua_State *L, Table *t); 112 | 113 | #endif 114 | -------------------------------------------------------------------------------- /src/vm/src/lua/linit.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: linit.c,v 1.14.1.1 2007/12/27 13:02:25 roberto Exp $ 3 | ** Initialization of libraries for lua.c 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #define linit_c 8 | #define LUA_LIB 9 | 10 | #include "lua.h" 11 | 12 | #include "lauxlib.h" 13 | #include "lualib.h" 14 | 15 | static const luaL_Reg lualibs[] = {{"", luaopen_base}, 16 | {LUA_TABLIBNAME, luaopen_table}, 17 | {LUA_IOLIBNAME, luaopen_io}, 18 | {LUA_OSLIBNAME, luaopen_os}, 19 | {LUA_STRLIBNAME, luaopen_string}, 20 | {LUA_MATHLIBNAME, luaopen_math}, 21 | {LUA_DBLIBNAME, luaopen_debug}, 22 | {NULL, NULL}}; 23 | 24 | LUALIB_API void luaL_openlibs(lua_State *L) 25 | { 26 | const luaL_Reg *lib = lualibs; 27 | for (; lib->func; lib++) { 28 | lua_pushcfunction(L, lib->func); 29 | lua_pushstring(L, lib->name); 30 | lua_call(L, 1, 0); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/vm/src/lua/llimits.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: llimits.h,v 1.69.1.1 2007/12/27 13:02:25 roberto Exp $ 3 | ** Limits, basic types, and some other `installation-dependent' definitions 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef llimits_h 8 | #define llimits_h 9 | 10 | #include 11 | #include 12 | 13 | #include "lua.h" 14 | 15 | typedef LUAI_UINT32 lu_int32; 16 | 17 | typedef LUAI_UMEM lu_mem; 18 | 19 | typedef LUAI_MEM l_mem; 20 | 21 | /* chars used as small naturals (so that `char' is reserved for characters) */ 22 | typedef unsigned char lu_byte; 23 | 24 | #define MAX_SIZET ((size_t)(~(size_t)0) - 2) 25 | 26 | #define MAX_LUMEM ((lu_mem)(~(lu_mem)0) - 2) 27 | 28 | #define MAX_INT (INT_MAX - 2) /* maximum value of an int (-2 for safety) */ 29 | 30 | /* 31 | ** conversion of pointer to integer 32 | ** this is for hashing only; there is no problem if the integer 33 | ** cannot hold the whole pointer value 34 | */ 35 | #define IntPoint(p) ((unsigned int)(lu_mem)(p)) 36 | 37 | /* type to ensure maximum alignment */ 38 | typedef LUAI_USER_ALIGNMENT_T L_Umaxalign; 39 | 40 | /* result of a `usual argument conversion' over lua_Number */ 41 | typedef LUAI_UACNUMBER l_uacNumber; 42 | 43 | /* internal assertions for in-house debugging */ 44 | #ifdef lua_assert 45 | 46 | #define check_exp(c, e) (lua_assert(c), (e)) 47 | #define api_check(l, e) lua_assert(e) 48 | 49 | #else 50 | 51 | #define lua_assert(c) ((void)0) 52 | #define check_exp(c, e) (e) 53 | #define api_check luai_apicheck 54 | 55 | #endif 56 | 57 | #ifndef UNUSED 58 | #define UNUSED(x) ((void)(x)) /* to avoid warnings */ 59 | #endif 60 | 61 | #ifndef cast 62 | #define cast(t, exp) ((t)(exp)) 63 | #endif 64 | 65 | #define cast_byte(i) cast(lu_byte, (i)) 66 | #define cast_num(i) cast(lua_Number, (i)) 67 | #define cast_int(i) cast(int, (i)) 68 | 69 | /* 70 | ** type for virtual-machine instructions 71 | ** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h) 72 | */ 73 | typedef lu_int32 Instruction; 74 | 75 | /* maximum stack for a Lua function */ 76 | #define MAXSTACK 250 77 | 78 | /* minimum size for the string table (must be power of 2) */ 79 | #ifndef MINSTRTABSIZE 80 | #define MINSTRTABSIZE 32 81 | #endif 82 | 83 | /* minimum size for string buffer */ 84 | #ifndef LUA_MINBUFFER 85 | #define LUA_MINBUFFER 32 86 | #endif 87 | 88 | #ifndef lua_lock 89 | #define lua_lock(L) ((void)0) 90 | #define lua_unlock(L) ((void)0) 91 | #endif 92 | 93 | #ifndef luai_threadyield 94 | #define luai_threadyield(L) \ 95 | { \ 96 | lua_unlock(L); \ 97 | lua_lock(L); \ 98 | } 99 | #endif 100 | 101 | /* 102 | ** macro to control inclusion of some hard tests on stack reallocation 103 | */ 104 | #ifndef HARDSTACKTESTS 105 | #define condhardstacktests(x) ((void)0) 106 | #else 107 | #define condhardstacktests(x) x 108 | #endif 109 | 110 | #endif 111 | -------------------------------------------------------------------------------- /src/vm/src/lua/lmathlib.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lmathlib.c,v 1.67.1.1 2007/12/27 13:02:25 roberto Exp $ 3 | ** Standard mathematical library 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | #define lmathlib_c 11 | #define LUA_LIB 12 | 13 | #include "lua.h" 14 | 15 | #include "lauxlib.h" 16 | #include "lualib.h" 17 | 18 | #undef PI 19 | #define PI (3.14159265358979323846) 20 | #define RADIANS_PER_DEGREE (PI / 180.0) 21 | 22 | static int math_abs(lua_State *L) 23 | { 24 | lua_pushnumber(L, fabs(luaL_checknumber(L, 1))); 25 | return 1; 26 | } 27 | 28 | static int math_sin(lua_State *L) 29 | { 30 | lua_pushnumber(L, sin(luaL_checknumber(L, 1))); 31 | return 1; 32 | } 33 | 34 | static int math_sinh(lua_State *L) 35 | { 36 | lua_pushnumber(L, sinh(luaL_checknumber(L, 1))); 37 | return 1; 38 | } 39 | 40 | static int math_cos(lua_State *L) 41 | { 42 | lua_pushnumber(L, cos(luaL_checknumber(L, 1))); 43 | return 1; 44 | } 45 | 46 | static int math_cosh(lua_State *L) 47 | { 48 | lua_pushnumber(L, cosh(luaL_checknumber(L, 1))); 49 | return 1; 50 | } 51 | 52 | static int math_tan(lua_State *L) 53 | { 54 | lua_pushnumber(L, tan(luaL_checknumber(L, 1))); 55 | return 1; 56 | } 57 | 58 | static int math_tanh(lua_State *L) 59 | { 60 | lua_pushnumber(L, tanh(luaL_checknumber(L, 1))); 61 | return 1; 62 | } 63 | 64 | static int math_asin(lua_State *L) 65 | { 66 | lua_pushnumber(L, asin(luaL_checknumber(L, 1))); 67 | return 1; 68 | } 69 | 70 | static int math_acos(lua_State *L) 71 | { 72 | lua_pushnumber(L, acos(luaL_checknumber(L, 1))); 73 | return 1; 74 | } 75 | 76 | static int math_atan(lua_State *L) 77 | { 78 | lua_pushnumber(L, atan(luaL_checknumber(L, 1))); 79 | return 1; 80 | } 81 | 82 | static int math_atan2(lua_State *L) 83 | { 84 | lua_pushnumber(L, atan2(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); 85 | return 1; 86 | } 87 | 88 | static int math_ceil(lua_State *L) 89 | { 90 | lua_pushnumber(L, ceil(luaL_checknumber(L, 1))); 91 | return 1; 92 | } 93 | 94 | static int math_floor(lua_State *L) 95 | { 96 | lua_pushnumber(L, floor(luaL_checknumber(L, 1))); 97 | return 1; 98 | } 99 | 100 | static int math_fmod(lua_State *L) 101 | { 102 | lua_pushnumber(L, fmod(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); 103 | return 1; 104 | } 105 | 106 | static int math_modf(lua_State *L) 107 | { 108 | double ip; 109 | double fp = modf(luaL_checknumber(L, 1), &ip); 110 | lua_pushnumber(L, ip); 111 | lua_pushnumber(L, fp); 112 | return 2; 113 | } 114 | 115 | static int math_sqrt(lua_State *L) 116 | { 117 | lua_pushnumber(L, sqrt(luaL_checknumber(L, 1))); 118 | return 1; 119 | } 120 | 121 | static int math_pow(lua_State *L) 122 | { 123 | lua_pushnumber(L, pow(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); 124 | return 1; 125 | } 126 | 127 | static int math_log(lua_State *L) 128 | { 129 | lua_pushnumber(L, log(luaL_checknumber(L, 1))); 130 | return 1; 131 | } 132 | 133 | static int math_log10(lua_State *L) 134 | { 135 | lua_pushnumber(L, log10(luaL_checknumber(L, 1))); 136 | return 1; 137 | } 138 | 139 | static int math_exp(lua_State *L) 140 | { 141 | lua_pushnumber(L, exp(luaL_checknumber(L, 1))); 142 | return 1; 143 | } 144 | 145 | static int math_deg(lua_State *L) 146 | { 147 | lua_pushnumber(L, luaL_checknumber(L, 1) / RADIANS_PER_DEGREE); 148 | return 1; 149 | } 150 | 151 | static int math_rad(lua_State *L) 152 | { 153 | lua_pushnumber(L, luaL_checknumber(L, 1) * RADIANS_PER_DEGREE); 154 | return 1; 155 | } 156 | 157 | static int math_frexp(lua_State *L) 158 | { 159 | int e; 160 | lua_pushnumber(L, frexp(luaL_checknumber(L, 1), &e)); 161 | lua_pushinteger(L, e); 162 | return 2; 163 | } 164 | 165 | static int math_ldexp(lua_State *L) 166 | { 167 | lua_pushnumber(L, ldexp(luaL_checknumber(L, 1), luaL_checkint(L, 2))); 168 | return 1; 169 | } 170 | 171 | static int math_min(lua_State *L) 172 | { 173 | int n = lua_gettop(L); /* number of arguments */ 174 | lua_Number dmin = luaL_checknumber(L, 1); 175 | int i; 176 | for (i = 2; i <= n; i++) { 177 | lua_Number d = luaL_checknumber(L, i); 178 | if (d < dmin) 179 | dmin = d; 180 | } 181 | lua_pushnumber(L, dmin); 182 | return 1; 183 | } 184 | 185 | static int math_max(lua_State *L) 186 | { 187 | int n = lua_gettop(L); /* number of arguments */ 188 | lua_Number dmax = luaL_checknumber(L, 1); 189 | int i; 190 | for (i = 2; i <= n; i++) { 191 | lua_Number d = luaL_checknumber(L, i); 192 | if (d > dmax) 193 | dmax = d; 194 | } 195 | lua_pushnumber(L, dmax); 196 | return 1; 197 | } 198 | 199 | static int math_random(lua_State *L) 200 | { 201 | /* the `%' avoids the (rare) case of r==1, and is needed also because on 202 | some systems (SunOS!) `rand()' may return a value larger than RAND_MAX */ 203 | lua_Number r = (lua_Number)(rand() % RAND_MAX) / (lua_Number)RAND_MAX; 204 | switch (lua_gettop(L)) { /* check number of arguments */ 205 | case 0: { /* no arguments */ 206 | lua_pushnumber(L, r); /* Number between 0 and 1 */ 207 | break; 208 | } 209 | case 1: { /* only upper limit */ 210 | int u = luaL_checkint(L, 1); 211 | luaL_argcheck(L, 1 <= u, 1, "interval is empty"); 212 | lua_pushnumber(L, floor(r * u) + 1); /* int between 1 and `u' */ 213 | break; 214 | } 215 | case 2: { /* lower and upper limits */ 216 | int l = luaL_checkint(L, 1); 217 | int u = luaL_checkint(L, 2); 218 | luaL_argcheck(L, l <= u, 2, "interval is empty"); 219 | lua_pushnumber(L, floor(r * (u - l + 1)) + l); /* int between `l' and `u' */ 220 | break; 221 | } 222 | default: 223 | return luaL_error(L, "wrong number of arguments"); 224 | } 225 | return 1; 226 | } 227 | 228 | static int math_randomseed(lua_State *L) 229 | { 230 | srand(luaL_checkint(L, 1)); 231 | return 0; 232 | } 233 | 234 | static const luaL_Reg mathlib[] = {{"abs", math_abs}, 235 | {"acos", math_acos}, 236 | {"asin", math_asin}, 237 | {"atan2", math_atan2}, 238 | {"atan", math_atan}, 239 | {"ceil", math_ceil}, 240 | {"cosh", math_cosh}, 241 | {"cos", math_cos}, 242 | {"deg", math_deg}, 243 | {"exp", math_exp}, 244 | {"floor", math_floor}, 245 | {"fmod", math_fmod}, 246 | {"frexp", math_frexp}, 247 | {"ldexp", math_ldexp}, 248 | {"log10", math_log10}, 249 | {"log", math_log}, 250 | {"max", math_max}, 251 | {"min", math_min}, 252 | {"modf", math_modf}, 253 | {"pow", math_pow}, 254 | {"rad", math_rad}, 255 | {"random", math_random}, 256 | {"randomseed", math_randomseed}, 257 | {"sinh", math_sinh}, 258 | {"sin", math_sin}, 259 | {"sqrt", math_sqrt}, 260 | {"tanh", math_tanh}, 261 | {"tan", math_tan}, 262 | {NULL, NULL}}; 263 | 264 | /* 265 | ** Open math library 266 | */ 267 | LUALIB_API int luaopen_math(lua_State *L) 268 | { 269 | luaL_register(L, LUA_MATHLIBNAME, mathlib); 270 | lua_pushnumber(L, PI); 271 | lua_setfield(L, -2, "pi"); 272 | lua_pushnumber(L, HUGE_VAL); 273 | lua_setfield(L, -2, "huge"); 274 | #if defined(LUA_COMPAT_MOD) 275 | lua_getfield(L, -1, "fmod"); 276 | lua_setfield(L, -2, "mod"); 277 | #endif 278 | return 1; 279 | } 280 | -------------------------------------------------------------------------------- /src/vm/src/lua/lmem.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lmem.c,v 1.70.1.1 2007/12/27 13:02:25 roberto Exp $ 3 | ** Interface to Memory Manager 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #include 8 | 9 | #define lmem_c 10 | #define LUA_CORE 11 | 12 | #include "lua.h" 13 | 14 | #include "ldebug.h" 15 | #include "ldo.h" 16 | #include "lmem.h" 17 | #include "lobject.h" 18 | #include "lstate.h" 19 | 20 | /* 21 | ** About the realloc function: 22 | ** void * frealloc (void *ud, void *ptr, size_t osize, size_t nsize); 23 | ** (`osize' is the old size, `nsize' is the new size) 24 | ** 25 | ** Lua ensures that (ptr == NULL) iff (osize == 0). 26 | ** 27 | ** * frealloc(ud, NULL, 0, x) creates a new block of size `x' 28 | ** 29 | ** * frealloc(ud, p, x, 0) frees the block `p' 30 | ** (in this specific case, frealloc must return NULL). 31 | ** particularly, frealloc(ud, NULL, 0, 0) does nothing 32 | ** (which is equivalent to free(NULL) in ANSI C) 33 | ** 34 | ** frealloc returns NULL if it cannot create or reallocate the area 35 | ** (any reallocation to an equal or smaller size cannot fail!) 36 | */ 37 | 38 | #define MINSIZEARRAY 4 39 | 40 | void *luaM_growaux_(lua_State *L, void *block, int *size, size_t size_elems, int limit, 41 | const char *errormsg) 42 | { 43 | void *newblock; 44 | int newsize; 45 | if (*size >= limit / 2) { /* cannot double it? */ 46 | if (*size >= limit) /* cannot grow even a little? */ 47 | luaG_runerror(L, errormsg); 48 | newsize = limit; /* still have at least one free place */ 49 | } else { 50 | newsize = (*size) * 2; 51 | if (newsize < MINSIZEARRAY) 52 | newsize = MINSIZEARRAY; /* minimum size */ 53 | } 54 | newblock = luaM_reallocv(L, block, *size, newsize, size_elems); 55 | *size = newsize; /* update only when everything else is OK */ 56 | return newblock; 57 | } 58 | 59 | void *luaM_toobig(lua_State *L) 60 | { 61 | luaG_runerror(L, "memory allocation error: block too big"); 62 | return NULL; /* to avoid warnings */ 63 | } 64 | 65 | /* 66 | ** generic allocation routine. 67 | */ 68 | void *luaM_realloc_(lua_State *L, void *block, size_t osize, size_t nsize) 69 | { 70 | global_State *g = G(L); 71 | lua_assert((osize == 0) == (block == NULL)); 72 | block = (*g->frealloc)(g->ud, block, osize, nsize); 73 | if (block == NULL && nsize > 0) 74 | luaD_throw(L, LUA_ERRMEM); 75 | lua_assert((nsize == 0) == (block == NULL)); 76 | g->totalbytes = (g->totalbytes - osize) + nsize; 77 | return block; 78 | } 79 | -------------------------------------------------------------------------------- /src/vm/src/lua/lmem.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lmem.h,v 1.31.1.1 2007/12/27 13:02:25 roberto Exp $ 3 | ** Interface to Memory Manager 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef lmem_h 8 | #define lmem_h 9 | 10 | #include 11 | 12 | #include "llimits.h" 13 | #include "lua.h" 14 | 15 | #define MEMERRMSG "not enough memory" 16 | 17 | #define luaM_reallocv(L, b, on, n, e) \ 18 | ((cast(size_t, (n) + 1) <= MAX_SIZET / (e)) ? /* +1 to avoid warnings */ \ 19 | luaM_realloc_(L, (b), (on) * (e), (n) * (e)) \ 20 | : luaM_toobig(L)) 21 | 22 | #define luaM_freemem(L, b, s) luaM_realloc_(L, (b), (s), 0) 23 | #define luaM_free(L, b) luaM_realloc_(L, (b), sizeof(*(b)), 0) 24 | #define luaM_freearray(L, b, n, t) luaM_reallocv(L, (b), n, 0, sizeof(t)) 25 | 26 | #define luaM_malloc(L, t) luaM_realloc_(L, NULL, 0, (t)) 27 | #define luaM_new(L, t) cast(t *, luaM_malloc(L, sizeof(t))) 28 | #define luaM_newvector(L, n, t) cast(t *, luaM_reallocv(L, NULL, 0, n, sizeof(t))) 29 | 30 | #define luaM_growvector(L, v, nelems, size, t, limit, e) \ 31 | if ((nelems) + 1 > (size)) \ 32 | ((v) = cast(t *, luaM_growaux_(L, v, &(size), sizeof(t), limit, e))) 33 | 34 | #define luaM_reallocvector(L, v, oldn, n, t) \ 35 | ((v) = cast(t *, luaM_reallocv(L, v, oldn, n, sizeof(t)))) 36 | 37 | LUAI_FUNC void *luaM_realloc_(lua_State *L, void *block, size_t oldsize, size_t size); 38 | LUAI_FUNC void *luaM_toobig(lua_State *L); 39 | LUAI_FUNC void *luaM_growaux_(lua_State *L, void *block, int *size, size_t size_elem, int limit, 40 | const char *errormsg); 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /src/vm/src/lua/lobject.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lobject.c,v 2.22.1.1 2007/12/27 13:02:25 roberto Exp $ 3 | ** Some generic functions over Lua objects 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #define lobject_c 14 | #define LUA_CORE 15 | 16 | #include "lua.h" 17 | 18 | #include "ldo.h" 19 | #include "lmem.h" 20 | #include "lobject.h" 21 | #include "lstate.h" 22 | #include "lstring.h" 23 | #include "lvm.h" 24 | 25 | const TValue luaO_nilobject_ = {{NULL}, LUA_TNIL}; 26 | 27 | /* 28 | ** converts an integer to a "floating point byte", represented as 29 | ** (eeeeexxx), where the real value is (1xxx) * 2^(eeeee - 1) if 30 | ** eeeee != 0 and (xxx) otherwise. 31 | */ 32 | int luaO_int2fb(unsigned int x) 33 | { 34 | int e = 0; /* expoent */ 35 | while (x >= 16) { 36 | x = (x + 1) >> 1; 37 | e++; 38 | } 39 | if (x < 8) 40 | return x; 41 | else 42 | return ((e + 1) << 3) | (cast_int(x) - 8); 43 | } 44 | 45 | /* converts back */ 46 | int luaO_fb2int(int x) 47 | { 48 | int e = (x >> 3) & 31; 49 | if (e == 0) 50 | return x; 51 | else 52 | return ((x & 7) + 8) << (e - 1); 53 | } 54 | 55 | int luaO_log2(unsigned int x) 56 | { 57 | static const lu_byte log_2[256] = { 58 | 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 59 | 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 60 | 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 61 | 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 62 | 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 63 | 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 64 | 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 65 | 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 66 | 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}; 67 | int l = -1; 68 | while (x >= 256) { 69 | l += 8; 70 | x >>= 8; 71 | } 72 | return l + log_2[x]; 73 | } 74 | 75 | int luaO_rawequalObj(const TValue *t1, const TValue *t2) 76 | { 77 | if (ttype(t1) != ttype(t2)) 78 | return 0; 79 | else 80 | switch (ttype(t1)) { 81 | case LUA_TNIL: 82 | return 1; 83 | case LUA_TNUMBER: 84 | return luai_numeq(nvalue(t1), nvalue(t2)); 85 | case LUA_TBOOLEAN: 86 | return bvalue(t1) == bvalue(t2); /* boolean true must be 1 !! */ 87 | case LUA_TLIGHTUSERDATA: 88 | return pvalue(t1) == pvalue(t2); 89 | default: 90 | lua_assert(iscollectable(t1)); 91 | return gcvalue(t1) == gcvalue(t2); 92 | } 93 | } 94 | 95 | int luaO_str2d(const char *s, lua_Number *result) 96 | { 97 | char *endptr; 98 | *result = lua_str2number(s, &endptr); 99 | if (endptr == s) 100 | return 0; /* conversion failed */ 101 | if (*endptr == 'x' || *endptr == 'X') /* maybe an hexadecimal constant? */ 102 | *result = cast_num(strtoul(s, &endptr, 16)); 103 | if (*endptr == '\0') 104 | return 1; /* most common case */ 105 | while (isspace(cast(unsigned char, *endptr))) 106 | endptr++; 107 | if (*endptr != '\0') 108 | return 0; /* invalid trailing characters? */ 109 | return 1; 110 | } 111 | 112 | static void pushstr(lua_State *L, const char *str) 113 | { 114 | setsvalue2s(L, L->top, luaS_new(L, str)); 115 | incr_top(L); 116 | } 117 | 118 | /* this function handles only `%d', `%c', %f, %p, and `%s' formats */ 119 | const char *luaO_pushvfstring(lua_State *L, const char *fmt, va_list argp) 120 | { 121 | int n = 1; 122 | pushstr(L, ""); 123 | for (;;) { 124 | const char *e = strchr(fmt, '%'); 125 | if (e == NULL) 126 | break; 127 | setsvalue2s(L, L->top, luaS_newlstr(L, fmt, e - fmt)); 128 | incr_top(L); 129 | switch (*(e + 1)) { 130 | case 's': { 131 | const char *s = va_arg(argp, char *); 132 | if (s == NULL) 133 | s = "(null)"; 134 | pushstr(L, s); 135 | break; 136 | } 137 | case 'c': { 138 | char buff[2]; 139 | buff[0] = cast(char, va_arg(argp, int)); 140 | buff[1] = '\0'; 141 | pushstr(L, buff); 142 | break; 143 | } 144 | case 'd': { 145 | setnvalue(L->top, cast_num(va_arg(argp, int))); 146 | incr_top(L); 147 | break; 148 | } 149 | case 'f': { 150 | setnvalue(L->top, cast_num(va_arg(argp, l_uacNumber))); 151 | incr_top(L); 152 | break; 153 | } 154 | case 'p': { 155 | char buff[4 * sizeof(void *) + 8]; /* should be enough space for a `%p' */ 156 | sprintf(buff, "%p", va_arg(argp, void *)); 157 | pushstr(L, buff); 158 | break; 159 | } 160 | case '%': { 161 | pushstr(L, "%"); 162 | break; 163 | } 164 | default: { 165 | char buff[3]; 166 | buff[0] = '%'; 167 | buff[1] = *(e + 1); 168 | buff[2] = '\0'; 169 | pushstr(L, buff); 170 | break; 171 | } 172 | } 173 | n += 2; 174 | fmt = e + 2; 175 | } 176 | pushstr(L, fmt); 177 | luaV_concat(L, n + 1, cast_int(L->top - L->base) - 1); 178 | L->top -= n; 179 | return svalue(L->top - 1); 180 | } 181 | 182 | const char *luaO_pushfstring(lua_State *L, const char *fmt, ...) 183 | { 184 | const char *msg; 185 | va_list argp; 186 | va_start(argp, fmt); 187 | msg = luaO_pushvfstring(L, fmt, argp); 188 | va_end(argp); 189 | return msg; 190 | } 191 | 192 | void luaO_chunkid(char *out, const char *source, size_t bufflen) 193 | { 194 | if (*source == '=') { 195 | strncpy(out, source + 1, bufflen); /* remove first char */ 196 | out[bufflen - 1] = '\0'; /* ensures null termination */ 197 | } else { /* out = "source", or "...source" */ 198 | if (*source == '@') { 199 | size_t l; 200 | source++; /* skip the `@' */ 201 | bufflen -= sizeof(" '...' "); 202 | l = strlen(source); 203 | strcpy(out, ""); 204 | if (l > bufflen) { 205 | source += (l - bufflen); /* get last part of file name */ 206 | strcat(out, "..."); 207 | } 208 | strcat(out, source); 209 | } else { /* out = [string "string"] */ 210 | size_t len = strcspn(source, "\n\r"); /* stop at first newline */ 211 | bufflen -= sizeof(" [string \"...\"] "); 212 | if (len > bufflen) 213 | len = bufflen; 214 | strcpy(out, "[string \""); 215 | if (source[len] != '\0') { /* must truncate? */ 216 | strncat(out, source, len); 217 | strcat(out, "..."); 218 | } else 219 | strcat(out, source); 220 | strcat(out, "\"]"); 221 | } 222 | } 223 | } 224 | -------------------------------------------------------------------------------- /src/vm/src/lua/lopcodes.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lopcodes.c,v 1.37.1.1 2007/12/27 13:02:25 roberto Exp $ 3 | ** See Copyright Notice in lua.h 4 | */ 5 | 6 | #define lopcodes_c 7 | #define LUA_CORE 8 | 9 | #include "lopcodes.h" 10 | 11 | /* ORDER OP */ 12 | 13 | const char *const luaP_opnames[NUM_OPCODES + 1] = { 14 | "MOVE", "LOADK", "LOADBOOL", "LOADNIL", "GETUPVAL", "GETGLOBAL", "GETTABLE", "SETGLOBAL", 15 | "SETUPVAL", "SETTABLE", "NEWTABLE", "SELF", "ADD", "SUB", "MUL", "DIV", 16 | "MOD", "POW", "UNM", "NOT", "LEN", "CONCAT", "JMP", "EQ", 17 | "LT", "LE", "TEST", "TESTSET", "CALL", "TAILCALL", "RETURN", "FORLOOP", 18 | "FORPREP", "TFORLOOP", "SETLIST", "CLOSE", "CLOSURE", "VARARG", NULL}; 19 | 20 | #define opmode(t, a, b, c, m) (((t) << 7) | ((a) << 6) | ((b) << 4) | ((c) << 2) | (m)) 21 | 22 | const lu_byte luaP_opmodes[NUM_OPCODES] = { 23 | /* T A B C mode opcode */ 24 | opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_MOVE */ 25 | , 26 | opmode(0, 1, OpArgK, OpArgN, iAD) /* OP_LOADK */ 27 | , 28 | opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_LOADBOOL */ 29 | , 30 | opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LOADNIL */ 31 | , 32 | opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_GETUPVAL */ 33 | , 34 | opmode(0, 1, OpArgK, OpArgN, iAD) /* OP_GETGLOBAL */ 35 | , 36 | opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_GETTABLE */ 37 | , 38 | opmode(0, 0, OpArgK, OpArgN, iAD) /* OP_SETGLOBAL */ 39 | , 40 | opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_SETUPVAL */ 41 | , 42 | opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABLE */ 43 | , 44 | opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_NEWTABLE */ 45 | , 46 | opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_SELF */ 47 | , 48 | opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_ADD */ 49 | , 50 | opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_SUB */ 51 | , 52 | opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MUL */ 53 | , 54 | opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_DIV */ 55 | , 56 | opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MOD */ 57 | , 58 | opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_POW */ 59 | , 60 | opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_UNM */ 61 | , 62 | opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_NOT */ 63 | , 64 | opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LEN */ 65 | , 66 | opmode(0, 1, OpArgR, OpArgR, iABC) /* OP_CONCAT */ 67 | , 68 | opmode(0, 0, OpArgR, OpArgN, iE) /* OP_JMP */ 69 | , 70 | opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_EQ */ 71 | , 72 | opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LT */ 73 | , 74 | opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LE */ 75 | , 76 | opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TEST */ 77 | , 78 | opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TESTSET */ 79 | , 80 | opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_CALL */ 81 | , 82 | opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_TAILCALL */ 83 | , 84 | opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_RETURN */ 85 | , 86 | opmode(0, 1, OpArgR, OpArgN, iAD) /* OP_FORLOOP */ 87 | , 88 | opmode(0, 1, OpArgR, OpArgN, iAD) /* OP_FORPREP */ 89 | , 90 | opmode(1, 0, OpArgN, OpArgU, iABC) /* OP_TFORLOOP */ 91 | , 92 | opmode(0, 0, OpArgU, OpArgU, iABC) /* OP_SETLIST */ 93 | , 94 | opmode(0, 0, OpArgN, OpArgN, iABC) /* OP_CLOSE */ 95 | , 96 | opmode(0, 1, OpArgU, OpArgN, iAD) /* OP_CLOSURE */ 97 | , 98 | opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_VARARG */ 99 | }; -------------------------------------------------------------------------------- /src/vm/src/lua/loslib.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: loslib.c,v 1.19.1.3 2008/01/18 16:38:18 roberto Exp $ 3 | ** Standard Operating System library 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #define loslib_c 14 | #define LUA_LIB 15 | 16 | #include "lua.h" 17 | 18 | #include "lauxlib.h" 19 | #include "lualib.h" 20 | 21 | static int os_pushresult(lua_State *L, int i, const char *filename) 22 | { 23 | int en = errno; /* calls to Lua API may change this value */ 24 | if (i) { 25 | lua_pushboolean(L, 1); 26 | return 1; 27 | } else { 28 | lua_pushnil(L); 29 | lua_pushfstring(L, "%s: %s", filename, strerror(en)); 30 | lua_pushinteger(L, en); 31 | return 3; 32 | } 33 | } 34 | 35 | static int os_execute(lua_State *L) 36 | { 37 | lua_pushinteger(L, system(luaL_optstring(L, 1, NULL))); 38 | return 1; 39 | } 40 | 41 | static int os_remove(lua_State *L) 42 | { 43 | const char *filename = luaL_checkstring(L, 1); 44 | return os_pushresult(L, remove(filename) == 0, filename); 45 | } 46 | 47 | static int os_rename(lua_State *L) 48 | { 49 | const char *fromname = luaL_checkstring(L, 1); 50 | const char *toname = luaL_checkstring(L, 2); 51 | return os_pushresult(L, rename(fromname, toname) == 0, fromname); 52 | } 53 | 54 | static int os_tmpname(lua_State *L) 55 | { 56 | char buff[LUA_TMPNAMBUFSIZE]; 57 | int err; 58 | lua_tmpnam(buff, err); 59 | if (err) 60 | return luaL_error(L, "unable to generate a unique filename"); 61 | lua_pushstring(L, buff); 62 | return 1; 63 | } 64 | 65 | static int os_getenv(lua_State *L) 66 | { 67 | lua_pushstring(L, getenv(luaL_checkstring(L, 1))); /* if NULL push nil */ 68 | return 1; 69 | } 70 | 71 | static int os_clock(lua_State *L) 72 | { 73 | lua_pushnumber(L, ((lua_Number)clock()) / (lua_Number)CLOCKS_PER_SEC); 74 | return 1; 75 | } 76 | 77 | /* 78 | ** {====================================================== 79 | ** Time/Date operations 80 | ** { year=%Y, month=%m, day=%d, hour=%H, min=%M, sec=%S, 81 | ** wday=%w+1, yday=%j, isdst=? } 82 | ** ======================================================= 83 | */ 84 | 85 | static void setfield(lua_State *L, const char *key, int value) 86 | { 87 | lua_pushinteger(L, value); 88 | lua_setfield(L, -2, key); 89 | } 90 | 91 | static void setboolfield(lua_State *L, const char *key, int value) 92 | { 93 | if (value < 0) /* undefined? */ 94 | return; /* does not set field */ 95 | lua_pushboolean(L, value); 96 | lua_setfield(L, -2, key); 97 | } 98 | 99 | static int getboolfield(lua_State *L, const char *key) 100 | { 101 | int res; 102 | lua_getfield(L, -1, key); 103 | res = lua_isnil(L, -1) ? -1 : lua_toboolean(L, -1); 104 | lua_pop(L, 1); 105 | return res; 106 | } 107 | 108 | static int getfield(lua_State *L, const char *key, int d) 109 | { 110 | int res; 111 | lua_getfield(L, -1, key); 112 | if (lua_isnumber(L, -1)) 113 | res = (int)lua_tointeger(L, -1); 114 | else { 115 | if (d < 0) 116 | return luaL_error(L, "field " LUA_QS " missing in date table", key); 117 | res = d; 118 | } 119 | lua_pop(L, 1); 120 | return res; 121 | } 122 | 123 | static int os_date(lua_State *L) 124 | { 125 | const char *s = luaL_optstring(L, 1, "%c"); 126 | time_t t = luaL_opt(L, (time_t)luaL_checknumber, 2, time(NULL)); 127 | struct tm *stm; 128 | if (*s == '!') { /* UTC? */ 129 | stm = gmtime(&t); 130 | s++; /* skip `!' */ 131 | } else 132 | stm = localtime(&t); 133 | if (stm == NULL) /* invalid date? */ 134 | lua_pushnil(L); 135 | else if (strcmp(s, "*t") == 0) { 136 | lua_createtable(L, 0, 9); /* 9 = number of fields */ 137 | setfield(L, "sec", stm->tm_sec); 138 | setfield(L, "min", stm->tm_min); 139 | setfield(L, "hour", stm->tm_hour); 140 | setfield(L, "day", stm->tm_mday); 141 | setfield(L, "month", stm->tm_mon + 1); 142 | setfield(L, "year", stm->tm_year + 1900); 143 | setfield(L, "wday", stm->tm_wday + 1); 144 | setfield(L, "yday", stm->tm_yday + 1); 145 | setboolfield(L, "isdst", stm->tm_isdst); 146 | } else { 147 | char cc[3]; 148 | luaL_Buffer b; 149 | cc[0] = '%'; 150 | cc[2] = '\0'; 151 | luaL_buffinit(L, &b); 152 | for (; *s; s++) { 153 | if (*s != '%' || *(s + 1) == '\0') /* no conversion specifier? */ 154 | luaL_addchar(&b, *s); 155 | else { 156 | size_t reslen; 157 | char buff[200]; /* should be big enough for any conversion result */ 158 | cc[1] = *(++s); 159 | reslen = strftime(buff, sizeof(buff), cc, stm); 160 | luaL_addlstring(&b, buff, reslen); 161 | } 162 | } 163 | luaL_pushresult(&b); 164 | } 165 | return 1; 166 | } 167 | 168 | static int os_time(lua_State *L) 169 | { 170 | time_t t; 171 | if (lua_isnoneornil(L, 1)) /* called without args? */ 172 | t = time(NULL); /* get current time */ 173 | else { 174 | struct tm ts; 175 | luaL_checktype(L, 1, LUA_TTABLE); 176 | lua_settop(L, 1); /* make sure table is at the top */ 177 | ts.tm_sec = getfield(L, "sec", 0); 178 | ts.tm_min = getfield(L, "min", 0); 179 | ts.tm_hour = getfield(L, "hour", 12); 180 | ts.tm_mday = getfield(L, "day", -1); 181 | ts.tm_mon = getfield(L, "month", -1) - 1; 182 | ts.tm_year = getfield(L, "year", -1) - 1900; 183 | ts.tm_isdst = getboolfield(L, "isdst"); 184 | t = mktime(&ts); 185 | } 186 | if (t == (time_t)(-1)) 187 | lua_pushnil(L); 188 | else 189 | lua_pushnumber(L, (lua_Number)t); 190 | return 1; 191 | } 192 | 193 | static int os_difftime(lua_State *L) 194 | { 195 | lua_pushnumber(L, 196 | difftime((time_t)(luaL_checknumber(L, 1)), (time_t)(luaL_optnumber(L, 2, 0)))); 197 | return 1; 198 | } 199 | 200 | /* }====================================================== */ 201 | 202 | static int os_setlocale(lua_State *L) 203 | { 204 | static const int cat[] = {LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, LC_NUMERIC, LC_TIME}; 205 | static const char *const catnames[] = {"all", "collate", "ctype", "monetary", 206 | "numeric", "time", NULL}; 207 | const char *l = luaL_optstring(L, 1, NULL); 208 | int op = luaL_checkoption(L, 2, "all", catnames); 209 | lua_pushstring(L, setlocale(cat[op], l)); 210 | return 1; 211 | } 212 | 213 | static int os_exit(lua_State *L) { exit(luaL_optint(L, 1, EXIT_SUCCESS)); } 214 | 215 | static const luaL_Reg syslib[] = { 216 | {"clock", os_clock}, {"date", os_date}, {"difftime", os_difftime}, 217 | {"execute", os_execute}, {"exit", os_exit}, {"getenv", os_getenv}, 218 | {"remove", os_remove}, {"rename", os_rename}, {"setlocale", os_setlocale}, 219 | {"time", os_time}, {"tmpname", os_tmpname}, {NULL, NULL}}; 220 | 221 | /* }====================================================== */ 222 | 223 | LUALIB_API int luaopen_os(lua_State *L) 224 | { 225 | luaL_register(L, LUA_OSLIBNAME, syslib); 226 | return 1; 227 | } 228 | -------------------------------------------------------------------------------- /src/vm/src/lua/lstate.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lstate.c,v 2.36.1.2 2008/01/03 15:20:39 roberto Exp $ 3 | ** Global State 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #include 8 | 9 | #define lstate_c 10 | #define LUA_CORE 11 | 12 | #include "lua.h" 13 | 14 | #include "ldebug.h" 15 | #include "ldo.h" 16 | #include "lfunc.h" 17 | #include "lgc.h" 18 | #include "lmem.h" 19 | #include "lstate.h" 20 | #include "lstring.h" 21 | #include "ltable.h" 22 | #include "ltm.h" 23 | 24 | #define state_size(x) (sizeof(x) + LUAI_EXTRASPACE) 25 | #define fromstate(l) (cast(lu_byte *, (l)) - LUAI_EXTRASPACE) 26 | #define tostate(l) (cast(lua_State *, cast(lu_byte *, l) + LUAI_EXTRASPACE)) 27 | 28 | /* 29 | ** Main thread combines a thread state and the global state 30 | */ 31 | typedef struct LG { 32 | lua_State l; 33 | global_State g; 34 | } LG; 35 | 36 | static void stack_init(lua_State *L1, lua_State *L) 37 | { 38 | /* initialize CallInfo array */ 39 | L1->base_ci = luaM_newvector(L, BASIC_CI_SIZE, CallInfo); 40 | L1->ci = L1->base_ci; 41 | L1->size_ci = BASIC_CI_SIZE; 42 | L1->end_ci = L1->base_ci + L1->size_ci - 1; 43 | /* initialize stack array */ 44 | L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, TValue); 45 | L1->stacksize = BASIC_STACK_SIZE + EXTRA_STACK; 46 | L1->top = L1->stack; 47 | L1->stack_last = L1->stack + (L1->stacksize - EXTRA_STACK) - 1; 48 | /* initialize first ci */ 49 | L1->ci->func = L1->top; 50 | setnilvalue(L1->top++); /* `function' entry for this `ci' */ 51 | L1->base = L1->ci->base = L1->top; 52 | L1->ci->top = L1->top + LUA_MINSTACK; 53 | } 54 | 55 | static void freestack(lua_State *L, lua_State *L1) 56 | { 57 | luaM_freearray(L, L1->base_ci, L1->size_ci, CallInfo); 58 | luaM_freearray(L, L1->stack, L1->stacksize, TValue); 59 | } 60 | 61 | /* 62 | ** open parts that may cause memory-allocation errors 63 | */ 64 | static void f_luaopen(lua_State *L, void *ud) 65 | { 66 | global_State *g = G(L); 67 | UNUSED(ud); 68 | stack_init(L, L); /* init stack */ 69 | sethvalue(L, gt(L), luaH_new(L, 0, 2)); /* table of globals */ 70 | sethvalue(L, registry(L), luaH_new(L, 0, 2)); /* registry */ 71 | luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */ 72 | luaT_init(L); 73 | luaS_fix(luaS_newliteral(L, MEMERRMSG)); 74 | g->GCthreshold = 4 * g->totalbytes; 75 | } 76 | 77 | static void preinit_state(lua_State *L, global_State *g) 78 | { 79 | G(L) = g; 80 | L->stack = NULL; 81 | L->stacksize = 0; 82 | L->errorJmp = NULL; 83 | L->hook = NULL; 84 | L->hookmask = 0; 85 | L->basehookcount = 0; 86 | L->allowhook = 1; 87 | resethookcount(L); 88 | L->openupval = NULL; 89 | L->size_ci = 0; 90 | L->nCcalls = L->baseCcalls = 0; 91 | L->status = 0; 92 | L->base_ci = L->ci = NULL; 93 | L->savedpc = NULL; 94 | L->errfunc = 0; 95 | setnilvalue(gt(L)); 96 | } 97 | 98 | static void close_state(lua_State *L) 99 | { 100 | global_State *g = G(L); 101 | luaF_close(L, L->stack); /* close all upvalues for this thread */ 102 | luaC_freeall(L); /* collect all objects */ 103 | lua_assert(g->rootgc == obj2gco(L)); 104 | lua_assert(g->strt.nuse == 0); 105 | luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size, TString *); 106 | luaZ_freebuffer(L, &g->buff); 107 | freestack(L, L); 108 | lua_assert(g->totalbytes == sizeof(LG)); 109 | (*g->frealloc)(g->ud, fromstate(L), state_size(LG), 0); 110 | } 111 | 112 | lua_State *luaE_newthread(lua_State *L) 113 | { 114 | lua_State *L1 = tostate(luaM_malloc(L, state_size(lua_State))); 115 | luaC_link(L, obj2gco(L1), LUA_TTHREAD); 116 | preinit_state(L1, G(L)); 117 | stack_init(L1, L); /* init stack */ 118 | setobj2n(L, gt(L1), gt(L)); /* share table of globals */ 119 | L1->hookmask = L->hookmask; 120 | L1->basehookcount = L->basehookcount; 121 | L1->hook = L->hook; 122 | resethookcount(L1); 123 | lua_assert(iswhite(obj2gco(L1))); 124 | return L1; 125 | } 126 | 127 | void luaE_freethread(lua_State *L, lua_State *L1) 128 | { 129 | luaF_close(L1, L1->stack); /* close all upvalues for this thread */ 130 | lua_assert(L1->openupval == NULL); 131 | luai_userstatefree(L1); 132 | freestack(L, L1); 133 | luaM_freemem(L, fromstate(L1), state_size(lua_State)); 134 | } 135 | 136 | LUA_API lua_State *lua_newstate(lua_Alloc f, void *ud) 137 | { 138 | int i; 139 | lua_State *L; 140 | global_State *g; 141 | void *l = (*f)(ud, NULL, 0, state_size(LG)); 142 | if (l == NULL) 143 | return NULL; 144 | L = tostate(l); 145 | g = &((LG *)L)->g; 146 | L->next = NULL; 147 | L->tt = LUA_TTHREAD; 148 | g->currentwhite = bit2mask(WHITE0BIT, FIXEDBIT); 149 | L->marked = luaC_white(g); 150 | set2bits(L->marked, FIXEDBIT, SFIXEDBIT); 151 | preinit_state(L, g); 152 | g->frealloc = f; 153 | g->ud = ud; 154 | g->mainthread = L; 155 | g->uvhead.u.l.prev = &g->uvhead; 156 | g->uvhead.u.l.next = &g->uvhead; 157 | g->GCthreshold = 0; /* mark it as unfinished state */ 158 | g->strt.size = 0; 159 | g->strt.nuse = 0; 160 | g->strt.hash = NULL; 161 | setnilvalue(registry(L)); 162 | luaZ_initbuffer(L, &g->buff); 163 | g->panic = NULL; 164 | g->gcstate = GCSpause; 165 | g->rootgc = obj2gco(L); 166 | g->sweepstrgc = 0; 167 | g->sweepgc = &g->rootgc; 168 | g->gray = NULL; 169 | g->grayagain = NULL; 170 | g->weak = NULL; 171 | g->tmudata = NULL; 172 | g->totalbytes = sizeof(LG); 173 | g->gcpause = LUAI_GCPAUSE; 174 | g->gcstepmul = LUAI_GCMUL; 175 | g->gcdept = 0; 176 | for (i = 0; i < NUM_TAGS; i++) 177 | g->mt[i] = NULL; 178 | if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) { 179 | /* memory allocation error: free partial state */ 180 | close_state(L); 181 | L = NULL; 182 | } else 183 | luai_userstateopen(L); 184 | return L; 185 | } 186 | 187 | static void callallgcTM(lua_State *L, void *ud) 188 | { 189 | UNUSED(ud); 190 | luaC_callGCTM(L); /* call GC metamethods for all udata */ 191 | } 192 | 193 | LUA_API void lua_close(lua_State *L) 194 | { 195 | L = G(L)->mainthread; /* only the main thread can be closed */ 196 | lua_lock(L); 197 | luaF_close(L, L->stack); /* close all upvalues for this thread */ 198 | luaC_separateudata(L, 1); /* separate udata that have GC metamethods */ 199 | L->errfunc = 0; /* no error function during GC metamethods */ 200 | do { /* repeat until no more errors */ 201 | L->ci = L->base_ci; 202 | L->base = L->top = L->ci->base; 203 | L->nCcalls = L->baseCcalls = 0; 204 | } while (luaD_rawrunprotected(L, callallgcTM, NULL) != 0); 205 | lua_assert(G(L)->tmudata == NULL); 206 | luai_userstateclose(L); 207 | close_state(L); 208 | } 209 | -------------------------------------------------------------------------------- /src/vm/src/lua/lstate.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lstate.h,v 2.24.1.2 2008/01/03 15:20:39 roberto Exp $ 3 | ** Global State 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef lstate_h 8 | #define lstate_h 9 | 10 | #include "lua.h" 11 | 12 | #include "lobject.h" 13 | #include "ltm.h" 14 | #include "lzio.h" 15 | 16 | struct lua_longjmp; /* defined in ldo.c */ 17 | 18 | /* table of globals */ 19 | #define gt(L) (&L->l_gt) 20 | 21 | /* registry */ 22 | #define registry(L) (&G(L)->l_registry) 23 | 24 | /* extra stack space to handle TM calls and some other extras */ 25 | #define EXTRA_STACK 5 26 | 27 | #define BASIC_CI_SIZE 8 28 | 29 | #define BASIC_STACK_SIZE (2 * LUA_MINSTACK) 30 | 31 | typedef struct stringtable { 32 | GCObject **hash; 33 | lu_int32 nuse; /* number of elements */ 34 | int size; 35 | } stringtable; 36 | 37 | /* 38 | ** informations about a call 39 | */ 40 | typedef struct CallInfo { 41 | StkId base; /* base for this function */ 42 | StkId func; /* function index in the stack */ 43 | StkId top; /* top for this function */ 44 | const Instruction *savedpc; 45 | int nresults; /* expected number of results from this function */ 46 | int tailcalls; /* number of tail calls lost under this entry */ 47 | } CallInfo; 48 | 49 | #define curr_func(L) (clvalue(L->ci->func)) 50 | #define ci_func(ci) (clvalue((ci)->func)) 51 | #define f_isLua(ci) (!ci_func(ci)->c.isC) 52 | #define isLua(ci) (ttisfunction((ci)->func) && f_isLua(ci)) 53 | 54 | /* 55 | ** `global state', shared by all threads of this state 56 | */ 57 | typedef struct global_State { 58 | stringtable strt; /* hash table for strings */ 59 | lua_Alloc frealloc; /* function to reallocate memory */ 60 | void *ud; /* auxiliary data to `frealloc' */ 61 | lu_byte currentwhite; 62 | lu_byte gcstate; /* state of garbage collector */ 63 | int sweepstrgc; /* position of sweep in `strt' */ 64 | GCObject *rootgc; /* list of all collectable objects */ 65 | GCObject **sweepgc; /* position of sweep in `rootgc' */ 66 | GCObject *gray; /* list of gray objects */ 67 | GCObject *grayagain; /* list of objects to be traversed atomically */ 68 | GCObject *weak; /* list of weak tables (to be cleared) */ 69 | GCObject *tmudata; /* last element of list of userdata to be GC */ 70 | Mbuffer buff; /* temporary buffer for string concatentation */ 71 | lu_mem GCthreshold; 72 | lu_mem totalbytes; /* number of bytes currently allocated */ 73 | lu_mem estimate; /* an estimate of number of bytes actually in use */ 74 | lu_mem gcdept; /* how much GC is `behind schedule' */ 75 | int gcpause; /* size of pause between successive GCs */ 76 | int gcstepmul; /* GC `granularity' */ 77 | lua_CFunction panic; /* to be called in unprotected errors */ 78 | TValue l_registry; 79 | struct lua_State *mainthread; 80 | UpVal uvhead; /* head of double-linked list of all open upvalues */ 81 | struct Table *mt[NUM_TAGS]; /* metatables for basic types */ 82 | TString *tmname[TM_N]; /* array with tag-method names */ 83 | } global_State; 84 | 85 | /* 86 | ** `per thread' state 87 | */ 88 | struct lua_State { 89 | CommonHeader; 90 | lu_byte status; 91 | StkId top; /* first free slot in the stack */ 92 | StkId base; /* base of current function */ 93 | global_State *l_G; 94 | CallInfo *ci; /* call info for current function */ 95 | const Instruction *savedpc; /* `savedpc' of current function */ 96 | StkId stack_last; /* last free slot in the stack */ 97 | StkId stack; /* stack base */ 98 | CallInfo *end_ci; /* points after end of ci array*/ 99 | CallInfo *base_ci; /* array of CallInfo's */ 100 | int stacksize; 101 | int size_ci; /* size of array `base_ci' */ 102 | unsigned short nCcalls; /* number of nested C calls */ 103 | unsigned short baseCcalls; /* nested C calls when resuming coroutine */ 104 | lu_byte hookmask; 105 | lu_byte allowhook; 106 | int basehookcount; 107 | int hookcount; 108 | lua_Hook hook; 109 | TValue l_gt; /* table of globals */ 110 | TValue env; /* temporary place for environments */ 111 | GCObject *openupval; /* list of open upvalues in this stack */ 112 | GCObject *gclist; 113 | struct lua_longjmp *errorJmp; /* current error recover point */ 114 | ptrdiff_t errfunc; /* current error handling function (stack index) */ 115 | }; 116 | 117 | #define G(L) (L->l_G) 118 | 119 | /* 120 | ** Union of all collectable objects 121 | */ 122 | union GCObject { 123 | GCheader gch; 124 | union TString ts; 125 | union Udata u; 126 | union Closure cl; 127 | struct Table h; 128 | struct Proto p; 129 | struct UpVal uv; 130 | struct lua_State th; /* thread */ 131 | }; 132 | 133 | /* macros to convert a GCObject into a specific value */ 134 | #define rawgco2ts(o) check_exp((o)->gch.tt == LUA_TSTRING, &((o)->ts)) 135 | #define gco2ts(o) (&rawgco2ts(o)->tsv) 136 | #define rawgco2u(o) check_exp((o)->gch.tt == LUA_TUSERDATA, &((o)->u)) 137 | #define gco2u(o) (&rawgco2u(o)->uv) 138 | #define gco2cl(o) check_exp((o)->gch.tt == LUA_TFUNCTION, &((o)->cl)) 139 | #define gco2h(o) check_exp((o)->gch.tt == LUA_TTABLE, &((o)->h)) 140 | #define gco2p(o) check_exp((o)->gch.tt == LUA_TPROTO, &((o)->p)) 141 | #define gco2uv(o) check_exp((o)->gch.tt == LUA_TUPVAL, &((o)->uv)) 142 | #define ngcotouv(o) check_exp((o) == NULL || (o)->gch.tt == LUA_TUPVAL, &((o)->uv)) 143 | #define gco2th(o) check_exp((o)->gch.tt == LUA_TTHREAD, &((o)->th)) 144 | 145 | /* macro to convert any Lua object into a GCObject */ 146 | #define obj2gco(v) (cast(GCObject *, (v))) 147 | 148 | LUAI_FUNC lua_State *luaE_newthread(lua_State *L); 149 | LUAI_FUNC void luaE_freethread(lua_State *L, lua_State *L1); 150 | 151 | #endif 152 | -------------------------------------------------------------------------------- /src/vm/src/lua/lstring.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lstring.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $ 3 | ** String table (keeps all strings handled by Lua) 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #include 8 | 9 | #define lstring_c 10 | #define LUA_CORE 11 | 12 | #include "lua.h" 13 | 14 | #include "lmem.h" 15 | #include "lobject.h" 16 | #include "lstate.h" 17 | #include "lstring.h" 18 | 19 | /* SPOOKY hash algorithm */ 20 | #include "../util/spooky.h" 21 | 22 | void luaS_resize(lua_State *L, int newsize) 23 | { 24 | GCObject **newhash; 25 | stringtable *tb; 26 | int i; 27 | if (G(L)->gcstate == GCSsweepstring) 28 | return; /* cannot resize during GC traverse */ 29 | newhash = luaM_newvector(L, newsize, GCObject *); 30 | tb = &G(L)->strt; 31 | for (i = 0; i < newsize; i++) 32 | newhash[i] = NULL; 33 | /* rehash */ 34 | for (i = 0; i < tb->size; i++) { 35 | GCObject *p = tb->hash[i]; 36 | while (p) { /* for each node in the list */ 37 | GCObject *next = p->gch.next; /* save next */ 38 | unsigned int h = gco2ts(p)->hash; 39 | int h1 = lmod(h, newsize); /* new position */ 40 | lua_assert(cast_int(h % newsize) == lmod(h, newsize)); 41 | p->gch.next = newhash[h1]; /* chain it */ 42 | newhash[h1] = p; 43 | p = next; 44 | } 45 | } 46 | luaM_freearray(L, tb->hash, tb->size, TString *); 47 | tb->size = newsize; 48 | tb->hash = newhash; 49 | } 50 | 51 | static TString *newlstr(lua_State *L, const char *str, size_t l, unsigned int h) 52 | { 53 | TString *ts; 54 | stringtable *tb; 55 | if (l + 1 > (MAX_SIZET - sizeof(TString)) / sizeof(char)) 56 | luaM_toobig(L); 57 | ts = cast(TString *, luaM_malloc(L, (l + 1) * sizeof(char) + sizeof(TString))); 58 | ts->tsv.len = l; 59 | ts->tsv.hash = h; 60 | ts->tsv.marked = luaC_white(G(L)); 61 | ts->tsv.tt = LUA_TSTRING; 62 | ts->tsv.reserved = 0; 63 | memcpy(ts + 1, str, l * sizeof(char)); 64 | ((char *)(ts + 1))[l] = '\0'; /* ending 0 */ 65 | tb = &G(L)->strt; 66 | h = lmod(h, tb->size); 67 | ts->tsv.next = tb->hash[h]; /* chain new entry */ 68 | tb->hash[h] = obj2gco(ts); 69 | tb->nuse++; 70 | if (tb->nuse > cast(lu_int32, tb->size) && tb->size <= MAX_INT / 2) 71 | luaS_resize(L, tb->size * 2); /* too crowded */ 72 | return ts; 73 | } 74 | 75 | TString *luaS_newlstr(lua_State *L, const char *str, size_t l) 76 | { 77 | GCObject *o; 78 | unsigned int h = spooky_hash32(str, l, cast(unsigned int, l)); 79 | 80 | for (o = G(L)->strt.hash[lmod(h, G(L)->strt.size)]; o != NULL; o = o->gch.next) { 81 | TString *ts = rawgco2ts(o); 82 | if (ts->tsv.len == l && (memcmp(str, getstr(ts), l) == 0)) { 83 | /* string may be dead */ 84 | if (isdead(G(L), o)) 85 | changewhite(o); 86 | return ts; 87 | } 88 | } 89 | return newlstr(L, str, l, h); /* not found */ 90 | } 91 | 92 | Udata *luaS_newudata(lua_State *L, size_t s, Table *e) 93 | { 94 | Udata *u; 95 | if (s > MAX_SIZET - sizeof(Udata)) 96 | luaM_toobig(L); 97 | u = cast(Udata *, luaM_malloc(L, s + sizeof(Udata))); 98 | u->uv.marked = luaC_white(G(L)); /* is not finalized */ 99 | u->uv.tt = LUA_TUSERDATA; 100 | u->uv.len = s; 101 | u->uv.metatable = NULL; 102 | u->uv.env = e; 103 | /* chain it on udata list (after main thread) */ 104 | u->uv.next = G(L)->mainthread->next; 105 | G(L)->mainthread->next = obj2gco(u); 106 | return u; 107 | } 108 | -------------------------------------------------------------------------------- /src/vm/src/lua/lstring.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lstring.h,v 1.43.1.1 2007/12/27 13:02:25 roberto Exp $ 3 | ** String table (keep all strings handled by Lua) 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef lstring_h 8 | #define lstring_h 9 | 10 | #include "lgc.h" 11 | #include "lobject.h" 12 | #include "lstate.h" 13 | 14 | #define sizestring(s) (sizeof(union TString) + ((s)->len + 1) * sizeof(char)) 15 | 16 | #define sizeudata(u) (sizeof(union Udata) + (u)->len) 17 | 18 | #define luaS_new(L, s) (luaS_newlstr(L, s, strlen(s))) 19 | #define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, (sizeof(s) / sizeof(char)) - 1)) 20 | 21 | #define luaS_fix(s) l_setbit((s)->tsv.marked, FIXEDBIT) 22 | 23 | LUAI_FUNC void luaS_resize(lua_State *L, int newsize); 24 | LUAI_FUNC Udata *luaS_newudata(lua_State *L, size_t s, Table *e); 25 | LUAI_FUNC TString *luaS_newlstr(lua_State *L, const char *str, size_t l); 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /src/vm/src/lua/ltable.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: ltable.h,v 2.10.1.1 2007/12/27 13:02:25 roberto Exp $ 3 | ** Lua tables (hash) 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef ltable_h 8 | #define ltable_h 9 | 10 | #include "lobject.h" 11 | 12 | #define gnode(t, i) (&(t)->node[i]) 13 | #define gkey(n) (&(n)->i_key.nk) 14 | #define gval(n) (&(n)->i_val) 15 | #define gnext(n) ((n)->i_key.nk.next) 16 | 17 | #define key2tval(n) (&(n)->i_key.tvk) 18 | 19 | LUAI_FUNC const TValue *luaH_getnum(Table *t, int key); 20 | LUAI_FUNC TValue *luaH_setnum(lua_State *L, Table *t, int key); 21 | LUAI_FUNC const TValue *luaH_getstr(Table *t, TString *key); 22 | LUAI_FUNC TValue *luaH_setstr(lua_State *L, Table *t, TString *key); 23 | LUAI_FUNC const TValue *luaH_get(Table *t, const TValue *key); 24 | LUAI_FUNC TValue *luaH_set(lua_State *L, Table *t, const TValue *key); 25 | LUAI_FUNC Table *luaH_new(lua_State *L, int narray, int lnhash); 26 | LUAI_FUNC void luaH_resizearray(lua_State *L, Table *t, int nasize); 27 | LUAI_FUNC void luaH_free(lua_State *L, Table *t); 28 | LUAI_FUNC int luaH_next(lua_State *L, Table *t, StkId key); 29 | LUAI_FUNC int luaH_getn(Table *t); 30 | 31 | #if defined(LUA_DEBUG) 32 | LUAI_FUNC Node *luaH_mainposition(const Table *t, const TValue *key); 33 | LUAI_FUNC int luaH_isdummy(Node *n); 34 | #endif 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /src/vm/src/lua/ltablib.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: ltablib.c,v 1.38.1.3 2008/02/14 16:46:58 roberto Exp $ 3 | ** Library for Table Manipulation 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #include 8 | 9 | #define ltablib_c 10 | #define LUA_LIB 11 | 12 | #include "lua.h" 13 | 14 | #include "lauxlib.h" 15 | #include "lualib.h" 16 | 17 | #define aux_getn(L, n) (luaL_checktype(L, n, LUA_TTABLE), luaL_getn(L, n)) 18 | 19 | static int foreachi(lua_State *L) 20 | { 21 | int i; 22 | int n = aux_getn(L, 1); 23 | luaL_checktype(L, 2, LUA_TFUNCTION); 24 | for (i = 1; i <= n; i++) { 25 | lua_pushvalue(L, 2); /* function */ 26 | lua_pushinteger(L, i); /* 1st argument */ 27 | lua_rawgeti(L, 1, i); /* 2nd argument */ 28 | lua_call(L, 2, 1); 29 | if (!lua_isnil(L, -1)) 30 | return 1; 31 | lua_pop(L, 1); /* remove nil result */ 32 | } 33 | return 0; 34 | } 35 | 36 | static int foreach (lua_State *L) 37 | { 38 | luaL_checktype(L, 1, LUA_TTABLE); 39 | luaL_checktype(L, 2, LUA_TFUNCTION); 40 | lua_pushnil(L); /* first key */ 41 | while (lua_next(L, 1)) { 42 | lua_pushvalue(L, 2); /* function */ 43 | lua_pushvalue(L, -3); /* key */ 44 | lua_pushvalue(L, -3); /* value */ 45 | lua_call(L, 2, 1); 46 | if (!lua_isnil(L, -1)) 47 | return 1; 48 | lua_pop(L, 2); /* remove value and result */ 49 | } 50 | return 0; 51 | } 52 | 53 | static int maxn(lua_State *L) 54 | { 55 | lua_Number max = 0; 56 | luaL_checktype(L, 1, LUA_TTABLE); 57 | lua_pushnil(L); /* first key */ 58 | while (lua_next(L, 1)) { 59 | lua_pop(L, 1); /* remove value */ 60 | if (lua_type(L, -1) == LUA_TNUMBER) { 61 | lua_Number v = lua_tonumber(L, -1); 62 | if (v > max) 63 | max = v; 64 | } 65 | } 66 | lua_pushnumber(L, max); 67 | return 1; 68 | } 69 | 70 | static int getn(lua_State *L) 71 | { 72 | lua_pushinteger(L, aux_getn(L, 1)); 73 | return 1; 74 | } 75 | 76 | static int setn(lua_State *L) 77 | { 78 | luaL_checktype(L, 1, LUA_TTABLE); 79 | #ifndef luaL_setn 80 | luaL_setn(L, 1, luaL_checkint(L, 2)); 81 | #else 82 | luaL_error(L, LUA_QL("setn") " is obsolete"); 83 | #endif 84 | lua_pushvalue(L, 1); 85 | return 1; 86 | } 87 | 88 | static int tinsert(lua_State *L) 89 | { 90 | int e = aux_getn(L, 1) + 1; /* first empty element */ 91 | int pos; /* where to insert new element */ 92 | switch (lua_gettop(L)) { 93 | case 2: { /* called with only 2 arguments */ 94 | pos = e; /* insert new element at the end */ 95 | break; 96 | } 97 | case 3: { 98 | int i; 99 | pos = luaL_checkint(L, 2); /* 2nd argument is the position */ 100 | if (pos > e) 101 | e = pos; /* `grow' array if necessary */ 102 | for (i = e; i > pos; i--) { /* move up elements */ 103 | lua_rawgeti(L, 1, i - 1); 104 | lua_rawseti(L, 1, i); /* t[i] = t[i-1] */ 105 | } 106 | break; 107 | } 108 | default: { 109 | return luaL_error(L, "wrong number of arguments to " LUA_QL("insert")); 110 | } 111 | } 112 | luaL_setn(L, 1, e); /* new size */ 113 | lua_rawseti(L, 1, pos); /* t[pos] = v */ 114 | return 0; 115 | } 116 | 117 | static int tremove(lua_State *L) 118 | { 119 | int e = aux_getn(L, 1); 120 | int pos = luaL_optint(L, 2, e); 121 | if (!(1 <= pos && pos <= e)) /* position is outside bounds? */ 122 | return 0; /* nothing to remove */ 123 | luaL_setn(L, 1, e - 1); /* t.n = n-1 */ 124 | lua_rawgeti(L, 1, pos); /* result = t[pos] */ 125 | for (; pos < e; pos++) { 126 | lua_rawgeti(L, 1, pos + 1); 127 | lua_rawseti(L, 1, pos); /* t[pos] = t[pos+1] */ 128 | } 129 | lua_pushnil(L); 130 | lua_rawseti(L, 1, e); /* t[e] = nil */ 131 | return 1; 132 | } 133 | 134 | static void addfield(lua_State *L, luaL_Buffer *b, int i) 135 | { 136 | lua_rawgeti(L, 1, i); 137 | if (!lua_isstring(L, -1)) 138 | luaL_error(L, "invalid value (%s) at index %d in table for " LUA_QL("concat"), 139 | luaL_typename(L, -1), i); 140 | luaL_addvalue(b); 141 | } 142 | 143 | static int tconcat(lua_State *L) 144 | { 145 | luaL_Buffer b; 146 | size_t lsep; 147 | int i, last; 148 | const char *sep = luaL_optlstring(L, 2, "", &lsep); 149 | luaL_checktype(L, 1, LUA_TTABLE); 150 | i = luaL_optint(L, 3, 1); 151 | last = luaL_opt(L, luaL_checkint, 4, luaL_getn(L, 1)); 152 | luaL_buffinit(L, &b); 153 | for (; i < last; i++) { 154 | addfield(L, &b, i); 155 | luaL_addlstring(&b, sep, lsep); 156 | } 157 | if (i == last) /* add last value (if interval was not empty) */ 158 | addfield(L, &b, i); 159 | luaL_pushresult(&b); 160 | return 1; 161 | } 162 | 163 | /* 164 | ** {====================================================== 165 | ** Quicksort 166 | ** (based on `Algorithms in MODULA-3', Robert Sedgewick; 167 | ** Addison-Wesley, 1993.) 168 | */ 169 | 170 | static void set2(lua_State *L, int i, int j) 171 | { 172 | lua_rawseti(L, 1, i); 173 | lua_rawseti(L, 1, j); 174 | } 175 | 176 | static int sort_comp(lua_State *L, int a, int b) 177 | { 178 | if (!lua_isnil(L, 2)) { /* function? */ 179 | int res; 180 | lua_pushvalue(L, 2); 181 | lua_pushvalue(L, a - 1); /* -1 to compensate function */ 182 | lua_pushvalue(L, b - 2); /* -2 to compensate function and `a' */ 183 | lua_call(L, 2, 1); 184 | res = lua_toboolean(L, -1); 185 | lua_pop(L, 1); 186 | return res; 187 | } else /* a < b? */ 188 | return lua_lessthan(L, a, b); 189 | } 190 | 191 | static void auxsort(lua_State *L, int l, int u) 192 | { 193 | while (l < u) { /* for tail recursion */ 194 | int i, j; 195 | /* sort elements a[l], a[(l+u)/2] and a[u] */ 196 | lua_rawgeti(L, 1, l); 197 | lua_rawgeti(L, 1, u); 198 | if (sort_comp(L, -1, -2)) /* a[u] < a[l]? */ 199 | set2(L, l, u); /* swap a[l] - a[u] */ 200 | else 201 | lua_pop(L, 2); 202 | if (u - l == 1) 203 | break; /* only 2 elements */ 204 | i = (l + u) / 2; 205 | lua_rawgeti(L, 1, i); 206 | lua_rawgeti(L, 1, l); 207 | if (sort_comp(L, -2, -1)) /* a[i]= P */ 228 | while (lua_rawgeti(L, 1, ++i), sort_comp(L, -1, -2)) { 229 | if (i > u) 230 | luaL_error(L, "invalid order function for sorting"); 231 | lua_pop(L, 1); /* remove a[i] */ 232 | } 233 | /* repeat --j until a[j] <= P */ 234 | while (lua_rawgeti(L, 1, --j), sort_comp(L, -3, -1)) { 235 | if (j < l) 236 | luaL_error(L, "invalid order function for sorting"); 237 | lua_pop(L, 1); /* remove a[j] */ 238 | } 239 | if (j < i) { 240 | lua_pop(L, 3); /* pop pivot, a[i], a[j] */ 241 | break; 242 | } 243 | set2(L, i, j); 244 | } 245 | lua_rawgeti(L, 1, u - 1); 246 | lua_rawgeti(L, 1, i); 247 | set2(L, u - 1, i); /* swap pivot (a[u-1]) with a[i] */ 248 | /* a[l..i-1] <= a[i] == P <= a[i+1..u] */ 249 | /* adjust so that smaller half is in [j..i] and larger one in [l..u] */ 250 | if (i - l < u - i) { 251 | j = l; 252 | i = i - 1; 253 | l = i + 2; 254 | } else { 255 | j = i + 1; 256 | i = u; 257 | u = j - 2; 258 | } 259 | auxsort(L, j, i); /* call recursively the smaller one */ 260 | } /* repeat the routine for the larger one */ 261 | } 262 | 263 | static int sort(lua_State *L) 264 | { 265 | int n = aux_getn(L, 1); 266 | luaL_checkstack(L, 40, ""); /* assume array is smaller than 2^40 */ 267 | if (!lua_isnoneornil(L, 2)) /* is there a 2nd argument? */ 268 | luaL_checktype(L, 2, LUA_TFUNCTION); 269 | lua_settop(L, 2); /* make sure there is two arguments */ 270 | auxsort(L, 1, n); 271 | return 0; 272 | } 273 | 274 | /* }====================================================== */ 275 | 276 | static const luaL_Reg tab_funcs[] = { 277 | {"concat", tconcat}, {"foreach", foreach}, {"foreachi", foreachi}, {"getn", getn}, 278 | {"maxn", maxn}, {"insert", tinsert}, {"remove", tremove}, {"setn", setn}, 279 | {"sort", sort}, {NULL, NULL}}; 280 | 281 | LUALIB_API int luaopen_table(lua_State *L) 282 | { 283 | luaL_register(L, LUA_TABLIBNAME, tab_funcs); 284 | return 1; 285 | } 286 | -------------------------------------------------------------------------------- /src/vm/src/lua/ltm.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: ltm.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $ 3 | ** Tag methods 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #include 8 | 9 | #define ltm_c 10 | #define LUA_CORE 11 | 12 | #include "lua.h" 13 | 14 | #include "lobject.h" 15 | #include "lstate.h" 16 | #include "lstring.h" 17 | #include "ltable.h" 18 | #include "ltm.h" 19 | 20 | const char *const luaT_typenames[] = {"nil", "boolean", "userdata", "number", 21 | "string", "table", "function", "userdata", 22 | "thread", "proto", "upval"}; 23 | 24 | void luaT_init(lua_State *L) 25 | { 26 | static const char *const luaT_eventname[] = { 27 | /* ORDER TM */ 28 | "__index", "__newindex", "__gc", "__mode", "__eq", "__add", "__sub", "__mul", "__div", 29 | "__mod", "__pow", "__unm", "__len", "__lt", "__le", "__concat", "__call"}; 30 | int i; 31 | for (i = 0; i < TM_N; i++) { 32 | G(L)->tmname[i] = luaS_new(L, luaT_eventname[i]); 33 | luaS_fix(G(L)->tmname[i]); /* never collect these names */ 34 | } 35 | } 36 | 37 | /* 38 | ** function to be used with macro "fasttm": optimized for absence of 39 | ** tag methods 40 | */ 41 | const TValue *luaT_gettm(Table *events, TMS event, TString *ename) 42 | { 43 | const TValue *tm = luaH_getstr(events, ename); 44 | lua_assert(event <= TM_EQ); 45 | if (ttisnil(tm)) { /* no tag method? */ 46 | events->flags |= cast_byte(1u << event); /* cache this fact */ 47 | return NULL; 48 | } else 49 | return tm; 50 | } 51 | 52 | const TValue *luaT_gettmbyobj(lua_State *L, const TValue *o, TMS event) 53 | { 54 | Table *mt; 55 | switch (ttype(o)) { 56 | case LUA_TTABLE: 57 | mt = hvalue(o)->metatable; 58 | break; 59 | case LUA_TUSERDATA: 60 | mt = uvalue(o)->metatable; 61 | break; 62 | default: 63 | mt = G(L)->mt[ttype(o)]; 64 | } 65 | return (mt ? luaH_getstr(mt, G(L)->tmname[event]) : luaO_nilobject); 66 | } 67 | -------------------------------------------------------------------------------- /src/vm/src/lua/ltm.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: ltm.h,v 2.6.1.1 2007/12/27 13:02:25 roberto Exp $ 3 | ** Tag methods 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef ltm_h 8 | #define ltm_h 9 | 10 | #include "lobject.h" 11 | 12 | /* 13 | * WARNING: if you change the order of this enumeration, 14 | * grep "ORDER TM" 15 | */ 16 | typedef enum { 17 | TM_INDEX, 18 | TM_NEWINDEX, 19 | TM_GC, 20 | TM_MODE, 21 | TM_EQ, /* last tag method with `fast' access */ 22 | TM_ADD, 23 | TM_SUB, 24 | TM_MUL, 25 | TM_DIV, 26 | TM_MOD, 27 | TM_POW, 28 | TM_UNM, 29 | TM_LEN, 30 | TM_LT, 31 | TM_LE, 32 | TM_CONCAT, 33 | TM_CALL, 34 | TM_N /* number of elements in the enum */ 35 | } TMS; 36 | 37 | #define gfasttm(g, et, e) \ 38 | ((et) == NULL ? NULL : ((et)->flags & (1u << (e))) ? NULL : luaT_gettm(et, e, (g)->tmname[e])) 39 | 40 | #define fasttm(l, et, e) gfasttm(G(l), et, e) 41 | 42 | LUAI_DATA const char *const luaT_typenames[]; 43 | 44 | LUAI_FUNC const TValue *luaT_gettm(Table *events, TMS event, TString *ename); 45 | LUAI_FUNC const TValue *luaT_gettmbyobj(lua_State *L, const TValue *o, TMS event); 46 | LUAI_FUNC void luaT_init(lua_State *L); 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /src/vm/src/lua/lualib.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lualib.h,v 1.36.1.1 2007/12/27 13:02:25 roberto Exp $ 3 | ** Lua standard libraries 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef lualib_h 8 | #define lualib_h 9 | 10 | #include "lua.h" 11 | 12 | /* Key to file-handle type */ 13 | #define LUA_FILEHANDLE "FILE*" 14 | 15 | #define LUA_COLIBNAME "coroutine" 16 | LUALIB_API int(luaopen_base)(lua_State *L); 17 | 18 | #define LUA_TABLIBNAME "table" 19 | LUALIB_API int(luaopen_table)(lua_State *L); 20 | 21 | #define LUA_IOLIBNAME "io" 22 | LUALIB_API int(luaopen_io)(lua_State *L); 23 | 24 | #define LUA_OSLIBNAME "os" 25 | LUALIB_API int(luaopen_os)(lua_State *L); 26 | 27 | #define LUA_STRLIBNAME "string" 28 | LUALIB_API int(luaopen_string)(lua_State *L); 29 | 30 | #define LUA_MATHLIBNAME "math" 31 | LUALIB_API int(luaopen_math)(lua_State *L); 32 | 33 | #define LUA_DBLIBNAME "debug" 34 | LUALIB_API int(luaopen_debug)(lua_State *L); 35 | 36 | #define LUA_LOADLIBNAME "package" 37 | LUALIB_API int(luaopen_package)(lua_State *L); 38 | 39 | /* open all previous libraries */ 40 | LUALIB_API void(luaL_openlibs)(lua_State *L); 41 | 42 | #ifndef lua_assert 43 | #define lua_assert(x) ((void)0) 44 | #endif 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /src/vm/src/lua/lvm.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lvm.h,v 2.5.1.1 2007/12/27 13:02:25 roberto Exp $ 3 | ** Lua virtual machine 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef lvm_h 8 | #define lvm_h 9 | 10 | #include "ldo.h" 11 | #include "lobject.h" 12 | #include "ltm.h" 13 | 14 | #define tostring(L, o) ((ttype(o) == LUA_TSTRING) || (luaV_tostring(L, o))) 15 | 16 | #define tonumber(o, n) (ttype(o) == LUA_TNUMBER || (((o) = luaV_tonumber(o, n)) != NULL)) 17 | 18 | #define equalobj(L, o1, o2) (ttype(o1) == ttype(o2) && luaV_equalval(L, o1, o2)) 19 | 20 | LUAI_FUNC int luaV_lessthan(lua_State *L, const TValue *l, const TValue *r); 21 | LUAI_FUNC int luaV_equalval(lua_State *L, const TValue *t1, const TValue *t2); 22 | LUAI_FUNC int luaV_lessequal(lua_State *L, const TValue *l, const TValue *r); 23 | LUAI_FUNC const TValue *luaV_tonumber(const TValue *obj, TValue *n); 24 | LUAI_FUNC int luaV_tostring(lua_State *L, StkId obj); 25 | LUAI_FUNC void luaV_gettable(lua_State *L, const TValue *t, TValue *key, StkId val); 26 | LUAI_FUNC void luaV_settable(lua_State *L, const TValue *t, TValue *key, StkId val); 27 | LUAI_FUNC void luaV_execute(lua_State *L, int nexeccalls); 28 | LUAI_FUNC void luaV_concat(lua_State *L, int total, int last); 29 | 30 | /* Lua++ additions */ 31 | LUAI_FUNC void luaV_getenv(lua_State *L, Table *env, TValue *k); 32 | LUAI_FUNC void luaV_arith(lua_State *L, StkId ra, const TValue *rb, const TValue *rc, TMS op); 33 | LUAI_FUNC void luapp_execute(lua_State *L, int nexeccalls); 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /src/vm/src/lua/lzio.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lzio.c,v 1.31.1.1 2007/12/27 13:02:25 roberto Exp $ 3 | ** a generic input stream interface 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #include 8 | 9 | #define lzio_c 10 | #define LUA_CORE 11 | 12 | #include "lua.h" 13 | 14 | #include "llimits.h" 15 | #include "lmem.h" 16 | #include "lstate.h" 17 | #include "lzio.h" 18 | 19 | int luaZ_fill(ZIO *z) 20 | { 21 | size_t size; 22 | lua_State *L = z->L; 23 | const char *buff; 24 | lua_unlock(L); 25 | buff = z->reader(L, z->data, &size); 26 | lua_lock(L); 27 | if (buff == NULL || size == 0) 28 | return EOZ; 29 | z->n = size - 1; 30 | z->p = buff; 31 | return char2int(*(z->p++)); 32 | } 33 | 34 | int luaZ_lookahead(ZIO *z) 35 | { 36 | if (z->n == 0) { 37 | if (luaZ_fill(z) == EOZ) 38 | return EOZ; 39 | else { 40 | z->n++; /* luaZ_fill removed first byte; put back it */ 41 | z->p--; 42 | } 43 | } 44 | return char2int(*z->p); 45 | } 46 | 47 | void luaZ_init(lua_State *L, ZIO *z, lua_Reader reader, void *data) 48 | { 49 | z->L = L; 50 | z->reader = reader; 51 | z->data = data; 52 | z->n = 0; 53 | z->p = NULL; 54 | } 55 | 56 | /* --------------------------------------------------------------- read --- */ 57 | size_t luaZ_read(ZIO *z, void *b, size_t n) 58 | { 59 | while (n) { 60 | size_t m; 61 | if (luaZ_lookahead(z) == EOZ) 62 | return n; /* return number of missing bytes */ 63 | m = (n <= z->n) ? n : z->n; /* min. between n and z->n */ 64 | memcpy(b, z->p, m); 65 | z->n -= m; 66 | z->p += m; 67 | b = (char *)b + m; 68 | n -= m; 69 | } 70 | return 0; 71 | } 72 | 73 | /* ------------------------------------------------------------------------ */ 74 | char *luaZ_openspace(lua_State *L, Mbuffer *buff, size_t n) 75 | { 76 | if (n > buff->buffsize) { 77 | if (n < LUA_MINBUFFER) 78 | n = LUA_MINBUFFER; 79 | luaZ_resizebuffer(L, buff, n); 80 | } 81 | return buff->buffer; 82 | } 83 | -------------------------------------------------------------------------------- /src/vm/src/lua/lzio.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lzio.h,v 1.21.1.1 2007/12/27 13:02:25 roberto Exp $ 3 | ** Buffered streams 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef lzio_h 8 | #define lzio_h 9 | 10 | #include "lua.h" 11 | 12 | #include "lmem.h" 13 | 14 | #define EOZ (-1) /* end of stream */ 15 | 16 | typedef struct Zio ZIO; 17 | 18 | #define char2int(c) cast(int, cast(unsigned char, (c))) 19 | 20 | #define zgetc(z) (((z)->n--) > 0 ? char2int(*(z)->p++) : luaZ_fill(z)) 21 | 22 | typedef struct Mbuffer { 23 | char *buffer; 24 | size_t n; 25 | size_t buffsize; 26 | } Mbuffer; 27 | 28 | #define luaZ_initbuffer(L, buff) ((buff)->buffer = NULL, (buff)->buffsize = 0) 29 | 30 | #define luaZ_buffer(buff) ((buff)->buffer) 31 | #define luaZ_sizebuffer(buff) ((buff)->buffsize) 32 | #define luaZ_bufflen(buff) ((buff)->n) 33 | 34 | #define luaZ_resetbuffer(buff) ((buff)->n = 0) 35 | 36 | #define luaZ_resizebuffer(L, buff, size) \ 37 | (luaM_reallocvector(L, (buff)->buffer, (buff)->buffsize, size, char), (buff)->buffsize = size) 38 | 39 | #define luaZ_freebuffer(L, buff) luaZ_resizebuffer(L, buff, 0) 40 | 41 | LUAI_FUNC char *luaZ_openspace(lua_State *L, Mbuffer *buff, size_t n); 42 | LUAI_FUNC void luaZ_init(lua_State *L, ZIO *z, lua_Reader reader, void *data); 43 | LUAI_FUNC size_t luaZ_read(ZIO *z, void *b, size_t n); /* read next n bytes */ 44 | LUAI_FUNC int luaZ_lookahead(ZIO *z); 45 | 46 | /* --------- Private Part ------------------ */ 47 | 48 | struct Zio { 49 | size_t n; /* bytes still unread */ 50 | const char *p; /* current position in buffer */ 51 | lua_Reader reader; 52 | void *data; /* additional data */ 53 | lua_State *L; /* Lua state (for reader) */ 54 | }; 55 | 56 | LUAI_FUNC int luaZ_fill(ZIO *z); 57 | 58 | #endif 59 | -------------------------------------------------------------------------------- /src/vm/src/lua/print.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: print.c,v 1.55a 2006/05/31 13:30:05 lhf Exp $ 3 | ** print bytecodes 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | #define luac_c 11 | #define LUA_CORE 12 | 13 | #include "ldebug.h" 14 | #include "lobject.h" 15 | 16 | #include "../../../common/bytecode.h" 17 | #include "../../../common/opcodes.h" 18 | 19 | #define PrintFunction luaU_print 20 | 21 | #define Sizeof(x) ((int)sizeof(x)) 22 | #define VOID(p) ((const void *)(p)) 23 | 24 | static void PrintString(const TString *ts) 25 | { 26 | const char *s = getstr(ts); 27 | size_t i, n = ts->tsv.len; 28 | putchar('"'); 29 | for (i = 0; i < n; i++) { 30 | int c = s[i]; 31 | switch (c) { 32 | case '"': 33 | printf("\\\""); 34 | break; 35 | case '\\': 36 | printf("\\\\"); 37 | break; 38 | case '\a': 39 | printf("\\a"); 40 | break; 41 | case '\b': 42 | printf("\\b"); 43 | break; 44 | case '\f': 45 | printf("\\f"); 46 | break; 47 | case '\n': 48 | printf("\\n"); 49 | break; 50 | case '\r': 51 | printf("\\r"); 52 | break; 53 | case '\t': 54 | printf("\\t"); 55 | break; 56 | case '\v': 57 | printf("\\v"); 58 | break; 59 | default: 60 | if (isprint((unsigned char)c)) 61 | putchar(c); 62 | else 63 | printf("\\%03u", (unsigned char)c); 64 | } 65 | } 66 | putchar('"'); 67 | } 68 | 69 | static void PrintConstant(const Proto *f, int i) 70 | { 71 | const TValue *o = &f->k[i]; 72 | switch (ttype(o)) { 73 | case LUA_TNIL: 74 | printf("nil"); 75 | break; 76 | case LUA_TBOOLEAN: 77 | printf(bvalue(o) ? "true" : "false"); 78 | break; 79 | case LUA_TNUMBER: 80 | printf(LUA_NUMBER_FMT, nvalue(o)); 81 | break; 82 | case LUA_TSTRING: 83 | PrintString(rawtsvalue(o)); 84 | break; 85 | default: /* cannot happen */ 86 | printf("? type=%d", ttype(o)); 87 | break; 88 | } 89 | } 90 | 91 | static void PrintCode(const Proto *f) 92 | { 93 | const Instruction *code = f->code; 94 | int pc, n = f->sizecode; 95 | for (pc = 0; pc < n; pc++) { 96 | Instruction i = code[pc]; 97 | opcode_t o = GET_OPCODE(i); 98 | int a = GETARG_A(i); 99 | int b = GETARG_B(i); 100 | int c = GETARG_C(i); 101 | int d = GETARG_D(i); 102 | int e = GETARG_E(i); 103 | 104 | printf("\t%d\t", pc + 1); 105 | 106 | int line = getline(f, pc); 107 | if (line > 0) 108 | printf("[%d]\t", line); 109 | else 110 | printf("[-]\t"); 111 | printf("%-9s\t", opcode_names[o]); 112 | 113 | // int line = getline(f, pc); 114 | // printf("\t%d\t", pc + 1); 115 | // if (line > 0) 116 | // printf("[%d]\t", line); 117 | // else 118 | // printf("[-]\t"); 119 | // printf("%-9s\t", luaP_opnames[o]); 120 | // switch (getOpMode(o)) { 121 | // case iABC: 122 | // printf("%d", a); 123 | // if (getBMode(o) != OpArgN) 124 | // printf(" %d", ISK(b) ? (-1 - INDEXK(b)) : b); 125 | // if (getCMode(o) != OpArgN) 126 | // printf(" %d", ISK(c) ? (-1 - INDEXK(c)) : c); 127 | // break; 128 | // case iAD: 129 | // if (getBMode(o) == OpArgK) 130 | // printf("%d %d", a, -1 - d); 131 | // else 132 | // printf("%d %d", a, d); 133 | // break; 134 | // case iE: 135 | // printf("%d", e); 136 | // break; 137 | // } 138 | // switch (o) { 139 | // case OP_LOADK: 140 | // printf("\t; "); 141 | // PrintConstant(f, d); 142 | // break; 143 | // case OP_GETUPVAL: 144 | // case OP_SETUPVAL: 145 | // printf("\t; %s", (f->sizeupvalues > 0) ? getstr(f->upvalues[b]) : "-"); 146 | // break; 147 | // case OP_GETGLOBAL: 148 | // case OP_SETGLOBAL: 149 | // printf("\t; %s", svalue(&f->k[d])); 150 | // break; 151 | // case OP_GETTABLE: 152 | // case OP_SELF: 153 | // if (ISK(c)) { 154 | // printf("\t; "); 155 | // PrintConstant(f, INDEXK(c)); 156 | // } 157 | // break; 158 | // case OP_SETTABLE: 159 | // case OP_ADD: 160 | // case OP_SUB: 161 | // case OP_MUL: 162 | // case OP_DIV: 163 | // case OP_POW: 164 | // case OP_EQ: 165 | // case OP_LT: 166 | // case OP_LE: 167 | // if (ISK(b) || ISK(c)) { 168 | // printf("\t; "); 169 | // if (ISK(b)) 170 | // PrintConstant(f, INDEXK(b)); 171 | // else 172 | // printf("-"); 173 | // printf(" "); 174 | // if (ISK(c)) 175 | // PrintConstant(f, INDEXK(c)); 176 | // else 177 | // printf("-"); 178 | // } 179 | // break; 180 | // case OP_JMP: 181 | // case OP_FORLOOP: 182 | // case OP_FORPREP: 183 | // printf("\t; to %d", d + pc + 2); 184 | // break; 185 | // case OP_CLOSURE: 186 | // printf("\t; %p", VOID(f->p[d])); 187 | // break; 188 | // case OP_SETLIST: 189 | // if (c == 0) 190 | // printf("\t; %d", (int)code[++pc]); 191 | // else 192 | // printf("\t; %d", c); 193 | // break; 194 | // default: 195 | // break; 196 | // } 197 | printf("\n"); 198 | } 199 | } 200 | 201 | #define SS(x) (x == 1) ? "" : "s" 202 | #define S(x) x, SS(x) 203 | 204 | static void PrintHeader(const Proto *f) 205 | { 206 | const char *s = getstr(f->source); 207 | if (*s == '@' || *s == '=') 208 | s++; 209 | else if (*s == LUA_SIGNATURE[0]) 210 | s = "(bstring)"; 211 | else 212 | s = "(string)"; 213 | printf("%s <%s:%d,%d> (%d instruction%s, %d bytes at %p)\n", 214 | (f->linedefined == 0) ? "main" : "function", s, f->linedefined, f->lastlinedefined, 215 | S(f->sizecode), f->sizecode * Sizeof(Instruction), VOID(f)); 216 | printf("%d%s param%s, %d slot%s, %d upvalue%s, ", f->numparams, f->is_vararg ? "+" : "", 217 | SS(f->numparams), S(f->maxstacksize), S(f->nups)); 218 | printf("%d local%s, %d constant%s, %d function%s\n", S(f->sizelocvars), S(f->sizek), 219 | S(f->sizep)); 220 | } 221 | 222 | static void PrintConstants(const Proto *f) 223 | { 224 | int i, n = f->sizek; 225 | printf("constants (%d) for %p:\n", n, VOID(f)); 226 | for (i = 0; i < n; i++) { 227 | printf("\t%d\t", i + 1); 228 | PrintConstant(f, i); 229 | printf("\n"); 230 | } 231 | } 232 | 233 | static void PrintLocals(const Proto *f) 234 | { 235 | int i, n = f->sizelocvars; 236 | printf("locals (%d) for %p:\n", n, VOID(f)); 237 | for (i = 0; i < n; i++) { 238 | printf("\t%d\t%s\t%d\t%d\n", i, getstr(f->locvars[i].varname), f->locvars[i].startpc + 1, 239 | f->locvars[i].endpc + 1); 240 | } 241 | } 242 | 243 | static void PrintUpvalues(const Proto *f) 244 | { 245 | int i, n = f->sizeupvalues; 246 | printf("upvalues (%d) for %p:\n", n, VOID(f)); 247 | if (f->upvalues == NULL) 248 | return; 249 | for (i = 0; i < n; i++) { 250 | printf("\t%d\t%s\n", i, getstr(f->upvalues[i])); 251 | } 252 | } 253 | 254 | void PrintFunction(const Proto *f, int full) 255 | { 256 | int i, n = f->sizep; 257 | PrintHeader(f); 258 | PrintCode(f); 259 | if (full) { 260 | PrintConstants(f); 261 | PrintLocals(f); 262 | PrintUpvalues(f); 263 | } 264 | for (i = 0; i < n; i++) 265 | PrintFunction(f->p[i], full); 266 | } 267 | -------------------------------------------------------------------------------- /src/vm/src/main.c: -------------------------------------------------------------------------------- 1 | /* vm.c - only version 2 | * main entry point for the VM (virtual machine) 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "lua/lauxlib.h" 11 | #include "lua/lua.h" 12 | #include "lua/lualib.h" 13 | 14 | /* main() -- entry point for the VM */ 15 | int main(int argc, char **argv) 16 | { 17 | char *dot; 18 | FILE *input; 19 | 20 | /* Determine if we are using stdin or file in. */ 21 | if (optind == argc - 1) { 22 | dot = strrchr(argv[optind], '.'); 23 | 24 | /* If the given file is of the correct type, init the reader */ 25 | if (dot && (!strcmp(dot, ".out") || !strcmp(dot, ".bin"))) 26 | input = fopen(argv[optind], "r"); 27 | else { 28 | printf("Error: incorrect file type.\n"); 29 | return 1; 30 | } 31 | } else { 32 | printf("Error: expected one input file, found %d files.\n", argc - optind); 33 | return 1; 34 | } 35 | 36 | lua_State *L = luaL_newstate(); 37 | luaL_openlibs(L); 38 | 39 | if (luapp_loadfile(L, "=lua++", input)) { 40 | /* An error occured, display it and pop it from the stack */ 41 | printf("Error: %s\n", lua_tostring(L, -1)); 42 | lua_pop(L, 1); 43 | 44 | /* Close everything and return */ 45 | lua_close(L); 46 | return 1; 47 | } 48 | 49 | /* Run the closure at L->top + 0 */ 50 | lua_resume(L, 0); 51 | lua_close(L); 52 | return 0; 53 | } -------------------------------------------------------------------------------- /src/vm/src/util/spooky.h: -------------------------------------------------------------------------------- 1 | // SpookyHash: a 128-bit noncryptographic hash function 2 | // By Bob Jenkins, public domain 3 | // Oct 31 2010: alpha, framework + SpookyHash::Mix appears right 4 | // Oct 11 2011: C version ported by Andi Kleen (andikleen@github) 5 | // Oct 31 2011: alpha again, Mix only good to 2^^69 but rest appears right 6 | // Dec 31 2011: beta, improved Mix, tested it for 2-bit deltas 7 | // Feb 2 2012: production, same bits as beta 8 | // Feb 5 2012: adjusted definitions of uint* to be more portable 9 | // Mar 30 2012: 3 bytes/cycle, not 4. Alpha was 4 but wasn't thorough enough. 10 | // Apr 27 2012: C version updated by Ziga Zupanec ziga.zupanec@gmail.com (agiz@github) 11 | // 12 | // Up to 3 bytes/cycle for long messages. Reasonably fast for short messages. 13 | // All 1 or 2 bit deltas achieve avalanche within 1% bias per output bit. 14 | // 15 | // This was developed for and tested on 64-bit x86-compatible processors. 16 | // It assumes the processor is little-endian. There is a macro 17 | // controlling whether unaligned reads are allowed (by default they are). 18 | // This should be an equally good hash on big-endian machines, but it will 19 | // compute different results on them than on little-endian machines. 20 | // 21 | // Google's CityHash has similar specs to SpookyHash, and CityHash is faster 22 | // on some platforms. MD4 and MD5 also have similar specs, but they are orders 23 | // of magnitude slower. CRCs are two or more times slower, but unlike 24 | // SpookyHash, they have nice math for combining the CRCs of pieces to form 25 | // the CRCs of wholes. There are also cryptographic hashes, but those are even 26 | // slower than MD5. 27 | // 28 | 29 | #include 30 | #include 31 | 32 | #define SC_NUMVARS 12 33 | #define SC_BLOCKSIZE (8 * SC_NUMVARS) 34 | #define SC_BUFSIZE (2 * SC_BLOCKSIZE) 35 | 36 | struct spooky_state { 37 | uint64_t m_data[2 * SC_NUMVARS]; 38 | uint64_t m_state[SC_NUMVARS]; 39 | size_t m_length; 40 | unsigned char m_remainder; 41 | }; 42 | 43 | void spooky_shorthash(const void *message, size_t length, uint64_t *hash1, uint64_t *hash2); 44 | 45 | void spooky_init(struct spooky_state *state, uint64_t hash1, uint64_t hash2); 46 | 47 | void spooky_update(struct spooky_state *state, const void *msg, size_t len); 48 | 49 | void spooky_final(struct spooky_state *state, uint64_t *hash1, uint64_t *hash2); 50 | 51 | // hash1/2 doubles as input parameter for seed1/2 and output for hash1/2 52 | void spooky_hash128(const void *message, size_t length, uint64_t *hash1, uint64_t *hash2); 53 | 54 | uint64_t spooky_hash64(const void *message, size_t len, uint64_t seed); 55 | 56 | uint32_t spooky_hash32(const void *message, size_t len, uint32_t seed); -------------------------------------------------------------------------------- /src/vm/tests/incorrect_version.bin: -------------------------------------------------------------------------------- 1 | aprint) " 2 | 3 | -------------------------------------------------------------------------------- /src/vm/tests/negativenum.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luapp-org/luapp/9188cc373fdabd07161eb6d2acdd5156ebb2eb2a/src/vm/tests/negativenum.bin -------------------------------------------------------------------------------- /src/vm/tests/string_table.bin: -------------------------------------------------------------------------------- 1 | stringprint) " 2 | 3 | -------------------------------------------------------------------------------- /src/vm/tests/test.bin: -------------------------------------------------------------------------------- 1 | test ;)print) " 2 | 3 | --------------------------------------------------------------------------------