├── .gitignore ├── .vscode ├── c_cpp_properties.json ├── launch.json ├── settings.json └── tasks.json ├── Makefile ├── README.md ├── lib ├── libtcmalloc.a ├── libunwind-x86_64.a └── libunwind.a ├── logo.png ├── puppy.h ├── puppy.sln ├── puppy.vcxproj ├── puppy.vcxproj.filters ├── src ├── PuMap.h ├── PuMath.cpp ├── PuMath.h ├── PuStack.h ├── PuString.cpp ├── PuString.h ├── PuVector.h ├── api.cpp ├── builtin.cpp ├── bytecode.cpp ├── config.h ├── coroutine.cpp ├── def ├── def.h ├── error.cpp ├── error.h ├── gc.cpp ├── global.cpp ├── global.h ├── pu.cpp ├── state.cpp ├── state.h ├── token.cpp ├── token.h ├── travel.cpp ├── travel.h ├── util.h ├── value.cpp └── value.h └── test ├── closure.pu ├── closure2.pu ├── cmp └── code1.pu ├── code1.pu ├── code2.pu ├── code3.pu ├── code4.pu ├── code5.pu ├── code6.pu ├── code7.pu ├── code8.pu ├── code9.pu ├── console.cpp ├── main.cpp ├── map.pu ├── pertest.pu ├── puppytest.vcxproj ├── puppytest.vcxproj.filters ├── s.pu └── tailcall.pu /.gitignore: -------------------------------------------------------------------------------- 1 | *.psess 2 | *.user 3 | *.suo 4 | *.lib 5 | *.tlog 6 | *.obj 7 | *.log 8 | *.idb 9 | *.pdb 10 | *.lastbuildstate 11 | *.data 12 | *.puc 13 | *.old 14 | test/hahah 15 | output/ 16 | bin/ 17 | hahah 18 | lib/libpuppy.a 19 | lib/libpuppy_d.a 20 | test/cmp/pb.lua 21 | test/cmp/yp.py 22 | *.sdf 23 | *.opendb 24 | *.VC.db 25 | *.o 26 | /.vs 27 | *.ipch 28 | -------------------------------------------------------------------------------- /.vscode/c_cpp_properties.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": [ 3 | { 4 | "name": "Mac", 5 | "includePath": [ 6 | "./", 7 | "/usr/include", 8 | "/usr/local/include", 9 | "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1" 10 | ], 11 | "browse": { 12 | "limitSymbolsToIncludedHeaders": true, 13 | "databaseFilename": "", 14 | "path": [ 15 | "./", 16 | "/usr/include", 17 | "/usr/local/include", 18 | "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1", 19 | "${workspaceRoot}" 20 | ] 21 | }, 22 | "intelliSenseMode": "clang-x64" 23 | }, 24 | { 25 | "name": "Linux", 26 | "includePath": [ 27 | "/usr/include", 28 | "/usr/local/include" 29 | ], 30 | "browse": { 31 | "limitSymbolsToIncludedHeaders": true, 32 | "databaseFilename": "", 33 | "path": [ 34 | "/usr/include", 35 | "/usr/local/include", 36 | "./", 37 | "${workspaceRoot}" 38 | ] 39 | }, 40 | "intelliSenseMode": "clang-x64" 41 | }, 42 | { 43 | "name": "Win32", 44 | "includePath": [ 45 | "C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/include/*" 46 | ], 47 | "browse": { 48 | "limitSymbolsToIncludedHeaders": true, 49 | "databaseFilename": "", 50 | "path": [ 51 | "C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/include/*", 52 | "${workspaceRoot}" 53 | ] 54 | }, 55 | "intelliSenseMode": "msvc-x64" 56 | } 57 | ], 58 | "version": 2 59 | } -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "C++ Launch", 6 | "type": "cppdbg", 7 | "request": "launch", 8 | "program": "${workspaceRoot}/bin/puppy_d", 9 | "args": ["test/s.pu"], 10 | "stopAtEntry": true, 11 | "cwd": "${workspaceRoot}", 12 | "environment": [], 13 | "externalConsole": true, 14 | "preLaunchTask": "make", 15 | "linux": { 16 | "MIMode": "gdb", 17 | "setupCommands": [ 18 | { 19 | "description": "Enable pretty-printing for gdb", 20 | "text": "-enable-pretty-printing", 21 | "ignoreFailures": true 22 | } 23 | ] 24 | }, 25 | "osx": { 26 | "MIMode": "lldb" 27 | }, 28 | "windows": { 29 | "MIMode": "gdb", 30 | "setupCommands": [ 31 | { 32 | "description": "Enable pretty-printing for gdb", 33 | "text": "-enable-pretty-printing", 34 | "ignoreFailures": true 35 | } 36 | ] 37 | } 38 | }, 39 | { 40 | "name": "C++ Attach", 41 | "type": "cppdbg", 42 | "request": "attach", 43 | "program": "${workspaceRoot}/bin/puppy_d", 44 | "processId": "${command:pickProcess}", 45 | "linux": { 46 | "MIMode": "gdb", 47 | "setupCommands": [ 48 | { 49 | "description": "Enable pretty-printing for gdb", 50 | "text": "-enable-pretty-printing", 51 | "ignoreFailures": true 52 | } 53 | ] 54 | }, 55 | "osx": { 56 | "MIMode": "lldb" 57 | }, 58 | "windows": { 59 | "MIMode": "gdb", 60 | "setupCommands": [ 61 | { 62 | "description": "Enable pretty-printing for gdb", 63 | "text": "-enable-pretty-printing", 64 | "ignoreFailures": true 65 | } 66 | ] 67 | } 68 | } 69 | ] 70 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "cmath": "cpp", 4 | "hashtable": "cpp", 5 | "cstdlib": "cpp", 6 | "*.tcc": "cpp" 7 | } 8 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "0.1.0", 5 | "command": "make", 6 | "isShellCommand": true, 7 | "args": [], 8 | "showOutput": "always" 9 | } -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Makefile 2 | # 3 | # usage : 4 | # make 5 | # make BUILD=release 6 | # make clean 7 | # 8 | 9 | TARGETNAME = puppy 10 | 11 | ifeq ($(BUILD), release) 12 | CXXFLAGS = -g -O3 -Wall -std=c++11 13 | OBJPATH = Release 14 | TARGET_BIN = bin/$(TARGETNAME) 15 | TARGET_LIB = lib/lib$(TARGETNAME).a 16 | LIBS = -L./lib/ -ltcmalloc -lunwind-x86_64 -lunwind -lpthread -all-static 17 | else 18 | CXXFLAGS = -g -O0 -D_DEBUG -Wall -std=c++11 19 | OBJPATH = Debug 20 | TARGET_BIN = bin/$(TARGETNAME)_d 21 | TARGET_LIB = lib/lib$(TARGETNAME)_d.a 22 | LIBS = 23 | endif 24 | 25 | 26 | SRCS_BIN = $(wildcard test/*.cpp) 27 | OBJS_BIN = $(SRCS_BIN:%.cpp=$(OBJPATH)/%.o) 28 | SRCS_LIB = $(wildcard *.cpp src/*.cpp) 29 | OBJS_LIB = $(SRCS_LIB:%.cpp=$(OBJPATH)/%.o) 30 | 31 | $(TARGET_BIN) : $(OBJS_BIN) $(TARGET_LIB) 32 | mkdir -p bin 33 | $(CXX) $(CXXFLAGS) -o $@ $^ $(LIBS) 34 | 35 | $(TARGET_LIB) : $(OBJS_LIB) 36 | mkdir -p lib 37 | $(AR) rc $(TARGET_LIB) $(OBJS_LIB) 38 | 39 | clean : 40 | rm -rf Release 41 | rm -rf Debug 42 | rm -rf bin 43 | 44 | $(OBJPATH)/%.o : %.cpp 45 | @mkdir -p $(dir $@) 46 | $(CXX) $(CXXFLAGS) -o $@ -c $< 47 | 48 | $(OBJPATH)/%.d : %.cpp 49 | @echo $(CXX) -MM -o $@ -c $< 50 | @rm -f $@ 51 | @mkdir -p $(dir $@) 52 | @$(CXX) $(CXXFLAGS) -MM -MT '$@ $(basename $@).o' $< -o $@ 53 | 54 | 55 | -include $(SRCS:%.cpp=$(OBJPATH)/%.d) 56 | 57 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 一种结构化脚本语言,含GC、闭包、协程、lambda等常规功能 2 | 带较少关键字,易学 3 | -------------------------------------------------------------------------------- /lib/libtcmalloc.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zlvb/PuppyLanguage/961a579c492911e5ada82ce6f0a461155ef393de/lib/libtcmalloc.a -------------------------------------------------------------------------------- /lib/libunwind-x86_64.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zlvb/PuppyLanguage/961a579c492911e5ada82ce6f0a461155ef393de/lib/libunwind-x86_64.a -------------------------------------------------------------------------------- /lib/libunwind.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zlvb/PuppyLanguage/961a579c492911e5ada82ce6f0a461155ef393de/lib/libunwind.a -------------------------------------------------------------------------------- /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zlvb/PuppyLanguage/961a579c492911e5ada82ce6f0a461155ef393de/logo.png -------------------------------------------------------------------------------- /puppy.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009 Zhang li 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | 22 | MIT License: http://www.opensource.org/licenses/mit-license.php 23 | */ 24 | 25 | /* 26 | Author zhang li 27 | Email zlvbvbzl@gmail.com 28 | puppy是一个小型语言解释器,支持所有的常规操作,如赋值、循环、条件判断等 29 | 并支持将使用c/c++编写的函数导入到脚本中 30 | */ 31 | 32 | #ifndef __Pu_H__ 33 | #define __Pu_H__ 34 | 35 | #include 36 | 37 | typedef int64_t PU_INT; 38 | typedef double PU_FLOAT; 39 | typedef PU_FLOAT PU_NUMBER; 40 | 41 | typedef struct Pu Pu; 42 | typedef struct __pu_var __pu_var; 43 | typedef __pu_var* pu_var; 44 | 45 | // 可以让脚本调用的函数类型 46 | typedef void (*ScriptFunc)(Pu*, int argnum, pu_var*); 47 | 48 | // 操作结果 49 | typedef enum PURESULT{ 50 | PU_FAILED = -1,// 失败 51 | PU_SUCCESS = 0// 成功 52 | }PURESULT; 53 | 54 | // 值类型 55 | typedef enum PUVALUETYPE{ 56 | NIL = 1000, // 空 57 | NUM, // 数字 58 | STR, // 字符串 59 | ARRAY, // 数组 60 | MAP, // 字典 61 | CORO, // 协程对象 62 | FILEHANDLE, // 文件句柄 63 | BOOLEANT, // 布尔 64 | INTEGER, // 整数 65 | FUN, // 函数 66 | CFUN, // C函数 67 | CPTR, // 指针 68 | }PUVALUETYPE; 69 | 70 | // 值是由脚本系统创建的,还是用户调用pu_new_value创建的 71 | typedef enum PUVALUECREATEDBY{ 72 | PU_SYSTEM,// 脚本系统 73 | PU_USER// 用户 74 | }PUVALUECREATEDBY;// 修改由脚本系统创建的值会导致失败 75 | 76 | 77 | #ifdef __cplusplus 78 | extern "C"{ 79 | #endif 80 | 81 | /** 82 | * 83 | * 获得解释器版本 84 | * 返回值: 85 | * 解释器版本 86 | * 87 | */ 88 | const char *pu_version(); 89 | 90 | /** 91 | * 92 | * 生成一个脚本解释器对象 93 | * 返回值: 94 | * Pu 指针 95 | * 96 | */ 97 | Pu *pu_open(); 98 | 99 | 100 | /** 101 | * 102 | * 关闭一个脚本解释器对象 103 | * 参数: 104 | * Pu *L 脚本解释器对象 105 | * 106 | */ 107 | void pu_close(Pu *L); 108 | 109 | 110 | /** 111 | * 112 | * 加载脚本 113 | * 参数: 114 | * Pu *L 脚本解释器对象 115 | * const char *fname 脚本文件名 116 | */ 117 | PURESULT pu_load(Pu *L, const char *fname); 118 | 119 | /* 120 | * 载入字符串 121 | */ 122 | PURESULT pu_loadbuff(Pu *L, const char *str); 123 | 124 | /** 125 | * 126 | * 执行脚本 127 | * 参数: 128 | * Pu *L 脚本解释器对象 129 | */ 130 | void pu_run(Pu *L); 131 | 132 | 133 | /** 134 | * 135 | * 根据源码生成字节码 136 | * 参数: 137 | * Pu *L 脚本解释器对象 138 | * const char *fname 源代码文件名 139 | * 140 | */ 141 | void pu_makebytecode(Pu *L, const char *fname); 142 | 143 | /** 144 | * 145 | * 设置脚本函数返回值 146 | * 参数: 147 | * Pu *L 脚本解释器对象 148 | * pu_value *v 返回值 149 | * 150 | */ 151 | void pu_set_return_value(Pu *L, pu_var v); 152 | pu_var pu_get_return_value(Pu *L); 153 | 154 | /** 155 | * 156 | * 注册一个函数让脚本调用 157 | * 参数: 158 | * Pu *L 脚本解释器对象 159 | * const char *funcname 在脚本中的函数名字 160 | * ScriptFunc func 函数指针 161 | * int argnum 参数个数 162 | * 163 | */ 164 | void pu_reg_func(Pu *L, const char *funcname, ScriptFunc pfunc); 165 | 166 | /** 167 | * 168 | * 把值转化成字符串 169 | * 参数: 170 | * const pu_value v 与脚本交互的值类型的对象 171 | * 返回: 172 | * 值所代表的字符串 173 | * 174 | */ 175 | const char *pu_str(pu_var v); 176 | 177 | /** 178 | * 179 | * 把值转化成数字 180 | * 参数: 181 | * const pu_value v 与脚本交互的值类型的对象 182 | * 返回: 183 | * 值所代表的数值 184 | * 185 | */ 186 | PU_NUMBER pu_num(pu_var v); 187 | 188 | /** 189 | * 190 | * 把值转化成整数 191 | * 参数: 192 | * const pu_value v 与脚本交互的值类型的对象 193 | * 返回: 194 | * 值所代表的整数 195 | * 196 | */ 197 | PU_INT pu_int(pu_var v); 198 | 199 | /** 200 | * 201 | * 把值转化成指针 202 | * 参数: 203 | * const pu_value v 与脚本交互的值类型的对象 204 | * 返回: 205 | * 值所代表的指针 206 | * 207 | */ 208 | void *pu_ptr(pu_var v); 209 | 210 | /** 211 | * 212 | * 获得数组下标所指向的值 213 | * 参数: 214 | * const pu_value v 与脚本交互的值类型的对象 215 | * int idx 数组下标 216 | * 返回: 217 | * 数组成员 218 | * 219 | */ 220 | pu_var pu_arr(pu_var v, int idx); 221 | 222 | /** 223 | * 224 | * 获得值的类型 225 | * 参数: 226 | * const pu_value v 与脚本交互的值类型的对象 227 | * 返回: 228 | * 类型 229 | * 230 | */ 231 | PUVALUETYPE pu_type(pu_var v); 232 | 233 | /** 234 | * 235 | * 把值设置为字符串 236 | * 参数: 237 | * const pu_value v 与脚本交互的值类型的对象 238 | * const char *str 要设置的字符串 239 | * 240 | */ 241 | PURESULT pu_set_str(pu_var v, const char *str); 242 | 243 | /** 244 | * 245 | * 把值设置为数字 246 | * 参数: 247 | * const pu_value v 与脚本交互的值类型的对象 248 | * int num 要设置的数字 249 | * 250 | */ 251 | PURESULT pu_set_num(pu_var v, PU_NUMBER num); 252 | 253 | /** 254 | * 255 | * 把值设置为整数 256 | * 参数: 257 | * const pu_value v 与脚本交互的值类型的对象 258 | * int num 要设置的整数 259 | * 260 | */ 261 | PURESULT pu_set_int(pu_var v, PU_INT num); 262 | 263 | /** 264 | * 265 | * 把值设置为指针 266 | * 参数: 267 | * const pu_value v 与脚本交互的值类型的对象 268 | * void *ptr 要设置的指针 269 | * 270 | */ 271 | PURESULT pu_set_ptr(pu_var v, void *ptr); 272 | 273 | /** 274 | * 275 | * 把值设置为数组 276 | * 参数: 277 | * const pu_value v 与脚本交互的值类型的对象 278 | * const int num 要设置的数字 279 | * 280 | */ 281 | PURESULT pu_set_arr(pu_var varr, int idx, pu_var v); 282 | 283 | // 值是由脚本系统创建的,还是用户调用pu_new_value创建的 284 | PUVALUECREATEDBY pu_value_created_by(pu_var v); 285 | 286 | // 在数组的最后插入值 287 | PURESULT pu_push_arr(pu_var varr, pu_var v); 288 | 289 | 290 | // 在数组的最后删除值 291 | PURESULT pu_pop_arr(pu_var varr); 292 | 293 | // 得到值的长度 294 | int pu_len(pu_var v); 295 | 296 | 297 | /** 298 | * 299 | * 产生新的值 300 | * 参数: 301 | * Pu *L 脚本解释器对象 302 | * 返回: 303 | * 值对象 304 | * 305 | */ 306 | pu_var pu_new_value(Pu *L); 307 | 308 | /** 309 | * 310 | * 删除一个值 311 | * 参数: 312 | * const pu_value v 与脚本交互的值类型的对象 313 | * 314 | */ 315 | PURESULT pu_del_value(pu_var v); 316 | 317 | /** 318 | * 319 | * 调用脚本中的函数 320 | * 参数: 321 | * Pu *L 脚本解释器对象 322 | * const char *function_name 函数名 323 | * const pu_value varr 参数数组 324 | * 325 | */ 326 | pu_var pu_call(Pu *L, const char *function_name, pu_var varr); 327 | 328 | /** 329 | * 330 | * 获得脚本中的全局变量 331 | * 参数: 332 | * Pu *L 脚本解释器对象 333 | * const char *varname 变量名 334 | * 返回值: 335 | * 脚本中的变量 336 | * 337 | */ 338 | pu_var pu_global(Pu *L, const char *varname); 339 | 340 | 341 | /* 342 | * 立即执行一个字符串 343 | */ 344 | int pu_eval(Pu *L, const char *str); 345 | 346 | 347 | /* 348 | * 得到一个值的字符串形式 349 | */ 350 | void pu_val2str(Pu *L, pu_var *v, char *buff, int buffsize); 351 | 352 | 353 | #ifdef __cplusplus 354 | } 355 | #endif 356 | 357 | #endif 358 | 359 | 360 | -------------------------------------------------------------------------------- /puppy.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26430.14 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pu", "puppy.vcxproj", "{E3E77AEA-990A-45D8-880E-3E1A8D01B565}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vm", "test\puppytest.vcxproj", "{4D9EDFC1-94C2-4010-8B26-BC3A54ED08D5}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Win32 = Debug|Win32 13 | Release|Win32 = Release|Win32 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {E3E77AEA-990A-45D8-880E-3E1A8D01B565}.Debug|Win32.ActiveCfg = Debug|Win32 17 | {E3E77AEA-990A-45D8-880E-3E1A8D01B565}.Debug|Win32.Build.0 = Debug|Win32 18 | {E3E77AEA-990A-45D8-880E-3E1A8D01B565}.Release|Win32.ActiveCfg = Release|Win32 19 | {E3E77AEA-990A-45D8-880E-3E1A8D01B565}.Release|Win32.Build.0 = Release|Win32 20 | {4D9EDFC1-94C2-4010-8B26-BC3A54ED08D5}.Debug|Win32.ActiveCfg = Debug|Win32 21 | {4D9EDFC1-94C2-4010-8B26-BC3A54ED08D5}.Debug|Win32.Build.0 = Debug|Win32 22 | {4D9EDFC1-94C2-4010-8B26-BC3A54ED08D5}.Release|Win32.ActiveCfg = Release|Win32 23 | {4D9EDFC1-94C2-4010-8B26-BC3A54ED08D5}.Release|Win32.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /puppy.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | pu 15 | {E3E77AEA-990A-45D8-880E-3E1A8D01B565} 16 | vm 17 | Win32Proj 18 | 8.1 19 | 20 | 21 | 22 | StaticLibrary 23 | v141 24 | Unicode 25 | 26 | 27 | StaticLibrary 28 | v141 29 | Unicode 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | <_ProjectFileVersion>11.0.61030.0 43 | 44 | 45 | $(SolutionDir)\lib\ 46 | $(Configuration)\ 47 | $(ProjectName)_d 48 | 49 | 50 | $(SolutionDir)\lib\ 51 | $(Configuration)\ 52 | 53 | 54 | 55 | Disabled 56 | false 57 | Neither 58 | false 59 | WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) 60 | false 61 | 62 | Level4 63 | EditAndContinue 64 | MultiThreadedDebug 65 | 66 | 67 | 68 | md $(SolutionDir)output\ 69 | md $(SolutionDir)output\lib\ 70 | md $(SolutionDir)output\include\ 71 | copy /y $(SolutionDir)lib\pu_d.lib $(SolutionDir)output\lib\ 72 | copy /y $(SolutionDir)puppy.h $(SolutionDir)output\include\ 73 | 74 | 75 | 76 | 77 | 78 | WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) 79 | false 80 | false 81 | 82 | Level4 83 | MultiThreaded 84 | 85 | 86 | true 87 | 88 | 89 | md $(SolutionDir)output\ 90 | md $(SolutionDir)output\lib\ 91 | md $(SolutionDir)output\include\ 92 | copy /y $(SolutionDir)lib\pu.lib $(SolutionDir)output\lib\ 93 | copy /y $(SolutionDir)puppy.h $(SolutionDir)output\include\ 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | -------------------------------------------------------------------------------- /puppy.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav 15 | 16 | 17 | {a8e60bc0-9d70-48b1-9c98-29979d2599ea} 18 | 19 | 20 | 21 | 22 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | Source Files 29 | 30 | 31 | Source Files 32 | 33 | 34 | Source Files 35 | 36 | 37 | Source Files 38 | 39 | 40 | Source Files 41 | 42 | 43 | Source Files 44 | 45 | 46 | Source Files 47 | 48 | 49 | Source Files 50 | 51 | 52 | Source Files 53 | 54 | 55 | utl 56 | 57 | 58 | utl 59 | 60 | 61 | Source Files 62 | 63 | 64 | 65 | 66 | Header Files 67 | 68 | 69 | Header Files 70 | 71 | 72 | Header Files 73 | 74 | 75 | Header Files 76 | 77 | 78 | Header Files 79 | 80 | 81 | Header Files 82 | 83 | 84 | Header Files 85 | 86 | 87 | utl 88 | 89 | 90 | utl 91 | 92 | 93 | utl 94 | 95 | 96 | utl 97 | 98 | 99 | utl 100 | 101 | 102 | Header Files 103 | 104 | 105 | Header Files 106 | 107 | 108 | Header Files 109 | 110 | 111 | -------------------------------------------------------------------------------- /src/PuMap.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009 Zhang li 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | 22 | MIT License: http://www.opensource.org/licenses/mit-license.php 23 | */ 24 | 25 | /* 26 | Author zhang li 27 | Email zlvbvbzl@gmail.com 28 | */ 29 | 30 | 31 | #ifndef __PU_MAP__ 32 | #define __PU_MAP__ 33 | 34 | #include "PuVector.h" 35 | #include 36 | 37 | template 38 | struct MapRef : public std::unordered_map 39 | { 40 | MapRef() :refcount(1) {}; 41 | int refcount; 42 | }; 43 | 44 | template 45 | class PuMap 46 | { 47 | public: 48 | typedef ::MapRef MapRef; 49 | typedef typename MapRef::iterator iterator; 50 | typedef typename MapRef::const_iterator const_iterator; 51 | PuMap():mapptr_(0) 52 | { } 53 | 54 | PuMap(const PuMap &r) :mapptr_(r.mapptr_) 55 | { 56 | if (mapptr_) 57 | { 58 | mapptr_->refcount++; 59 | } 60 | } 61 | 62 | ~PuMap() 63 | { 64 | release(); 65 | } 66 | 67 | void operator=(const PuMap &x) 68 | { 69 | if (mapptr_ != x.mapptr_) 70 | { 71 | if (mapptr_) 72 | { 73 | mapptr_->refcount--; 74 | } 75 | mapptr_ = x.mapptr_; 76 | if (mapptr_) 77 | { 78 | mapptr_->refcount++; 79 | } 80 | } 81 | } 82 | 83 | bool operator==(const PuMap &x) const 84 | { 85 | if (mapptr_ == x.mapptr_) 86 | { 87 | return true; 88 | } 89 | 90 | if (!mapptr_ || !x.mapptr_) 91 | { 92 | return false; 93 | } 94 | 95 | return *mapptr_ == *x.mapptr_; 96 | } 97 | 98 | int size() const 99 | { 100 | return mapptr_ ? mapptr_->size() : 0; 101 | } 102 | 103 | iterator begin() 104 | { 105 | if (!mapptr_) 106 | { 107 | return end(); 108 | } 109 | return mapptr_->begin(); 110 | } 111 | 112 | iterator end() 113 | { 114 | if (!mapptr_) 115 | { 116 | static MapRef dummy; 117 | return dummy.end(); 118 | } 119 | return mapptr_->end(); 120 | } 121 | 122 | const_iterator begin() const 123 | { 124 | if (!mapptr_) 125 | { 126 | return end(); 127 | } 128 | return mapptr_->begin(); 129 | } 130 | 131 | const_iterator end() const 132 | { 133 | if (!mapptr_) 134 | { 135 | static MapRef dummy; 136 | return dummy.end(); 137 | } 138 | return mapptr_->end(); 139 | } 140 | 141 | iterator find(const Key_T &key) 142 | { 143 | if (!mapptr_) 144 | { 145 | return end(); 146 | } 147 | return mapptr_->find(key); 148 | } 149 | 150 | iterator insert(const Key_T &key, const Value_T &const_value) 151 | { 152 | if (!mapptr_) 153 | { 154 | mapptr_ = new MapRef; 155 | } 156 | return mapptr_->insert(std::make_pair(key, const_value)).first; 157 | } 158 | 159 | void release() 160 | { 161 | if (mapptr_) 162 | { 163 | --mapptr_->refcount; 164 | if (mapptr_->refcount <= 0) 165 | { 166 | delete mapptr_; 167 | } 168 | mapptr_ = nullptr; 169 | } 170 | } 171 | 172 | void clear() 173 | { 174 | if (mapptr_) 175 | { 176 | mapptr_->clear(); 177 | } 178 | } 179 | 180 | MapRef *mapptr_; 181 | }; 182 | 183 | #endif 184 | 185 | -------------------------------------------------------------------------------- /src/PuMath.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009 Zhang li 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | 22 | MIT License: http://www.opensource.org/licenses/mit-license.php 23 | */ 24 | 25 | /* 26 | Author zhang li 27 | Email zlvbvbzl@gmail.com 28 | */ 29 | 30 | #include "PuMap.h" 31 | #include 32 | 33 | // 判断字符串是否可表示为一个整数 34 | extern "C" int is_int(const char *str) 35 | { 36 | if (!str) return 0; 37 | 38 | // 判断是否有符号 39 | if (str[0] == '-' || str[0] == '+') 40 | { 41 | ++str; 42 | } 43 | 44 | while (*str != '\0') 45 | { 46 | if (!isdigit(*str)) return 0; 47 | ++str; 48 | } 49 | return 1; 50 | } 51 | 52 | // 判断字符串是否可表示为一个浮点数 53 | extern "C" int is_float(const char *str) 54 | { 55 | int point = 0; 56 | if (!str) return 0; 57 | 58 | // 判断是否有符号 59 | if (str[0] == '-' || str[0] == '+') 60 | { 61 | ++str; 62 | } 63 | 64 | while (*str != '\0') 65 | { 66 | if (!isdigit(*str)) 67 | { 68 | if (*str == '.' && point == 0) 69 | { 70 | point=1; 71 | } 72 | else 73 | { 74 | return 0; 75 | } 76 | } 77 | ++str; 78 | } 79 | return 1; 80 | } 81 | 82 | -------------------------------------------------------------------------------- /src/PuMath.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009 Zhang li 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | 22 | MIT License: http://www.opensource.org/licenses/mit-license.php 23 | */ 24 | 25 | /* 26 | Author zhang li 27 | Email zlvbvbzl@gmail.com 28 | */ 29 | 30 | #ifndef _UTL_H_ 31 | #define _UTL_H_ 32 | 33 | #ifdef __cplusplus 34 | extern "C"{ 35 | #endif 36 | int is_int(const char *str); 37 | int is_float(const char *str); 38 | #ifdef __cplusplus 39 | } 40 | #endif 41 | 42 | #endif 43 | 44 | -------------------------------------------------------------------------------- /src/PuStack.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009 Zhang li 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | 22 | MIT License: http://www.opensource.org/licenses/mit-license.php 23 | */ 24 | 25 | /* 26 | Author zhang li 27 | Email zlvbvbzl@gmail.com 28 | */ 29 | 30 | #ifndef __pu_STACK_H__ 31 | #define __pu_STACK_H__ 32 | #include 33 | 34 | 35 | template 36 | struct PuStack : public std::vector 37 | { 38 | PuStack() 39 | { } 40 | 41 | void push( const T &i ) 42 | { 43 | this->push_back(i); 44 | } 45 | 46 | void pop() 47 | { 48 | this->pop_back(); 49 | } 50 | 51 | const T &top() const 52 | { 53 | return this->back(); 54 | } 55 | 56 | T &top() 57 | { 58 | return this->back(); 59 | } 60 | 61 | const T &bottom() const 62 | { 63 | return *this->begin(); 64 | } 65 | 66 | void release() 67 | { 68 | std::vector dummy; 69 | this->swap(dummy); 70 | } 71 | }; 72 | 73 | #endif 74 | 75 | -------------------------------------------------------------------------------- /src/PuString.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009 Zhang li 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | 22 | MIT License: http://www.opensource.org/licenses/mit-license.php 23 | */ 24 | 25 | /* 26 | Author zhang li 27 | Email zlvbvbzl@gmail.com 28 | */ 29 | 30 | #include "PuString.h" 31 | 32 | void PuString::set_char( int idx, char c ) 33 | { 34 | if ((*pbuff)[idx] != c) 35 | { 36 | if (pbuff->refc > 1) 37 | { 38 | PuBuffer *new_pbuff = new PuBuffer(c_str(), length()); 39 | release_buff(); 40 | pbuff = new_pbuff; 41 | } 42 | (*pbuff)[idx]=c; 43 | hash_Key = 0; 44 | } 45 | } 46 | 47 | PuString & PuString::operator=( const char *x ) 48 | { 49 | if (pbuff) 50 | { 51 | if (pbuff->c_str() == x) 52 | { 53 | return *this; 54 | } 55 | 56 | release_buff(); 57 | } 58 | hash_Key = 0; 59 | pbuff = new PuBuffer(x); 60 | return *this; 61 | } 62 | 63 | PuString & PuString::operator=( const PuString &x ) 64 | { 65 | if (pbuff == x.pbuff) 66 | { 67 | return *this; 68 | } 69 | 70 | if (pbuff) 71 | { 72 | release_buff(); 73 | } 74 | pbuff = x.pbuff; 75 | hash_Key = x.hash_Key; 76 | 77 | if (pbuff) 78 | { 79 | ++pbuff->refc; 80 | } 81 | 82 | return *this; 83 | } 84 | 85 | PuString PuString::operator+( const PuString &x ) const 86 | { 87 | PuBuffer *temp = new PuBuffer(c_str(), length()); 88 | temp->append(x.c_str(), x.length()); 89 | PuString ts; 90 | ts.pbuff = temp; 91 | return ts; 92 | } 93 | 94 | PuString &PuString::operator+=(char x) 95 | { 96 | char temp[2]={0}; 97 | temp[0] = x; 98 | return operator+=(temp); 99 | } 100 | 101 | PuString PuString::operator+( const char *x ) const 102 | { 103 | PuBuffer *temp = new PuBuffer(c_str(), length()); 104 | temp->append(x); 105 | PuString ts; 106 | ts.pbuff = temp; 107 | return ts; 108 | } 109 | 110 | bool PuString::operator==( const PuString &x ) const 111 | { 112 | return (pbuff == x.pbuff)? true : strcmp(c_str(),x.c_str()) == 0; 113 | } 114 | 115 | bool PuString::operator!=(const PuString &x) const 116 | { 117 | return !(*this == x); 118 | } 119 | 120 | PuString &PuString::operator+=( const PuString &x ) 121 | { 122 | if (pbuff) 123 | { 124 | PuBuffer *new_pbuff = new PuBuffer(c_str(), length()); 125 | new_pbuff->append(x.c_str(), x.length()); 126 | release_buff(); 127 | pbuff = new_pbuff; 128 | hash_Key = 0; 129 | } 130 | else 131 | { 132 | pbuff = new PuBuffer(x.c_str(), x.length()); 133 | } 134 | 135 | return *this; 136 | } 137 | 138 | PuString & PuString::operator+=( const char *x ) 139 | { 140 | if (pbuff) 141 | { 142 | PuBuffer *new_pbuff = new PuBuffer(c_str(), length()); 143 | new_pbuff->append(x); 144 | release_buff(); 145 | pbuff = new_pbuff; 146 | hash_Key = 0; 147 | } 148 | else 149 | { 150 | pbuff = new PuBuffer(x); 151 | } 152 | 153 | return *this; 154 | } 155 | 156 | void PuString::release_buff() 157 | { 158 | if (pbuff) 159 | { 160 | --pbuff->refc; 161 | if (pbuff->refc <= 0) 162 | { 163 | delete pbuff; 164 | } 165 | pbuff = nullptr; 166 | } 167 | } -------------------------------------------------------------------------------- /src/PuString.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009 Zhang li 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | 22 | MIT License: http://www.opensource.org/licenses/mit-license.php 23 | */ 24 | 25 | /* 26 | Author zhang li 27 | Email zlvbvbzl@gmail.com 28 | */ 29 | 30 | #ifndef _ZLSTR_H_ 31 | #define _ZLSTR_H_ 32 | 33 | #include "global.h" 34 | #include 35 | #include 36 | 37 | struct PuBuffer : public std::string 38 | { 39 | PuBuffer(const char *s) 40 | :std::string(s) 41 | ,refc(1) 42 | { 43 | 44 | } 45 | 46 | PuBuffer(const char *s, int l) 47 | :std::string(s, l) 48 | , refc(1) 49 | { 50 | 51 | } 52 | 53 | inline PuBuffer() 54 | :refc(1) 55 | {} 56 | 57 | int refc; 58 | }; 59 | 60 | 61 | struct PuString 62 | { 63 | PuString():pbuff(nullptr),hash_Key(0) 64 | { 65 | 66 | } 67 | 68 | PuString(const char *x):pbuff(nullptr),hash_Key(0) 69 | { 70 | *this = x; 71 | } 72 | 73 | PuString(const PuString &x):pbuff(nullptr),hash_Key(0) 74 | { 75 | *this = x; 76 | } 77 | 78 | ~PuString() 79 | { 80 | release_buff(); 81 | } 82 | 83 | bool operator==( const char *x ) const 84 | { 85 | if (!pbuff) 86 | { 87 | return false; 88 | } 89 | return *pbuff == x; 90 | } 91 | 92 | bool operator!=( const char *x ) const 93 | { 94 | return !(*this == x); 95 | } 96 | 97 | int length() const 98 | { 99 | return (pbuff) ? pbuff->length() : 0; 100 | } 101 | 102 | char operator[](int idx) const 103 | { 104 | return (*pbuff)[idx]; 105 | } 106 | 107 | void set_char(int idx, char c); 108 | 109 | bool operator<(const PuString &x) const 110 | { 111 | return strcmp(c_str(),x.c_str()) < 0; 112 | } 113 | 114 | PuString &operator=(const char *x); 115 | PuString &operator=(const PuString &x); 116 | PuString operator+(const PuString &x) const; 117 | PuString operator+(const char *x) const; 118 | 119 | PuString operator+(char x) const 120 | { 121 | char temp[2]={0}; 122 | temp[0] = x; 123 | return operator+(temp); 124 | } 125 | 126 | bool operator==(const PuString &x) const; 127 | bool operator!=(const PuString &x) const; 128 | PuString &operator+=(const PuString &x); 129 | PuString &operator+=(const char *x); 130 | void release_buff(); 131 | PuString &operator+=(char x); 132 | 133 | const char *c_str() const 134 | { 135 | return (pbuff)? pbuff->c_str(): ""; 136 | } 137 | 138 | unsigned int hash() const 139 | { 140 | if (hash_Key != 0) 141 | return hash_Key; 142 | 143 | const unsigned int seed = 131; 144 | const char *str = c_str(); 145 | unsigned int h = 0; 146 | 147 | while (*str) 148 | h = h * seed + ( *str++ ); 149 | 150 | hash_Key = h & 0x7FFFFFFF; 151 | return hash_Key; 152 | } 153 | 154 | PuBuffer *pbuff; 155 | mutable unsigned int hash_Key; 156 | }; 157 | 158 | 159 | #endif 160 | 161 | -------------------------------------------------------------------------------- /src/PuVector.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009 Zhang li 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | 22 | MIT License: http://www.opensource.org/licenses/mit-license.php 23 | */ 24 | 25 | /* 26 | Author zhang li 27 | Email zlvbvbzl@gmail.com 28 | */ 29 | 30 | #ifndef _PuVector_H_ 31 | #define _PuVector_H_ 32 | 33 | #include "global.h" 34 | #include 35 | 36 | template 37 | struct VectorBuff : public std::vector 38 | { 39 | VectorBuff():refcount(1) 40 | {} 41 | 42 | int refcount; 43 | }; 44 | 45 | template 46 | struct PuVector 47 | { 48 | typedef ValueType *iterator; 49 | 50 | PuVector():buff(nullptr) 51 | {} 52 | 53 | PuVector(const PuVector &x):buff(nullptr) 54 | { 55 | buff = x.buff; 56 | if (buff) 57 | { 58 | ++buff->refcount; 59 | } 60 | } 61 | 62 | ~PuVector() 63 | { 64 | release(); 65 | } 66 | 67 | bool operator==(const PuVector &x) const 68 | { 69 | if (buff == x.buff) 70 | { 71 | return true; 72 | } 73 | 74 | if (!buff || !x.buff) 75 | { 76 | return false; 77 | } 78 | 79 | return *buff == *x.buff; 80 | } 81 | 82 | int size() const 83 | { 84 | return (buff)? (int)buff->size() : 0; 85 | } 86 | 87 | void pop_back() 88 | { 89 | buff->pop_back(); 90 | } 91 | 92 | const ValueType &operator[](int idx) const 93 | { 94 | return (*buff)[idx]; 95 | } 96 | 97 | ValueType &operator[](int idx) 98 | { 99 | return (*buff)[idx]; 100 | } 101 | 102 | iterator begin() const 103 | { 104 | return (buff)? &*buff->begin() : 0; 105 | } 106 | 107 | iterator end() const 108 | { 109 | iterator it = &buff->back(); 110 | return (buff)? (++it) : 0; 111 | } 112 | 113 | ValueType &back() 114 | { 115 | return buff->back(); 116 | } 117 | 118 | void release() 119 | { 120 | if (buff && (--buff->refcount) == 0) 121 | { 122 | delete buff; 123 | } 124 | buff = 0; 125 | } 126 | 127 | void operator=(const PuVector &x) 128 | { 129 | if (buff != x.buff) 130 | { 131 | release(); 132 | buff = x.buff; 133 | if (buff) 134 | { 135 | ++buff->refcount; 136 | } 137 | } 138 | } 139 | 140 | void init(const ValueType &v, int count) 141 | { 142 | for (int i=0; i < count; ++i) 143 | { 144 | push_back(v); 145 | } 146 | } 147 | 148 | void push_back(const ValueType &v) 149 | { 150 | if (!buff) 151 | { 152 | buff = new VectorBuff(); 153 | } 154 | buff->push_back(v); 155 | } 156 | 157 | void erase(int idx) 158 | { 159 | buff->erase(buff->begin() + idx); 160 | } 161 | 162 | VectorBuff *buff; 163 | }; 164 | 165 | 166 | 167 | #endif 168 | 169 | -------------------------------------------------------------------------------- /src/api.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009 Zhang li 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | 22 | MIT License: http://www.opensource.org/licenses/mit-license.php 23 | */ 24 | 25 | /* 26 | Author zhang li 27 | Email zlvbvbzl@gmail.com 28 | */ 29 | 30 | #include "state.h" 31 | #include "error.h" 32 | const char *PU_VERSION = "Puppy 1.5.1"; 33 | 34 | extern int do_string(Pu *L, const char *str); 35 | extern void clear_state(Pu *L); 36 | extern int vm(Pu *L); 37 | extern const char *get_typestr(__pu_var &v); 38 | extern void regbuiltin(Pu *L); 39 | extern void set_var(Pu *L, const std::string &varname, __pu_var &new_value, __pu_var *&got); 40 | extern __pu_var *regvar(Pu *L, const std::string *varname); 41 | #ifdef _MSC_VER 42 | #pragma warning(disable:4127) // while(1) 43 | #endif 44 | 45 | 46 | PUAPI const char *pu_version() 47 | { 48 | return PU_VERSION; 49 | } 50 | 51 | PUAPI void pu_set_return_value(Pu *L, pu_var v) 52 | { 53 | L->return_value = *v; 54 | } 55 | 56 | PUAPI pu_var pu_get_return_value(Pu *L) 57 | { 58 | return &L->return_value; 59 | } 60 | 61 | PUAPI void pu_reg_func(Pu *L, const char *funcname, 62 | ScriptFunc pfunc) 63 | { 64 | FuncPos fps; 65 | fps.pfunc = pfunc; 66 | L->funclist.push_back(fps); 67 | 68 | __pu_var v(L); 69 | v.SetType(CFUN); 70 | v.intVal() = (PU_INT)L->funclist.size()-1; 71 | const std::string *strname = InsertStrPool(L, funcname); 72 | __pu_var *got = regvar(L, strname); 73 | *got = v; 74 | } 75 | 76 | PUAPI const char *pu_str(pu_var v) 77 | { 78 | return v->strVal().c_str(); 79 | } 80 | 81 | PUAPI PU_NUMBER pu_num(pu_var v) 82 | { 83 | return v->numVal(); 84 | } 85 | 86 | PUAPI PU_INT pu_int(pu_var v) 87 | { 88 | return v->intVal(); 89 | } 90 | 91 | PUAPI pu_var pu_arr(pu_var v, int idx) 92 | { 93 | return &(v->arr()[idx]); 94 | } 95 | 96 | PUAPI void *pu_ptr(pu_var v) 97 | { 98 | PU_INT n = v->intVal(); 99 | return (void*)n; 100 | } 101 | 102 | PUAPI int pu_type(pu_var v) 103 | { 104 | return int(v->type()); 105 | } 106 | 107 | PUAPI PURESULT pu_set_str(pu_var v, const char *str) 108 | { 109 | if (v->createby_ == PU_SYSTEM) 110 | { 111 | return PU_FAILED; 112 | } 113 | 114 | v->SetType(STR); 115 | v->strVal() = str; 116 | return PU_SUCCESS; 117 | } 118 | 119 | PUAPI int pu_eval(Pu *L, const char *str) 120 | { 121 | int ret = do_string(L, str); 122 | L->isquit = false; 123 | L->isreturn.clear(); 124 | return ret; 125 | } 126 | 127 | PUAPI PURESULT pu_set_num(pu_var v, PU_NUMBER number) 128 | { 129 | if (v->createby_ == PU_SYSTEM) 130 | { 131 | return PU_FAILED; 132 | } 133 | 134 | v->SetType(NUM); 135 | v->numVal() = number; 136 | return PU_SUCCESS; 137 | } 138 | 139 | PUAPI PURESULT pu_set_int(pu_var v, PU_INT intval) 140 | { 141 | if (v->createby_ == PU_SYSTEM) 142 | { 143 | return PU_FAILED; 144 | } 145 | 146 | v->SetType(INTEGER); 147 | v->intVal() = intval; 148 | return PU_SUCCESS; 149 | } 150 | 151 | PUAPI PURESULT pu_set_ptr(pu_var v, void *ptr) 152 | { 153 | if (v->createby_ == PU_SYSTEM) 154 | { 155 | return PU_FAILED; 156 | } 157 | 158 | v->SetType(CPTR); 159 | PU_INT n = (PU_INT)ptr; 160 | v->intVal() = n; 161 | return PU_SUCCESS; 162 | } 163 | 164 | PUAPI PURESULT pu_set_arr(pu_var v, 165 | int idx, pu_var u) 166 | { 167 | if (v->createby_ == PU_SYSTEM) 168 | { 169 | return PU_FAILED; 170 | } 171 | 172 | if (u->type() == ARRAY) 173 | { 174 | return PU_FAILED; 175 | } 176 | 177 | if (v->type() != ARRAY) 178 | { 179 | return PU_FAILED; 180 | } 181 | 182 | if (v->arr().size() < idx+1) 183 | { 184 | return PU_FAILED; 185 | } 186 | 187 | v->arr()[idx] = *u; 188 | return PU_SUCCESS; 189 | } 190 | 191 | 192 | PUAPI pu_var pu_new_value(Pu *L) 193 | { 194 | __pu_var *v = new __pu_var(L); 195 | v->createby_ = PU_USER; 196 | return v; 197 | } 198 | 199 | PUAPI PURESULT pu_del_value(pu_var v) 200 | { 201 | if (v->createby_ == PU_SYSTEM) 202 | { 203 | return PU_FAILED; 204 | } 205 | delete v; 206 | return PU_SUCCESS; 207 | } 208 | 209 | PUAPI PURESULT pu_push_arr(pu_var varr, 210 | pu_var v) 211 | { 212 | if (varr->createby_ == PU_SYSTEM) 213 | { 214 | return PU_FAILED; 215 | } 216 | 217 | varr->SetType(ARRAY); 218 | 219 | varr->arr().push_back(*v); 220 | return PU_SUCCESS; 221 | } 222 | 223 | PUAPI PURESULT pu_pop_arr(pu_var varr) 224 | { 225 | if (varr->createby_ == PU_SYSTEM) 226 | { 227 | return PU_FAILED; 228 | } 229 | 230 | varr->arr().pop_back(); 231 | return PU_SUCCESS; 232 | } 233 | 234 | PUAPI int pu_len(pu_var v) 235 | { 236 | if (v->type() == STR) 237 | { 238 | return v->strVal().length(); 239 | } 240 | else if (v->type() == ARRAY) 241 | { 242 | return v->arr().size(); 243 | } 244 | return -1; 245 | } 246 | 247 | 248 | PUAPI PUVALUECREATEDBY pu_value_created_by(pu_var v) 249 | { 250 | return v->createby_; 251 | } 252 | 253 | extern void run_coro( Pu * L, int coro_id, __pu_var * corov ); 254 | PUAPI void pu_run(Pu *L) 255 | { 256 | clear_state(L); 257 | regbuiltin(L); 258 | NEXT_TOKEN; 259 | vm(L); 260 | while (L->coros.size() > 0) 261 | { 262 | run_coro(L, 0, nullptr); 263 | } 264 | } 265 | 266 | PUAPI pu_var pu_global(Pu *L, const char *name) 267 | { 268 | StrKeyMap *pvarmap = L->varstack.bottom(); 269 | std::string strkey(name); 270 | auto it = pvarmap->find(&strkey); 271 | if (it != pvarmap->end()) 272 | { 273 | return &(it->second); 274 | } 275 | 276 | return nullptr; 277 | } 278 | 279 | PUAPI pu_var pu_call(Pu *L, const char *funcname, 280 | pu_var varr) 281 | { 282 | L->return_value.SetType(UNKNOWN); 283 | pu_var fv = pu_global(L,funcname); 284 | FuncPos &fps = L->funclist[(int)fv->intVal()]; 285 | 286 | const FunArgs &vArgs = fps.argnames; 287 | L->isreturn.push(0); 288 | if (fps.start == -1) 289 | { 290 | pu_var *args = nullptr; 291 | ValueArr vs; 292 | for (auto &v : varr->arr()) 293 | { 294 | vs.push_back(v); 295 | } 296 | 297 | int arg_num = vs.size(); 298 | 299 | if (arg_num > 0) 300 | { 301 | args = new pu_var[arg_num]; 302 | } 303 | 304 | for (int j = 0; j < arg_num; ++j) 305 | { 306 | args[j] = &(vs[j]); 307 | } 308 | 309 | fps.pfunc(L, int(arg_num), args); 310 | 311 | if (args) 312 | { 313 | delete[] args; 314 | } 315 | } 316 | else 317 | { 318 | StrKeyMap *newvarmap = new StrKeyMap; 319 | L->varstack.push(newvarmap); 320 | 321 | for (int j = 0; j < (int)vArgs.size(); ++j) 322 | { 323 | __pu_var v = varr->arr()[j]; 324 | newvarmap->insert(std::make_pair(vArgs[j], v)); 325 | } 326 | 327 | L->callstack.push(L->cur_token); 328 | L->cur_token = fps.start; 329 | NEXT_TOKEN; 330 | vm(L); 331 | L->varstack.pop(); 332 | delete newvarmap; 333 | 334 | L->cur_token = L->callstack.top(); 335 | L->callstack.pop(); 336 | } 337 | L->isreturn.pop(); 338 | 339 | return &(L->return_value); 340 | } 341 | 342 | 343 | PUAPI void pu_set_error_handle(Pu *L, ErrHandle func) 344 | { 345 | L->err_handle = func; 346 | } 347 | 348 | PUAPI void pu_set_output_handle(Pu *L, OutputHandle func) 349 | { 350 | L->output_handle = func; 351 | } 352 | 353 | #define s_WRITE_STR(s,b) \ 354 | strcat(b, s->strVal().c_str()); 355 | 356 | 357 | #define s_WRITE_NUM(n,b) \ 358 | char num[64]={0};\ 359 | if (PU_INT(n->numVal()) == n->numVal())\ 360 | PU_SNPRINTF(num, sizeof(num), "%.lf", n->numVal());\ 361 | else\ 362 | PU_SNPRINTF(num, sizeof(num),"%lf", n->numVal());\ 363 | strcat(b,num); 364 | 365 | #define s_WRITE_INT(n,b) \ 366 | char num[64]={0};\ 367 | PU_SNPRINTF(num, sizeof(num),"%lld", n->intVal());\ 368 | strcat(b,num); 369 | 370 | 371 | static void s_write_arr(const __pu_var &arr, char *b) 372 | { 373 | strcat(b,"["); 374 | ValueArr::iterator it = arr.arr().begin(); 375 | ValueArr::iterator ite = arr.arr().end(); 376 | while (it != ite) 377 | { 378 | __pu_var temp = *it; 379 | if (temp.type() == STR) 380 | { 381 | strcat(b,"\'"); 382 | s_WRITE_STR((&temp),b); 383 | strcat(b, "\'"); 384 | } 385 | else if (temp.type() == INTEGER) 386 | { 387 | s_WRITE_INT((&temp),b); 388 | } 389 | else if (temp.type() == NUM) 390 | { 391 | s_WRITE_NUM((&temp),b); 392 | } 393 | else if (temp.type() == ARRAY) 394 | { 395 | s_write_arr(temp,b); 396 | } 397 | ++it; 398 | 399 | if (it != ite) 400 | strcat(b,","); 401 | else 402 | break; 403 | } 404 | strcat(b,"]"); 405 | } 406 | 407 | PUAPI void pu_val2str(Pu *, pu_var *p, char *b, int buffsize) 408 | { 409 | b[0]=0; 410 | pu_var &v = *p; 411 | if (v->type() == INTEGER) 412 | { 413 | s_WRITE_INT(v,b); 414 | } 415 | else if (v->type() == NUM) 416 | { 417 | s_WRITE_NUM(v,b); 418 | } 419 | else if (v->type() == STR) 420 | { 421 | s_WRITE_STR(v,b); 422 | } 423 | else if (v->type() == ARRAY) 424 | { 425 | s_write_arr(*v,b); 426 | } 427 | else if (v->type() == MAP) 428 | { 429 | 430 | } 431 | else if (v->type() == BOOLEANT) 432 | { 433 | PU_SNPRINTF(b, buffsize, "%s", (v->intVal() != 0)?"true":"false"); 434 | } 435 | else 436 | { 437 | strncpy(b, get_typestr(*v), buffsize); 438 | } 439 | } 440 | 441 | 442 | 443 | -------------------------------------------------------------------------------- /src/builtin.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009 Zhang li 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | 22 | MIT License: http://www.opensource.org/licenses/mit-license.php 23 | */ 24 | 25 | /* 26 | Author zhang li 27 | Email zlvbvbzl@gmail.com 28 | */ 29 | 30 | #include "state.h" 31 | #include "error.h" 32 | #include "PuMath.h" 33 | #include 34 | 35 | #ifdef _MSC_VER 36 | #include //for win32 Sleep 37 | #pragma warning(disable:4127) //while(1) 38 | #else 39 | #include //for linux usleep 40 | #endif 41 | 42 | extern void get_var(Pu *L, const std::string *name, __pu_var *&v); 43 | PUAPI{ 44 | PURESULT pu_push_arr(pu_var varr, const pu_var v); 45 | PURESULT pu_loadbuff(Pu *L, const char *str); 46 | void pu_val2str(Pu *, const pu_var *p, char *b, int buffsize); 47 | void pu_set_return_value(Pu *L, const pu_var v); 48 | } 49 | extern int vm(Pu *L); 50 | extern bool check_complete(Pu *L); 51 | extern int findcurstart(Pu *L); 52 | #define bi_return_null {__pu_var None(L); None.SetType(NIL); pu_set_return_value(L, &None);}return; 53 | void bi_return_null_func(Pu *L) 54 | { 55 | bi_return_null; 56 | } 57 | 58 | void bi_return_num( Pu * L, int v ) 59 | { 60 | __pu_var r = __pu_var(L); 61 | r.SetType(NUM); 62 | r.numVal() = v; 63 | pu_set_return_value(L, &r); 64 | } 65 | 66 | void bi_return_int( Pu * L, int v ) 67 | { 68 | __pu_var r = __pu_var(L); 69 | r.SetType(INTEGER); 70 | r.intVal() = v; 71 | pu_set_return_value(L, &r); 72 | } 73 | 74 | const char *get_typestr(__pu_var &v) 75 | { 76 | static const char *type_string[]={ 77 | "", 78 | "", 79 | "", 80 | "", 81 | "", 82 | "", 83 | "", 84 | "", 85 | "", 86 | "", 87 | "", 88 | "", 89 | }; 90 | 91 | return type_string[(int)v.type()-NIL]; 92 | } 93 | 94 | void bi_sleep(Pu *L, int, pu_var *v) 95 | { 96 | if (v == nullptr || v[0]->type() != INTEGER) 97 | { 98 | error(L, 24); 99 | bi_return_null; 100 | } 101 | unsigned long mili = (unsigned long)(v[0]->intVal()); 102 | 103 | #ifdef _WIN32 104 | Sleep(mili); 105 | #else 106 | usleep(mili*1000); 107 | #endif 108 | 109 | bi_return_null; 110 | } 111 | 112 | void bi_get_value_len(Pu *L, int, pu_var *v) 113 | { 114 | if (v == nullptr) 115 | { 116 | error(L, 25); 117 | bi_return_null; 118 | } 119 | 120 | __pu_var r(L); 121 | r.SetType(INTEGER); 122 | if (v[0]->type() == INTEGER) 123 | { 124 | r.intVal() = 1; 125 | } 126 | else if (v[0]->type() == NUM) 127 | { 128 | r.intVal() = 1; 129 | } 130 | else if (v[0]->type() == STR) 131 | { 132 | r.intVal() = (PU_INT)v[0]->strVal().length(); 133 | } 134 | else if (v[0]->type() == ARRAY) 135 | { 136 | r.intVal() = (PU_INT)v[0]->arr().size(); 137 | } 138 | pu_set_return_value(L,&r); 139 | } 140 | 141 | void bi_time(Pu *L, int, pu_var*) 142 | { 143 | time_t ti = time(nullptr); 144 | __pu_var t(L); 145 | t.SetType(INTEGER); 146 | t.intVal() = (PU_INT)ti; 147 | 148 | pu_set_return_value(L, &t); 149 | } 150 | 151 | void bi_date(Pu *L, int, pu_var*) 152 | { 153 | struct tm *local; 154 | time_t ti; 155 | ti=time(nullptr); 156 | local=localtime(&ti); 157 | 158 | __pu_var t(L); 159 | t.SetType(INTEGER); 160 | 161 | __pu_var r(L); 162 | r.createby_ = PU_USER; 163 | 164 | t.intVal() = (PU_INT)local->tm_year+1900; 165 | pu_push_arr(&r, &t); 166 | 167 | t.intVal() = (PU_INT)local->tm_mon; 168 | pu_push_arr(&r, &t); 169 | 170 | t.intVal() = (PU_INT)local->tm_mday; 171 | pu_push_arr(&r, &t); 172 | 173 | t.intVal() = (PU_INT)local->tm_wday; 174 | pu_push_arr(&r, &t); 175 | 176 | t.intVal() = (PU_INT)local->tm_hour; 177 | pu_push_arr(&r, &t); 178 | 179 | t.intVal() = (PU_INT)local->tm_min; 180 | pu_push_arr(&r, &t); 181 | 182 | t.intVal() = (PU_INT)local->tm_sec; 183 | pu_push_arr(&r, &t); 184 | 185 | pu_set_return_value(L, &r); 186 | } 187 | 188 | void bi_quit(Pu *L, int, pu_var *) 189 | { 190 | L->isquit = true; 191 | bi_return_null; 192 | } 193 | 194 | void bi_rand(Pu *L, int, pu_var *) 195 | { 196 | __pu_var r(L); 197 | 198 | srand( (unsigned)time( nullptr ) ); 199 | 200 | int n = rand(); 201 | r.SetType(INTEGER); 202 | r.intVal() = (PU_INT)n; 203 | pu_set_return_value(L,&r); 204 | } 205 | 206 | #define WRITE_STR(s) \ 207 | printf("%s", s->strVal().c_str()); 208 | 209 | 210 | #define WRITE_NUM(n) \ 211 | if (PU_INT(n->numVal()) == n->numVal()) \ 212 | printf("%.lf", n->numVal()); \ 213 | else \ 214 | printf("%lf", n->numVal()); 215 | 216 | #define WRITE_INT(n) \ 217 | printf("%lld", n->intVal()); 218 | 219 | 220 | static void write_arr(const __pu_var &arr) 221 | { 222 | printf("["); 223 | ValueArr::iterator it = arr.arr().begin(); 224 | ValueArr::iterator ite = arr.arr().end(); 225 | while (it != ite) 226 | { 227 | __pu_var temp = *it; 228 | if (temp.type() == INTEGER) 229 | { 230 | WRITE_INT((&temp)); 231 | } 232 | else if (temp.type() == STR) 233 | { 234 | printf("\'"); 235 | WRITE_STR((&temp)); 236 | printf("\'"); 237 | } 238 | else if (temp.type() == NUM) 239 | { 240 | WRITE_NUM((&temp)); 241 | } 242 | else if (temp.type() == ARRAY) 243 | { 244 | write_arr(temp); 245 | } 246 | ++it; 247 | 248 | if (it != ite) 249 | printf(","); 250 | else 251 | break; 252 | } 253 | printf("]"); 254 | } 255 | 256 | void bi_str(Pu *L, int argc, pu_var *v) 257 | { 258 | if (argc == 0) 259 | { 260 | bi_return_null; 261 | } 262 | 263 | if (v[0]->type() != STR) 264 | { 265 | __pu_var o(L); 266 | char buff[65536]; 267 | pu_val2str(L, &v[0], buff, sizeof(buff)); 268 | o.SetType(STR); 269 | o.strVal() = buff; 270 | pu_set_return_value(L, &o); 271 | } 272 | else 273 | { 274 | pu_set_return_value(L, v[0]); 275 | } 276 | } 277 | 278 | void bi_num(Pu *L, int argc, pu_var *v) 279 | { 280 | if (argc == 0 || v[0]->type() != STR) 281 | { 282 | bi_return_null; 283 | } 284 | const char *str = v[0]->strVal().c_str(); 285 | __pu_var o(L); 286 | o.SetType(NUM); 287 | if (is_int(str)) 288 | { 289 | PU_INT nv = atoll(str); 290 | o.numVal() = (PU_NUMBER)nv; 291 | pu_set_return_value(L, v[0]); 292 | } 293 | else if (is_float(str)) 294 | { 295 | PU_NUMBER nv = (PU_NUMBER)atof(str); 296 | o.numVal() = nv; 297 | pu_set_return_value(L, v[0]); 298 | } 299 | } 300 | 301 | void bi_int(Pu *L, int argc, pu_var *v) 302 | { 303 | if (argc == 0 || v[0]->type() != STR) 304 | { 305 | bi_return_null; 306 | } 307 | const char *str = v[0]->strVal().c_str(); 308 | __pu_var o(L); 309 | o.SetType(INTEGER); 310 | if (is_int(str)) 311 | { 312 | PU_INT nv = atoll(str); 313 | o.intVal() = nv; 314 | pu_set_return_value(L, v[0]); 315 | } 316 | else if (is_float(str)) 317 | { 318 | PU_INT nv = (PU_INT)atof(str); 319 | o.intVal() = nv; 320 | pu_set_return_value(L, v[0]); 321 | } 322 | } 323 | 324 | static void writefilehandle(Pu *L, int argc, pu_var *v) 325 | { 326 | FILE *pfile = (FILE*)v[0]->file(); 327 | for (int i = 1; i < argc; ++i) 328 | { 329 | char buff[65536]; 330 | pu_val2str(L, &v[i], buff, sizeof(buff)); 331 | fwrite(buff, sizeof(char), strlen(buff), pfile); 332 | fwrite(" ", sizeof(char), 1, pfile); 333 | } 334 | } 335 | 336 | void bi_write(Pu *L, int argc, pu_var *v) 337 | { 338 | if (v == 0) 339 | { 340 | bi_return_null; 341 | } 342 | 343 | if (v[0]->type() == FILEHANDLE) 344 | { 345 | writefilehandle(L,argc,v); 346 | } 347 | else 348 | { 349 | for (int i = 0; i < argc; ++i) 350 | { 351 | if (v[i]->type() == INTEGER) 352 | { 353 | WRITE_INT(v[i]); 354 | } 355 | else if (v[i]->type() == NUM) 356 | { 357 | WRITE_NUM(v[i]); 358 | } 359 | else if (v[i]->type() == STR) 360 | { 361 | WRITE_STR(v[i]); 362 | } 363 | else if (v[i]->type() == ARRAY) 364 | { 365 | write_arr(*v[i]); 366 | } 367 | else if (v[i]->type() == BOOLEANT) 368 | { 369 | printf((v[i]->intVal() != 0)?"true":"false"); 370 | } 371 | else 372 | { 373 | printf("%s", get_typestr(*v[i])); 374 | } 375 | } 376 | } 377 | bi_return_null; 378 | } 379 | 380 | void bi_writeln(Pu *L, int argc, pu_var *v) 381 | { 382 | if (v == 0) 383 | { 384 | bi_return_null; 385 | } 386 | 387 | if (v[0]->type() == FILEHANDLE) 388 | { 389 | writefilehandle(L, argc, v); 390 | } 391 | else 392 | { 393 | for (int i = 0; i < argc; ++i) 394 | { 395 | if (v[i]->type() == INTEGER) 396 | { 397 | WRITE_INT(v[i]); 398 | } 399 | else if (v[i]->type() == NUM) 400 | { 401 | WRITE_NUM(v[i]); 402 | } 403 | else if (v[i]->type() == STR) 404 | { 405 | WRITE_STR(v[i]); 406 | } 407 | else if (v[i]->type() == ARRAY) 408 | { 409 | write_arr(*v[i]); 410 | } 411 | else if (v[i]->type() == BOOLEANT) 412 | { 413 | printf((v[i]->intVal() != 0) ? "true" : "false"); 414 | } 415 | else 416 | { 417 | printf("%s", get_typestr(*v[i])); 418 | } 419 | } 420 | } 421 | putchar('\n'); 422 | bi_return_null; 423 | } 424 | 425 | 426 | void bi_get_var(Pu *L, int argn, pu_var *v) 427 | { 428 | __pu_var *temp = nullptr; 429 | if (argn > 0) 430 | { 431 | if (v[0]->type() == STR) 432 | { 433 | get_var(L, v[0]->strVal().pbuff, temp); 434 | CHECK_EXP(temp); 435 | } 436 | } 437 | pu_set_return_value(L, temp); 438 | } 439 | 440 | void bi_type(Pu *L, int argn, pu_var *v) 441 | { 442 | __pu_var o(L); 443 | o.SetType(STR); 444 | if (argn > 0) 445 | { 446 | o.strVal() = get_typestr(*v[0]); 447 | } 448 | else 449 | { 450 | o.strVal() = ""; 451 | } 452 | pu_set_return_value(L,&o); 453 | } 454 | 455 | // 删除尾部的废代码 456 | static void clear_tailcode(Pu *L, int evstart) 457 | { 458 | L->cur_token = L->callstack.top(); 459 | L->callstack.pop(); 460 | L->lasterr = -1; 461 | int max_token = L->tokens.size(); 462 | for (int i = 0; i < max_token - evstart; ++i) 463 | { 464 | L->tokens.pop_back(); 465 | } 466 | } 467 | 468 | int do_string(Pu *L, const char *str) 469 | { 470 | if (L->mode == PU_CODE_FROM_FILE) 471 | L->mode = PU_CODE_FROM_BUFF; 472 | L->callstack.push(L->cur_token); 473 | PURESULT load_result = pu_loadbuff(L, str); 474 | int evstart = findcurstart(L); 475 | 476 | if (load_result == PU_FAILED) 477 | { 478 | if (L->lasterr >=0 && L->lasterr != 26) 479 | { 480 | clear_tailcode(L, evstart); 481 | L->mode = PU_CODE_FROM_FILE; 482 | return 0; 483 | } 484 | } 485 | 486 | if (!check_complete(L)) 487 | { 488 | // 代码未结尾,去掉最后的FINISH 489 | L->tokens.pop_back(); 490 | L->cur_token = L->callstack.top(); 491 | L->callstack.pop(); 492 | return -2; 493 | } 494 | else 495 | { 496 | L->cur_token = evstart; 497 | NEXT_TOKEN 498 | int ret = vm(L); 499 | L->cur_token = L->callstack.top(); 500 | L->callstack.pop(); 501 | L->lasterr = -1; 502 | L->mode = PU_CODE_FROM_FILE; 503 | return ret; 504 | } 505 | } 506 | 507 | void bi_eval(Pu *L, int argc, pu_var *v) 508 | { 509 | if (argc==0) 510 | { 511 | bi_return_null; 512 | } 513 | do_string(L, v[0]->strVal().c_str()); 514 | bi_return_null; 515 | } 516 | 517 | void bi_open(Pu *L, int argc, pu_var *v) 518 | { 519 | if (argc==0) 520 | { 521 | bi_return_null; 522 | } 523 | 524 | __pu_var r(L); 525 | FILE *p = fopen(v[0]->strVal().c_str(), "a+"); 526 | if (p == nullptr) 527 | { 528 | r.SetType(NIL); 529 | } 530 | else 531 | { 532 | r.SetType(FILEHANDLE); 533 | r.file() = p; 534 | } 535 | pu_set_return_value(L, &r); 536 | } 537 | 538 | void bi_close(Pu *L, int argc, pu_var *v) 539 | { 540 | if (argc==0) return; 541 | if (v[0]->file()) 542 | { 543 | fclose((FILE*)v[0]->file()); 544 | } 545 | bi_return_null; 546 | } 547 | 548 | static void readfilehandle(Pu *L, pu_var *vrr) 549 | { 550 | FILE *pfile = (FILE*)vrr[0]->file(); 551 | 552 | size_t pos = ftell(pfile); 553 | fseek(pfile, 0, SEEK_END); 554 | size_t fsize = ftell(pfile); 555 | fseek(pfile, pos, SEEK_SET); 556 | 557 | char *buff = (char*)malloc(fsize); 558 | if (vrr[1]->strVal() == "max") 559 | { 560 | fread(buff, fsize, 1, pfile); 561 | buff[fsize] = 0; 562 | } 563 | else if (vrr[1]->strVal() == "line") 564 | { 565 | fgets(buff, fsize, pfile); 566 | size_t len = strlen(buff); 567 | if (buff[len-1] == '\n') 568 | { 569 | buff[ - 1] = '\0'; 570 | } 571 | } 572 | else if (vrr[1]->strVal() == "word") 573 | { 574 | int n = fscanf(pfile, "%s", buff); 575 | if (n == EOF) 576 | { 577 | buff[0] = '\0'; 578 | } 579 | } 580 | 581 | __pu_var r(L); 582 | r.SetType(STR); 583 | r.strVal() = buff; 584 | pu_set_return_value(L, &r); 585 | free(buff); 586 | } 587 | 588 | void bi_read(Pu *L, int argc, pu_var *vrr) 589 | { 590 | if (argc == 0) 591 | { 592 | char temp[1024]; 593 | fgets(temp, sizeof(temp), stdin); 594 | temp[strlen(temp) - 1] = '\0'; 595 | __pu_var v(L); 596 | 597 | if (is_int(temp)) 598 | { 599 | PU_INT nv = atoll(temp); 600 | v.SetType(INTEGER); 601 | v.intVal() = nv; 602 | } 603 | else if (is_float(temp)) 604 | { 605 | PU_NUMBER nv = (PU_NUMBER)atof(temp); 606 | v.SetType(NUM); 607 | v.numVal() = nv; 608 | } 609 | else 610 | { 611 | v.SetType(STR); 612 | v.strVal() = temp; 613 | } 614 | 615 | pu_set_return_value(L,&v); 616 | } 617 | else if (argc > 1 && vrr[0]->type() == FILEHANDLE && vrr[1]->type() == STR) 618 | { 619 | readfilehandle(L,vrr); 620 | } 621 | } 622 | -------------------------------------------------------------------------------- /src/bytecode.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009 Zhang li 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | 22 | MIT License: http://www.opensource.org/licenses/mit-license.php 23 | */ 24 | 25 | /* 26 | Author zhang li 27 | Email zlvbvbzl@gmail.com 28 | */ 29 | 30 | #include "state.h" 31 | #include 32 | #include 33 | 34 | extern void append_token(Pu *L, Token &t); 35 | extern void parse_include(Pu *L, const Token &filename); 36 | extern void parse_function(Pu *L, int token_from, FILE *pbcf, TokenList *tl); 37 | extern Token get_token_from_file(Pu *L, TokenList *t); 38 | extern bool check_complete(Pu *L); 39 | extern void parse_function_body(Pu *L, 40 | int ldef, 41 | int token_from, 42 | Token &t, 43 | FILE *pbcf=0, 44 | TokenList *tl=0); 45 | 46 | static void save_token(FILE *pbcf, TokenList &tokens) 47 | { 48 | TokenList::iterator it = tokens.begin(); 49 | TokenList::iterator ite = tokens.end(); 50 | while (it != ite) 51 | { 52 | int ctp = it->type; 53 | fwrite(&ctp, sizeof(ctp), 1, pbcf); 54 | switch (it->type) 55 | { 56 | case INTEGER: 57 | fwrite(&it->literal_value->intVal(), sizeof(it->literal_value->intVal()), 1, pbcf); 58 | break; 59 | case NUM: 60 | fwrite(&it->literal_value->numVal(), sizeof(it->literal_value->numVal()), 1, pbcf); 61 | break; 62 | case OP:{ 63 | char cop = (char)it->optype; 64 | fwrite(&cop, sizeof(cop), 1, pbcf); 65 | }break; 66 | case VAR:{ 67 | char sl = (char)it->name->length(); 68 | fwrite(&sl, sizeof(sl), 1, pbcf); 69 | fwrite(it->name->c_str(), sl, 1, pbcf); 70 | }break; 71 | case STR:{ 72 | size_t sl = it->literal_value->strVal().length(); 73 | fwrite(&sl, sizeof(size_t), 1, pbcf); 74 | fwrite(it->literal_value->strVal().c_str(), it->literal_value->strVal().length(), 1, pbcf); 75 | }break; 76 | default: 77 | break; 78 | } 79 | fwrite(&it->line, sizeof(it->line), 1, pbcf); 80 | ++it; 81 | } 82 | } 83 | 84 | void savebytecode(Pu *, const char *fname, TokenList &tokensave) 85 | { 86 | FILE *pbcf = fopen(fname, "wb"); 87 | time_t ti; 88 | ti = time(nullptr); 89 | fwrite(&ti, sizeof(ti), 1, pbcf); 90 | save_token(pbcf, tokensave); 91 | fclose(pbcf); 92 | } 93 | 94 | void get_nextbytetoken(Pu *L, FILE *pbcf, Token &t) 95 | { 96 | int type = UNKNOWN; 97 | bool needinclude = false; 98 | for (;;) 99 | { 100 | if (fread(&type, sizeof(char), 1, pbcf)) 101 | { 102 | t.type = (PuType)type; 103 | t.line = 0; 104 | 105 | switch (type) 106 | { 107 | case INTEGER:{ 108 | PU_INT number = 0; 109 | fread(&number, sizeof(number), 1, pbcf); 110 | t.literal_value = get_int_literal(L, number); 111 | } break; 112 | 113 | case NUM:{ 114 | PU_NUMBER number = 0; 115 | fread(&number, sizeof(number), 1, pbcf); 116 | t.literal_value = get_num_literal(L, number); 117 | } break; 118 | 119 | case OP:{ 120 | char cop = 0; 121 | fread(&cop, sizeof(cop), 1, pbcf); 122 | t.optype = (OperatorType)cop; 123 | } break; 124 | 125 | case VAR:{ 126 | char l = 0; 127 | fread(&l,sizeof(l),1,pbcf); 128 | char *c = (char*)malloc(l + 1); 129 | memset(c,0,l+1); 130 | fread(c, 1, l, pbcf); 131 | t.name = InsertStrPool(L, c); 132 | free(c); 133 | } break; 134 | 135 | case STR:{ 136 | size_t l = 0; 137 | fread(&l, sizeof(l), 1, pbcf); 138 | char *c = (char*)malloc(l + 1); 139 | fread(c, 1, l, pbcf); 140 | c[l] = 0; 141 | t.literal_value = get_str_literal(L, c); 142 | free(c); 143 | } break; 144 | } 145 | t.filename = L->current_filename.back(); 146 | fread(&t.line, sizeof(t.line), 1, pbcf); 147 | append_token(L,t); 148 | } 149 | 150 | if (type != KW_INCLUDE) 151 | { 152 | break; 153 | } 154 | else 155 | { 156 | needinclude = true; 157 | } 158 | } 159 | 160 | if (needinclude) 161 | { 162 | parse_include(L, t); 163 | } 164 | else if (type == KW_FUNCTION) 165 | { 166 | parse_function(L, FROM_BYTECODE, pbcf, 0); 167 | } 168 | } 169 | 170 | static void get_token_from_bytecode(Pu *L, FILE *pbcf) 171 | { 172 | for (;;) 173 | { 174 | Token t; 175 | t.type = UNKNOWN; 176 | get_nextbytetoken(L,pbcf, t); 177 | if (t.type == FINISH) 178 | break; 179 | } 180 | } 181 | 182 | PUAPI void pu_getbytecodename(char *bytecodename, 183 | const char *csource_code_name) 184 | { 185 | size_t i = strlen(csource_code_name) - 1; 186 | for ( ; i != 0; --i) 187 | { 188 | if (csource_code_name[i] == '.') 189 | { 190 | break; 191 | } 192 | } 193 | 194 | memcpy(bytecodename, csource_code_name, i); 195 | memcpy(bytecodename + i, ".puc", 5); 196 | } 197 | 198 | 199 | PUAPI int pu_loadbytecode(Pu *L, const char *fname) 200 | { 201 | FILE *pbcf = fopen(fname, "rb"); 202 | if (!pbcf) 203 | return 0; 204 | 205 | time_t ti; 206 | fread(&ti, sizeof(ti), 1, pbcf); 207 | 208 | struct stat buf; 209 | char sfn[1024] = {0}; 210 | strncpy(sfn, fname, strlen(fname)-1); 211 | if (stat( sfn ,&buf) != 0) 212 | { 213 | fclose(pbcf); 214 | return 0; 215 | } 216 | else if (buf.st_mtime > ti) 217 | { 218 | fclose(pbcf); 219 | return 0; 220 | } 221 | L->current_filename.push_back(InsertStrPool(L, fname)); 222 | get_token_from_bytecode(L, pbcf); 223 | L->current_filename.pop_back(); 224 | fclose(pbcf); 225 | return 1; 226 | } 227 | 228 | PUAPI PURESULT pu_load(Pu *L, const char *sname) 229 | { 230 | size_t sname_index_max = strlen(sname)-1; 231 | for ( ; sname_index_max != 0; --sname_index_max) 232 | { 233 | if (sname[sname_index_max] == '.') 234 | break; 235 | } 236 | 237 | if (strcmp(&(sname[sname_index_max]), ".puc") == 0) 238 | { 239 | return (PURESULT)pu_loadbytecode(L, sname); 240 | } 241 | 242 | L->source.pf = fopen(sname, "r"); 243 | L->source.type = Pusource::ST_FILE; 244 | if (L->source.pf == nullptr) 245 | { 246 | return PU_FAILED; 247 | } 248 | 249 | L->current_filename.push_back(InsertStrPool(L, sname)); 250 | 251 | if (L->tokens.size() > 0 && L->tokens.back().type == FINISH) 252 | { 253 | if (L->cur_token == (int)L->tokens.size() - 1) 254 | { 255 | L->cur_token--; 256 | } 257 | L->tokens.pop_back(); 258 | } 259 | 260 | TokenList t; 261 | Token temp; 262 | do 263 | { 264 | temp = get_token_from_file(L, &t); 265 | CHECKTOKENERROR PU_FAILED; 266 | }while(temp.type != FINISH); 267 | fclose(L->source.pf); 268 | L->source.pf = nullptr; 269 | 270 | if (!check_complete(L)) 271 | { 272 | return PU_FAILED; 273 | } 274 | 275 | char bname[1024]={0}; 276 | if (sname_index_max + 1 > sizeof(bname)) 277 | { 278 | return PU_FAILED; 279 | } 280 | pu_getbytecodename(bname, sname); 281 | savebytecode(L, bname, t); 282 | t.clear(); 283 | L->cur_token = 0; 284 | L->current_filename.pop_back(); 285 | L->jumpstack.release(); 286 | return PU_SUCCESS; 287 | } 288 | 289 | 290 | PUAPI PURESULT pu_loadbuff(Pu *L, const char *str) 291 | { 292 | if (str == nullptr) 293 | { 294 | return PU_FAILED; 295 | } 296 | 297 | const char *buffname = ""; 298 | L->current_filename.push_back(InsertStrPool(L, buffname)); 299 | L->source.type = Pusource::ST_BUFFER; 300 | L->source.str.buff = str; 301 | L->source.str.pos = 0; 302 | 303 | Token temp = get_token_from_file(L,nullptr); 304 | while(L->tokens[L->tokens.size()-1].type != FINISH) { 305 | if (L->funstack.size() > 0 && L->funstack.back() >= 1)// 如果有函数未结束,继续获取函数内容 306 | parse_function_body(L,L->uncomdef.top(), 307 | FROM_SOURCECODE, temp, 308 | nullptr,nullptr); 309 | else 310 | temp = get_token_from_file(L,nullptr); 311 | CHECKTOKENERROR PU_FAILED; 312 | } 313 | L->source.str.buff = nullptr; 314 | L->source.str.pos = 0; 315 | L->cur_token = 0; 316 | L->current_filename.pop_back(); 317 | return PU_SUCCESS; 318 | } 319 | 320 | 321 | PUAPI void pu_makebytecode(Pu *L, const char *sname) 322 | { 323 | pu_load(L, sname); 324 | L->cur_token = 0; 325 | char codename[1024]={0}; 326 | pu_getbytecodename(codename, sname); 327 | TokenList t; 328 | do 329 | { 330 | NEXT_TOKEN; 331 | t.push_back(TOKEN); 332 | }while(TOKEN.type != FINISH); 333 | savebytecode(L,codename,t); 334 | } 335 | -------------------------------------------------------------------------------- /src/config.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009 Zhang li 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | 22 | MIT License: http://www.opensource.org/licenses/mit-license.php 23 | */ 24 | 25 | /* 26 | Author zhang li 27 | Email zlvbvbzl@gmail.com 28 | */ 29 | 30 | #include 31 | 32 | typedef int64_t PU_INT; 33 | typedef double PU_FLOAT; 34 | 35 | typedef PU_FLOAT PU_NUMBER; 36 | 37 | #define PU_MAXVARLEN 1024 38 | #define PU_MAXCFUNCARGNUM 32 39 | #define _DEBUG_MEM 1 40 | 41 | 42 | #if defined(_MSC_VER) 43 | #define GC_LEVEL 1 44 | #if defined(_DEBUG) 45 | #if _DEBUG_MEM == 1 46 | #include 47 | #define new new(_NORMAL_BLOCK, __FILE__, __LINE__) 48 | #endif 49 | #endif 50 | #else 51 | #define GC_LEVEL 1024 52 | #endif -------------------------------------------------------------------------------- /src/coroutine.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009 Zhang li 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | 22 | MIT License: http://www.opensource.org/licenses/mit-license.php 23 | */ 24 | 25 | /* 26 | Author zhang li 27 | Email zlvbvbzl@gmail.com 28 | */ 29 | 30 | #include "def.h" 31 | #include "value.h" 32 | #include "state.h" 33 | #include "error.h" 34 | 35 | PUAPI void pu_set_return_value(Pu *L, pu_var v); 36 | extern int vm(Pu *L); 37 | extern void bi_return_int( Pu * L, int v ); 38 | void bi_coro_create(Pu *L, int argnum, pu_var *v) 39 | { 40 | if (argnum == 0) 41 | { 42 | return; 43 | } 44 | 45 | if (v[0]->type() != STR && v[0]->type() != FUN) 46 | { 47 | return; 48 | } 49 | 50 | FuncPos &fps = L->funclist[(int)v[0]->intVal()]; 51 | 52 | const FunArgs &args = fps.argnames; 53 | 54 | if (argnum - 1 != (int)args.size()) 55 | { 56 | error(L,27); 57 | return; 58 | } 59 | 60 | if (fps.start == -1) 61 | { 62 | return; 63 | } 64 | else 65 | { 66 | StrKeyMap *newvarmap = new StrKeyMap; 67 | 68 | int i=0; 69 | 70 | for (; i < argnum - 1; ++i)// ) 71 | { 72 | newvarmap->insert(std::make_pair(args[i], *(v[i+1]))); 73 | } 74 | coro c; 75 | c.begin = fps.start; 76 | c.end = fps.end; 77 | c.cur = c.begin; 78 | c.funpos = (int)v[0]->intVal(); 79 | c.varmap = newvarmap; 80 | c.id = L->coros.size(); 81 | L->coros.push_back(c); 82 | __pu_var retv(L); 83 | retv.SetType(CORO); 84 | retv.intVal() = (PU_INT)L->coros.size()-1; 85 | pu_set_return_value(L, &retv); 86 | } 87 | } 88 | 89 | void run_coro( Pu * L, int coro_id, __pu_var * corov ); 90 | 91 | void bi_coro_resume(Pu *L, int argnum, pu_var *v) 92 | { 93 | int coro_id = 0; 94 | __pu_var *corov = nullptr; 95 | if (argnum == 0) 96 | { 97 | coro_id = rand() % L->coros.size(); 98 | } 99 | else 100 | { 101 | corov = v[0]; 102 | if (corov->type() != CORO) 103 | { 104 | bi_return_int(L, -1); 105 | return; 106 | } 107 | coro_id = int(corov->intVal()); 108 | } 109 | 110 | if (coro_id < 0 || coro_id >= (int)L->coros.size()) 111 | { 112 | return; 113 | } 114 | 115 | run_coro(L, coro_id, corov); 116 | return; 117 | } 118 | 119 | void bi_coro_yield(Pu *L, int, pu_var *) 120 | { 121 | L->isyield = true; 122 | } 123 | 124 | void run_coro( Pu *L, int coro_id, __pu_var *corov ) 125 | { 126 | coro &c = L->coros[coro_id]; 127 | 128 | if (c.cur == c.end) 129 | { 130 | bi_return_int(L, 0); 131 | return; 132 | } 133 | 134 | L->varstack.push(c.varmap); 135 | L->callstack.push(L->cur_token); 136 | L->isreturn.push(0); 137 | L->cur_token = c.cur; 138 | NEXT_TOKEN; 139 | 140 | if (c.cur != c.begin) 141 | { 142 | PREV_TOKEN; 143 | } 144 | 145 | vm(L); 146 | L->varstack.pop(); 147 | c.cur = L->cur_token; 148 | L->cur_token = L->callstack.top(); 149 | L->callstack.pop(); 150 | L->isreturn.pop(); 151 | 152 | __pu_var r = __pu_var(L); 153 | r.SetType(INTEGER); 154 | if (L->isyield) 155 | { 156 | r.intVal() = 1; 157 | coro cbak = L->coros[coro_id]; 158 | L->coros[coro_id] = L->coros.back(); 159 | L->coros.back() = cbak; 160 | } 161 | else 162 | { 163 | r.intVal() = 0; 164 | if (corov) 165 | { 166 | corov->intVal() = -1; 167 | } 168 | delete c.varmap; 169 | c.varmap = nullptr; 170 | L->coros.erase(L->coros.begin() + coro_id); 171 | } 172 | pu_set_return_value(L, &r); 173 | L->isyield = false; 174 | } 175 | 176 | 177 | 178 | -------------------------------------------------------------------------------- /src/def: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zlvb/PuppyLanguage/961a579c492911e5ada82ce6f0a461155ef393de/src/def -------------------------------------------------------------------------------- /src/def.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009 Zhang li 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | 22 | MIT License: http://www.opensource.org/licenses/mit-license.php 23 | */ 24 | 25 | /* 26 | Author zhang li 27 | Email zlvbvbzl@gmail.com 28 | */ 29 | 30 | #ifndef __VM_DEF_H__ 31 | #define __VM_DEF_H__ 32 | 33 | #include "config.h" 34 | 35 | struct Pu; 36 | struct Token; 37 | struct __pu_var; 38 | typedef __pu_var* pu_var; 39 | struct FuncPos; 40 | 41 | #define PUAPI extern "C" 42 | 43 | // 可以让脚本调用的函数类型 44 | typedef void (*ScriptFunc)(Pu*, int arg_num, pu_var*); 45 | 46 | // 错误处理回调 47 | typedef void (*ErrHandle)(int err, const char *err_str); 48 | 49 | // 处理输出的回调 50 | typedef void (*OutputHandle)(const char *str); 51 | 52 | #define QUIT_SCRIPT {L->isquit=true; L->cur_token = L->tokens.size() - 1;NEXT_TOKEN} 53 | #define TOKEN (*(L->token)) 54 | #define NEXT_TOKEN {L->token = &(L->tokens[L->cur_token++]);} 55 | #define NEXT_TOKEN_N(n) assert(n!=0);{L->token = &(L->tokens[L->cur_token+n-1]);L->cur_token+=n;} 56 | #define PREV_TOKEN {L->cur_token-=2;NEXT_TOKEN;} 57 | #define PREV_TOKEN_N(n) {L->cur_token-=1+n;NEXT_TOKEN;} 58 | #define SET_TOKEN(pos) {L->cur_token=pos-1; NEXT_TOKEN;} 59 | // 操作结果 60 | typedef enum PURESULT { 61 | PU_FAILED = -1,// 失败 62 | PU_SUCCESS = 0// 成功 63 | }PURESULT; 64 | 65 | #ifdef _MSC_VER 66 | #define PU_SNPRINTF(dest, size, fmt, ...) _snprintf(dest, size, fmt, __VA_ARGS__) 67 | #else 68 | #define PU_SNPRINTF(dest, size, fmt, ...) snprintf(dest, size, fmt, __VA_ARGS__) 69 | #endif 70 | 71 | #define MAKE_TEMP_VALUE(p) \ 72 | if (L->tempool.size() > 0)\ 73 | {\ 74 | p = L->tempool.back();\ 75 | L->tempool.pop_back();\ 76 | }\ 77 | else\ 78 | {\ 79 | p = new __pu_var(L);\ 80 | } \ 81 | L->tempvals.push_back(p); 82 | 83 | #define CHECK_EXP(v) \ 84 | if (!v || v->type() == UNKNOWN)\ 85 | {\ 86 | error(L, 7);\ 87 | return;\ 88 | } 89 | 90 | #define CHECK_EXP_RETURN(v, r) \ 91 | if (!v || v->type() == UNKNOWN)\ 92 | {\ 93 | error(L, 7);\ 94 | return r;\ 95 | } 96 | 97 | #define CHECK_EXP_CONTINUE(v) \ 98 | if (!v || v->type() == UNKNOWN)\ 99 | {\ 100 | error(L, 7);\ 101 | continue;\ 102 | } 103 | 104 | #define CHECK_EXP_RETURNERR(v) \ 105 | if (!v || v->type() == UNKNOWN)\ 106 | {\ 107 | error(L, 7);\ 108 | __pu_var *_r = nullptr;\ 109 | MAKE_TEMP_VALUE(_r);\ 110 | return _r;\ 111 | } 112 | #endif -------------------------------------------------------------------------------- /src/error.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009 Zhang li 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | 22 | MIT License: http://www.opensource.org/licenses/mit-license.php 23 | */ 24 | 25 | /* 26 | Author zhang li 27 | Email zlvbvbzl@gmail.com 28 | */ 29 | 30 | #include "error.h" 31 | #include "state.h" 32 | 33 | void error(Pu *L, const char *err_msg, int line) 34 | { 35 | if (line) 36 | { 37 | printf("error: %s\nlines: %d\n", err_msg, line); 38 | } 39 | else if (L && L->token && TOKEN.line > 0) 40 | { 41 | printf("error: %s\nlines: %d\nfile: %s\n", err_msg, TOKEN.line, TOKEN.filename->c_str()); 42 | } 43 | else 44 | { 45 | printf("error: %s\n", err_msg); 46 | } 47 | 48 | #if defined(_DEBUG) && defined(_MSC_VER) 49 | _asm {int 3} 50 | #endif 51 | QUIT_SCRIPT; 52 | } 53 | 54 | void error(Pu *L, int id, int line) 55 | { 56 | L->lasterr = id; 57 | if (L->err_handle) 58 | { 59 | L->err_handle(id, geterrcode(id)); 60 | QUIT_SCRIPT; 61 | } 62 | else 63 | { 64 | error(L, geterrcode(id), line); 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /src/error.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009 Zhang li 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | 22 | MIT License: http://www.opensource.org/licenses/mit-license.php 23 | */ 24 | 25 | /* 26 | Author zhang li 27 | Email zlvbvbzl@gmail.com 28 | */ 29 | 30 | #ifndef _ERROR_H_ 31 | #define _ERROR_H_ 32 | 33 | struct Pu; 34 | 35 | static const char *errtable[] = { 36 | "\" mismatched",//0 37 | "() mismatched",//1 38 | "only the array and string can be accessed by index",//2 39 | "index must be a integer",//3 40 | "[] mismatched",//4 41 | "array index overflow",//5 42 | "invalid type, modify the string failure",//6 43 | "unknown identifiers",//7 44 | "read operator does not specify the variable name",//8 45 | "only digital can subtraction between",//9 46 | "only digital can divide between",//10 47 | "only digital can mod between",//11 48 | "digital can not be multiplied by string",//12 49 | "value can not be compared",//13 50 | "unsupported operation",//14 51 | "function can not nested",//15 52 | "undefined label",//16 53 | "keyword \'end\' mismatched",//17 54 | "function redefined",//18 55 | "include recursive",//19 56 | "can not open file",//20 57 | "invalid argument's type",//21 58 | "can not modify the const value", //22 59 | "a number is required", //23 60 | "a string is required", //24 61 | "requires arguments", //25 62 | "keyword \'end\' mismatched", //26 63 | "function have got wrong number of arguments",// 27 64 | "identifier is too long",//28 65 | "syntax error", // 29 66 | "only number and string can calc hash", // 30 67 | "key must be a number or a string",//31 68 | "key not exist",//32 69 | "can not return while out of function",//33 70 | "count of function arguments is invalid",//34 71 | "number division by zero",//35 72 | "the type is not iterable",//36 73 | "for/function/while/end is not matched correctly",//37 74 | }; 75 | 76 | 77 | inline const char *geterrcode(int id) 78 | { 79 | return errtable[id]; 80 | } 81 | 82 | void error(Pu *L, const char *err_msg, int line = 0); 83 | void error(Pu *L, int err_id, int line = 0); 84 | 85 | #endif 86 | -------------------------------------------------------------------------------- /src/gc.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009 Zhang li 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | 22 | MIT License: http://www.opensource.org/licenses/mit-license.php 23 | */ 24 | 25 | /* 26 | Author zhang li 27 | Email zlvbvbzl@gmail.com 28 | */ 29 | 30 | #include "state.h" 31 | 32 | static void mark(StrKeyMap *global_vmap); 33 | static void mark(_scope *scope); 34 | static void mark(__pu_var &v) 35 | { 36 | if (v.type() == FUN) 37 | { 38 | _scope *uv = &v.up_value(); 39 | if (uv && !uv->base_->marked) 40 | { 41 | uv->base_->marked = true; 42 | mark(uv); 43 | } 44 | } 45 | } 46 | 47 | void mark(StrKeyMap *global_vmap) 48 | { 49 | for (auto &pair : *global_vmap) 50 | { 51 | mark(pair.second); 52 | } 53 | } 54 | 55 | void mark(_scope *scope) 56 | { 57 | for (auto &pair : *scope->base_->vmap_) 58 | { 59 | mark(pair.second); 60 | } 61 | } 62 | 63 | void sweep(Pu *L) 64 | { 65 | L->start_gc = true; 66 | auto it = L->gccontainer.begin(); 67 | auto itend = L->gccontainer.end(); 68 | while (it != itend) 69 | { 70 | if (!(*it)->marked) 71 | { 72 | L->garbage.insert(*it); 73 | it = L->gccontainer.erase(it); 74 | } 75 | else 76 | { 77 | (*it)->marked = false; 78 | ++it; 79 | } 80 | } 81 | 82 | while (L->garbage.size() > 0) 83 | { 84 | for (auto ptr : L->garbage) 85 | { 86 | for (auto &pair : *ptr->vmap_) 87 | { 88 | __pu_var &var = pair.second; 89 | if (var.type() == FUN) 90 | { 91 | _scope &uv = var.up_value(); 92 | if (L->garbage.find(uv.base_) != L->garbage.end()) 93 | { 94 | uv.base_ = nullptr; // release circular reference 95 | } 96 | } 97 | } 98 | } 99 | auto itg = L->garbage.begin(); 100 | delete (*itg); 101 | L->garbage.erase(itg); 102 | } 103 | L->start_gc = false; 104 | } 105 | 106 | void gc(Pu *L) 107 | { 108 | StrKeyMap *root = L->varstack.bottom(); 109 | mark(root); 110 | sweep(L); 111 | } 112 | 113 | void clear_temp(Pu *L) 114 | { 115 | for (auto &v : L->tempvals) 116 | { 117 | L->tempool.push_back(v); 118 | } 119 | L->tempvals.clear(); 120 | } 121 | 122 | void add_to_gc(Pu *L, _scope::_smap *vmap) 123 | { 124 | L->gccontainer.insert(vmap); 125 | } 126 | 127 | void remove_from_gc(Pu *L, _scope::_smap *vmap) 128 | { 129 | L->gccontainer.erase(vmap); 130 | } 131 | -------------------------------------------------------------------------------- /src/global.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009 Zhang li 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | 22 | MIT License: http://www.opensource.org/licenses/mit-license.php 23 | */ 24 | 25 | /* 26 | Author zhang li 27 | Email zlvbvbzl@gmail.com 28 | */ 29 | 30 | #include "global.h" 31 | 32 | const char *OPERATOR_CHARS = "+-*/<>!=()|&%[],{}:"; 33 | const char *KEYWORDS[] = {"while", "end", "if", "else", 34 | "break", "goto", "def", "return", 35 | "include", "continue", "elif", "null", "false", "true", "var", "for", "in"}; 36 | 37 | 38 | const char SPACE_TYPES[] = {' ', '\t', '\n', '\r'}; 39 | 40 | const char *OPERATORS[OPT_COUNT] = {}; 41 | 42 | static int init_operator() 43 | { 44 | OPERATORS[OPT_ADD] = "+";//0 45 | OPERATORS[OPT_SUB] = "-";//1 46 | OPERATORS[OPT_MUL] = "*";//2 47 | OPERATORS[OPT_DIV] = "/";//3 48 | OPERATORS[OPT_GT] = ">";//4 49 | OPERATORS[OPT_LT] = "<";//5 50 | OPERATORS[OPT_SET] = "=";//6 51 | OPERATORS[OPT_EQ] = "==";//7 52 | OPERATORS[OPT_GTA] = ">=";//8 53 | OPERATORS[OPT_LTA] = "<=";//9 54 | OPERATORS[OPT_NEQ] = "!=";//10 55 | OPERATORS[OPT_LB] = "(";//11 56 | OPERATORS[OPT_RB] = ")";//12 57 | OPERATORS[OPT_OR] = "||";//13 58 | OPERATORS[OPT_AND] = "&&";//14 59 | OPERATORS[OPT_MOD] = "%";//15 60 | OPERATORS[OPT_LSB] = "[";//16 61 | OPERATORS[OPT_RSB] = "]";//17 62 | OPERATORS[OPT_COM] = ",";//18 63 | OPERATORS[OPT_LBR] = "{";//19 64 | OPERATORS[OPT_RBR] = "}";//20 65 | OPERATORS[OPT_ADDS] = "+=";//21 66 | OPERATORS[OPT_SUBS] = "-=";//22 67 | OPERATORS[OPT_NOT] = "!";//23 68 | OPERATORS[OPT_MULS] = "*=";//24 69 | OPERATORS[OPT_DIVS] = "/=";//25 70 | OPERATORS[OPT_COL] = ":";//26 71 | OPERATORS[OPT_SEM] = ";";//28 72 | return 0; 73 | }; 74 | 75 | static int init_op = init_operator(); -------------------------------------------------------------------------------- /src/global.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009 Zhang li 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | 22 | MIT License: http://www.opensource.org/licenses/mit-license.php 23 | */ 24 | 25 | /* 26 | Author zhang li 27 | Email zlvbvbzl@gmail.com 28 | */ 29 | 30 | #ifndef __GLOBAL_H_ 31 | #define __GLOBAL_H_ 32 | 33 | #include "config.h" 34 | #include 35 | 36 | #define KEYWORDS_TYPES_LENGTH 17 37 | #define OPERATOR_TYPES_LENGTH 28 38 | #define SPACE_TYPES_LENGTH 4 39 | 40 | extern const char SPACE_TYPES[]; 41 | extern const char *KEYWORDS[]; 42 | extern const char *OPERATORS[]; 43 | extern const char *OPERATOR_CHARS; 44 | 45 | enum OperatorType 46 | { 47 | OPT_ADD, 48 | OPT_SUB, 49 | OPT_MUL, 50 | OPT_DIV, 51 | OPT_GT, 52 | OPT_LT, 53 | OPT_SET, 54 | OPT_EQ, 55 | OPT_GTA, 56 | OPT_LTA, // <= 57 | OPT_NEQ, // != 58 | OPT_LB, // ( 59 | OPT_RB, // ) 60 | OPT_OR, 61 | OPT_AND, 62 | OPT_MOD, 63 | OPT_LSB, // [ 64 | OPT_RSB, // ] 65 | OPT_COM, // , 66 | OPT_LBR, // { 67 | OPT_RBR, // } 68 | OPT_ADDS, 69 | OPT_SUBS, 70 | OPT_NOT, 71 | OPT_MULS, 72 | OPT_DIVS, 73 | OPT_COL, // : 74 | OPT_SEM, // ; 75 | //-------------- 76 | OPT_COUNT, 77 | OPT_UNKNOWN = -1, 78 | }; 79 | 80 | 81 | enum PuType 82 | { 83 | KW_WHILE, // 0 84 | KW_END, // 1 85 | KW_IF, // 2 86 | KW_ELSE, // 3 87 | KW_BREAK, // 4 88 | KW_GOTO, // 5 89 | KW_FUNCTION, // 6 90 | KW_RETURN, // 7 91 | KW_INCLUDE, // 8 92 | KW_CONTINUE, // 9 93 | KW_ELIF, // 10 94 | KW_NIL, // 11 95 | KW_FALSE, // 12 96 | KW_TRUE, // 13 97 | KW_VAR, // 14 98 | KW_FOR, // 15 99 | KW_IN, // 16 100 | //----------------------------------------------- 101 | OP = 500, // 102 | VAR, // 103 | FINISH, 104 | LABEL, 105 | //----------------------------------------------- 106 | UNKNOWN = 1000, 107 | NIL, 108 | NUM, 109 | STR, 110 | ARRAY, 111 | MAP, 112 | CORO, 113 | FILEHANDLE, 114 | BOOLEANT, 115 | INTEGER, 116 | FUN, 117 | CFUN, 118 | CPTR 119 | }; 120 | 121 | enum CODEFROM{ 122 | FROM_BYTECODE, 123 | FROM_SOURCECODE 124 | }; 125 | 126 | #endif 127 | 128 | 129 | -------------------------------------------------------------------------------- /src/state.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009 Zhang li 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | 22 | MIT License: http://www.opensource.org/licenses/mit-license.php 23 | */ 24 | 25 | /* 26 | Author zhang li 27 | Email zlvbvbzl@gmail.com 28 | */ 29 | 30 | #include "state.h" 31 | #include "util.h" 32 | 33 | #if defined(_MSC_VER) && defined(_DEBUG) 34 | #if _DEBUG_MEM == 1 35 | #include 36 | #endif 37 | #endif 38 | extern void bi_get_value_len(Pu *L, int, pu_var *v); 39 | extern void bi_date(Pu *L, int ,pu_var*); 40 | extern void bi_time(Pu *L, int, pu_var*); 41 | extern void bi_get_value_len(Pu *L, int, pu_var *v); 42 | extern void bi_write(Pu *L, int ,pu_var *v); 43 | extern void bi_writeln(Pu *L, int, pu_var *v); 44 | extern void bi_read(Pu *L, int ,pu_var *v); 45 | extern void bi_rand(Pu *L, int ,pu_var *v); 46 | extern void bi_sleep(Pu *L, int, pu_var *v); 47 | extern void bi_type(Pu *L, int, pu_var *v); 48 | extern void bi_eval(Pu *L, int, pu_var *v); 49 | extern void bi_quit(Pu *L, int, pu_var *); 50 | extern void bi_read(Pu *L, int argc, pu_var *v); 51 | extern void bi_open(Pu *L, int argc, pu_var *v); 52 | extern void bi_close(Pu *L, int argc, pu_var *v); 53 | extern void bi_str(Pu *L, int argc, pu_var *v); 54 | extern void bi_num(Pu *L, int argc, pu_var *v); 55 | extern void bi_int(Pu *L, int argc, pu_var *v); 56 | extern void bi_coro_create(Pu *L, int argnum, pu_var *v); 57 | extern void bi_coro_resume(Pu *L, int argnum, pu_var *v); 58 | extern void bi_coro_yield(Pu *L, int argnum, pu_var *v); 59 | extern void bi_get_var(Pu *L, int argnum, pu_var *v); 60 | PUAPI void pu_reg_func(Pu *L, const char *funcname, ScriptFunc pfunc); 61 | 62 | Pu::Pu() 63 | :token(nullptr), 64 | cur_token(0), 65 | line(1), 66 | isquit(false), 67 | mode(0), 68 | err_handle(0), 69 | output_handle(0), 70 | lasterr(-1), 71 | isyield(false), 72 | return_value(this), 73 | up_scope(this, nullptr), 74 | cur_scope(this, new StrKeyMap), 75 | builtinreg(false), 76 | tail_optimize(false), 77 | start_gc(false) 78 | { 79 | varstack.push(cur_scope.base_->vmap_); 80 | return_value.SetType(NIL); 81 | debug(this, "Global scop = %p", cur_scope.base_->vmap_); 82 | } 83 | 84 | extern void gc(Pu *L); 85 | extern void sweep(Pu *L); 86 | Pu::~Pu() 87 | { 88 | gc(this); 89 | sweep(this); 90 | StrKeyMap *global_vmap = varstack.bottom(); 91 | delete global_vmap; 92 | 93 | for (auto p : tempool) 94 | { 95 | delete p; 96 | } 97 | 98 | for (auto &pair : strpool) 99 | { 100 | delete pair.second; 101 | } 102 | 103 | for (auto &pair : const_str_vals) 104 | { 105 | delete pair.second; 106 | } 107 | 108 | for (auto &pair : const_num_vals) 109 | { 110 | delete pair.second; 111 | } 112 | } 113 | 114 | PUAPI Pu *pu_open() 115 | { 116 | #if defined(_MSC_VER) && defined(_DEBUG) 117 | #if _DEBUG_MEM == 1 118 | _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF); 119 | #endif 120 | #endif 121 | 122 | Pu *L = new Pu; 123 | return L; 124 | } 125 | 126 | void regbuiltin(Pu *L) 127 | { 128 | if (L->builtinreg) 129 | { 130 | return; 131 | } 132 | L->builtinreg = true; 133 | pu_reg_func(L, "len", bi_get_value_len); 134 | pu_reg_func(L, "write", bi_write); 135 | pu_reg_func(L, "writeln", bi_writeln); 136 | pu_reg_func(L, "read", bi_read); 137 | pu_reg_func(L, "rand", bi_rand); 138 | pu_reg_func(L, "date", bi_date); 139 | pu_reg_func(L, "time", bi_time); 140 | pu_reg_func(L, "sleep", bi_sleep); 141 | pu_reg_func(L, "type", bi_type); 142 | pu_reg_func(L, "eval", bi_eval); 143 | pu_reg_func(L, "quit", bi_quit); 144 | pu_reg_func(L, "exit", bi_quit); 145 | pu_reg_func(L, "coro_create", bi_coro_create); 146 | pu_reg_func(L, "coro_resume", bi_coro_resume); 147 | pu_reg_func(L, "coro_yield", bi_coro_yield); 148 | pu_reg_func(L, "open", bi_open); 149 | pu_reg_func(L, "close", bi_close); 150 | pu_reg_func(L, "str", bi_str); 151 | pu_reg_func(L, "num", bi_num); 152 | pu_reg_func(L, "int", bi_int); 153 | pu_reg_func(L, "get_var", bi_get_var); 154 | } 155 | 156 | void clear_state(Pu *L) 157 | { 158 | if (L->source.pf) 159 | { 160 | fclose(L->source.pf); 161 | L->source.pf = nullptr; 162 | } 163 | 164 | L->source.str.buff = 0; 165 | L->source.str.pos = 0; 166 | L->source.type = -1; 167 | L->callstack.clear(); 168 | L->cur_token = 0; 169 | L->isquit = false; 170 | L->isreturn.clear(); 171 | L->return_value.SetType(NIL); 172 | } 173 | 174 | PUAPI void pu_close(Pu *L) 175 | { 176 | clear_state(L); 177 | delete L; 178 | } 179 | -------------------------------------------------------------------------------- /src/state.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009 Zhang li 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | 22 | MIT License: http://www.opensource.org/licenses/mit-license.php 23 | */ 24 | 25 | /* 26 | Author zhang li 27 | Email zlvbvbzl@gmail.com 28 | */ 29 | 30 | #ifndef _pu_STATE_ 31 | #define _pu_STATE_ 32 | 33 | #include "PuMap.h" 34 | #include "PuStack.h" 35 | #include "PuVector.h" 36 | #include "def.h" 37 | #include "token.h" 38 | #include 39 | 40 | typedef std::unordered_map StrMap; 41 | typedef std::unordered_map ConstVarStrPool; 42 | typedef std::unordered_map ConstVarNumPool; 43 | typedef std::unordered_map ConstVarIntPool; 44 | typedef PuStack CallStack; 45 | typedef PuStack VarStack; 46 | typedef std::unordered_map LabelMap; 47 | typedef std::vector FunArgs; 48 | typedef std::vector<__pu_var*> VarVec; 49 | struct FuncPos 50 | { 51 | int start; 52 | int end; 53 | FunArgs argnames; 54 | ScriptFunc pfunc; 55 | 56 | FuncPos() 57 | :start(-1) 58 | ,end(-1) 59 | ,pfunc(nullptr) 60 | { 61 | 62 | } 63 | }; 64 | typedef std::vector FuncList; 65 | struct Pustrbuff 66 | { 67 | Pustrbuff():pos(0),buff(0) 68 | {} 69 | int pos; 70 | const char *buff; 71 | }; 72 | 73 | struct Pusource 74 | { 75 | Pusource():pf(0),type(-1) 76 | {} 77 | FILE *pf; 78 | Pustrbuff str; 79 | int type; 80 | 81 | enum __SOURCETYPE 82 | { 83 | ST_BUFFER, 84 | ST_FILE 85 | }; 86 | }; 87 | 88 | struct coro 89 | { 90 | StrKeyMap *varmap; 91 | int begin; 92 | int cur; 93 | int end; 94 | int funpos; 95 | int id; 96 | }; 97 | 98 | typedef std::vector CoroList; 99 | 100 | struct Pu 101 | { 102 | Pu(); 103 | ~Pu(); 104 | 105 | Token *token; 106 | int cur_token; 107 | int line; 108 | PuStack isreturn; 109 | bool isquit; 110 | int mode; 111 | std::vector funstack; 112 | ErrHandle err_handle; 113 | OutputHandle output_handle; 114 | int lasterr; 115 | bool isyield; 116 | TokenList tokens; 117 | Pusource source; 118 | LabelMap labelmap; 119 | FuncList funclist; 120 | VarStack varstack; 121 | CallStack callstack; 122 | __pu_var return_value; 123 | std::vector current_filename; 124 | StrMap strpool; 125 | CoroList coros; 126 | PuStack uncomdef; 127 | PuStack jumpstack; 128 | std::unordered_set<_scope::_smap*> gccontainer; 129 | std::unordered_set<_scope::_smap*> garbage; 130 | _scope up_scope; 131 | _scope cur_scope; 132 | VarVec tempool; 133 | VarVec tempvals; 134 | ConstVarStrPool const_str_vals; 135 | ConstVarNumPool const_num_vals; 136 | ConstVarIntPool const_int_vals; 137 | bool builtinreg; 138 | bool tail_optimize; 139 | bool start_gc; 140 | std::vector > *control_flow; 141 | }; 142 | 143 | 144 | #endif 145 | -------------------------------------------------------------------------------- /src/token.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009 Zhang li 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | 22 | MIT License: http://www.opensource.org/licenses/mit-license.php 23 | */ 24 | 25 | /* 26 | Author zhang li 27 | Email zlvbvbzl@gmail.com 28 | */ 29 | 30 | #include "state.h" 31 | #include "error.h" 32 | #include "PuMath.h" 33 | #include 34 | 35 | #define CHECK_ADDLINES {if(c=='\n') ++L->line;} 36 | #define CHECK_MINLINES {if(c=='\n') --L->line;} 37 | 38 | extern void get_nextbytetoken(Pu *L, FILE *pbcf, Token &t); 39 | extern void savebytecode(Pu *L, const char *fname, TokenList &tokens); 40 | PUAPI int pu_loadbytecode(Pu *L, const char *fname); 41 | Token get_token_from_file(Pu *L, TokenList *t); 42 | 43 | static PuType check_token_type(const std::string &identifier) 44 | { 45 | int i = 0; 46 | for (; i < KEYWORDS_TYPES_LENGTH; ++i) 47 | { 48 | if (identifier == KEYWORDS[i]) 49 | { 50 | if (i == KW_NIL) 51 | { 52 | return NIL; 53 | } 54 | else 55 | { 56 | return (PuType)i; 57 | } 58 | } 59 | } 60 | return VAR; 61 | } 62 | 63 | #define CHECK_MATCH(stack) \ 64 | if (stack.size() == 0) { \ 65 | error(L, 37, L->line); \ 66 | return;\ 67 | } 68 | 69 | void append_token(Pu *L, Token &t) 70 | { 71 | L->tokens.push_back(t); 72 | 73 | if (t.type == KW_IF || t.type == KW_WHILE || t.type == KW_FUNCTION || t.type == KW_FOR) 74 | { 75 | int startpos = L->tokens.size()-1; 76 | L->jumpstack.push(startpos); 77 | } 78 | else if (t.type == KW_ELIF || t.type == KW_ELSE) 79 | { 80 | CHECK_MATCH(L->jumpstack); 81 | int startpos = L->jumpstack.top(); 82 | L->tokens[startpos].endpos = L->tokens.size()-1; 83 | L->jumpstack.pop(); 84 | startpos = L->tokens.size()-1; 85 | L->jumpstack.push(startpos); 86 | } 87 | else if (t.type == KW_END) 88 | { 89 | CHECK_MATCH(L->jumpstack); 90 | int startpos = L->jumpstack.top(); 91 | Token &p = L->tokens[startpos]; 92 | if (p.type != KW_FUNCTION) 93 | { 94 | p.endpos = L->tokens.size()-1; 95 | } 96 | CHECK_MATCH(L->jumpstack); 97 | L->jumpstack.pop(); 98 | } 99 | } 100 | 101 | static int pu_sgetc(Pustrbuff &s) 102 | { 103 | return s.buff[s.pos++]; 104 | } 105 | 106 | static void _pu_ungetc(Pustrbuff &s) 107 | { 108 | s.pos--; 109 | } 110 | 111 | static void pu_sscanf(Pustrbuff &s, const char *fmt, void *out) 112 | { 113 | int n=0; 114 | char newfmt[128]={0}; 115 | strncpy(newfmt,fmt, sizeof(newfmt)); 116 | strcat(newfmt,"%n"); 117 | sscanf(&(s.buff[s.pos]),newfmt,out,&n); 118 | s.pos += n; 119 | } 120 | 121 | static int pu_getc(Pu *L) 122 | { 123 | int c; 124 | if (L->source.type == Pusource::ST_FILE) 125 | { 126 | c = fgetc(L->source.pf); 127 | } 128 | else 129 | { 130 | c = pu_sgetc(L->source.str); 131 | } 132 | CHECK_ADDLINES; 133 | return c; 134 | } 135 | 136 | static void pu_ungetc(Pu *L, int c) 137 | { 138 | if (L->source.type == Pusource::ST_FILE) 139 | { 140 | ungetc(c, L->source.pf); 141 | } 142 | else 143 | { 144 | _pu_ungetc(L->source.str); 145 | } 146 | CHECK_MINLINES; 147 | } 148 | 149 | static void pu_scanf(Pusource &s, const char *fmt, void *out) 150 | { 151 | if (s.type == Pusource::ST_FILE) 152 | { 153 | fscanf(s.pf,fmt,out); 154 | } 155 | else 156 | { 157 | pu_sscanf(s.str,fmt,out); 158 | } 159 | } 160 | 161 | const __pu_var *get_str_literal(Pu *L, const PuString &strVal) 162 | { 163 | const __pu_var *literal_value = nullptr; 164 | auto it = L->const_str_vals.find(*strVal.pbuff); 165 | if (it != L->const_str_vals.end()) 166 | { 167 | literal_value = it->second; 168 | } 169 | else 170 | { 171 | literal_value = new __pu_var(L); 172 | const_cast<__pu_var*>(literal_value)->SetType(STR); 173 | const_cast<__pu_var*>(literal_value)->strVal() = strVal; 174 | L->const_str_vals[*strVal.pbuff] = literal_value; 175 | } 176 | 177 | return literal_value; 178 | } 179 | 180 | static void get_string(Pu *L, int c, Token &newToken) 181 | { 182 | bool qtt = (c=='\''); 183 | c = pu_getc(L); 184 | PuString strValout; 185 | while ( (c != '\'' && qtt) || (c != '\"' && !qtt) ) 186 | { 187 | if (check_source_end(c,L->source)) 188 | { 189 | error(L,0, L->line); 190 | return; 191 | } 192 | if (c == '\\') 193 | { 194 | c = pu_getc(L); 195 | switch (c) 196 | { 197 | case 'n': c = '\n';break; 198 | case 't': c = '\t';break; 199 | case 'r': c = '\r';break; 200 | case '\'': c = '\'';break; 201 | case '\"': c = '\"';break; 202 | } 203 | } 204 | strValout += (char(c)); 205 | c = pu_getc(L); 206 | } 207 | 208 | newToken.type = STR; 209 | newToken.literal_value = get_str_literal(L, strValout); 210 | } 211 | 212 | const __pu_var *get_int_literal(Pu *L, PU_INT intval) 213 | { 214 | const __pu_var *literal_value = nullptr; 215 | int64_t key = intval; 216 | auto it = L->const_int_vals.find(key); 217 | if (it != L->const_int_vals.end()) 218 | { 219 | literal_value = it->second; 220 | } 221 | else 222 | { 223 | literal_value = new __pu_var(L); 224 | const_cast<__pu_var*>(literal_value)->SetType(INTEGER); 225 | const_cast<__pu_var*>(literal_value)->intVal() = intval; 226 | L->const_int_vals[key] = literal_value; 227 | } 228 | 229 | return literal_value; 230 | } 231 | 232 | const __pu_var *get_num_literal(Pu *L, PU_NUMBER number) 233 | { 234 | const __pu_var *literal_value = nullptr; 235 | uint64_t key = *(uint64_t*)&number; 236 | auto it = L->const_num_vals.find(key); 237 | if (it != L->const_num_vals.end()) 238 | { 239 | literal_value = it->second; 240 | } 241 | else 242 | { 243 | literal_value = new __pu_var(L); 244 | const_cast<__pu_var*>(literal_value)->SetType(NUM); 245 | const_cast<__pu_var*>(literal_value)->numVal() = number; 246 | L->const_num_vals[key] = literal_value; 247 | } 248 | 249 | return literal_value; 250 | } 251 | 252 | static void get_num(Pu *L, int c, Token &newToken) 253 | { 254 | char syntax[64] = {0}; 255 | int nlen = 0; 256 | while (isdigit(c) || c == '.') 257 | { 258 | if (check_source_end(c, L->source)) 259 | { 260 | error(L, 0, L->line); 261 | return; 262 | } 263 | syntax[nlen++] += char(c); 264 | c = pu_getc(L); 265 | } 266 | 267 | pu_ungetc(L, c); 268 | 269 | if (is_int(syntax)) 270 | { 271 | newToken.type = INTEGER; 272 | newToken.literal_value = get_int_literal(L, atoll(syntax)); 273 | } 274 | else if (is_float(syntax)) 275 | { 276 | newToken.type = NUM; 277 | newToken.literal_value = get_num_literal(L, atof(syntax)); 278 | } 279 | else 280 | { 281 | error(L, 29); 282 | } 283 | } 284 | 285 | static bool is_space(Pu *L, int c) 286 | { 287 | if (c == '#') 288 | { 289 | while (c != '\n' && !check_source_end(c,L->source)) 290 | { 291 | c = pu_getc(L); 292 | } 293 | return true; 294 | } 295 | if (c == '@') 296 | { 297 | c = pu_getc(L); 298 | while (c != '@' && !check_source_end(c,L->source)) 299 | { 300 | c = pu_getc(L); 301 | } 302 | return true; 303 | } 304 | 305 | int i = 0; 306 | for (; i < SPACE_TYPES_LENGTH; ++i) 307 | { 308 | if (c == SPACE_TYPES[i]) 309 | { 310 | return true; 311 | } 312 | } 313 | return false; 314 | } 315 | 316 | 317 | static int check_op_type(const std::string &s) 318 | { 319 | int i = 0; 320 | for (; i < OPERATOR_TYPES_LENGTH; ++i) 321 | { 322 | if (s == OPERATORS[i]) 323 | { 324 | return i+1; 325 | } 326 | } 327 | return 0; 328 | } 329 | 330 | static bool is_op(int c) 331 | { 332 | for (int i=0; OPERATOR_CHARS[i]!='\0'; ++i) 333 | { 334 | if (OPERATOR_CHARS[i] == c) 335 | return true; 336 | } 337 | return false; 338 | } 339 | 340 | static void get_op(Pu *L, int c, Token &newToken) 341 | { 342 | char identifier[PU_MAXVARLEN]={0}; 343 | int i=-1; 344 | newToken.type = OP; 345 | 346 | while (is_op(c)) 347 | { 348 | if (i == 128) 349 | { 350 | error(L,28); 351 | return; 352 | } 353 | 354 | identifier[++i] = char(c); 355 | int optype = check_op_type(identifier); 356 | if (optype == 0 && c != '|' && c != '&' && c != '!') 357 | { 358 | identifier[i]='\0'; 359 | break; 360 | } 361 | else 362 | { 363 | c = pu_getc(L); 364 | } 365 | } 366 | pu_ungetc(L,c); 367 | newToken.optype = (OperatorType)(check_op_type(identifier) - 1); 368 | if (newToken.type == OP) 369 | { 370 | assert(newToken.optype != -1); 371 | } 372 | } 373 | 374 | static void get_var_key(Pu *L, int c, Token &newToken) 375 | { 376 | char identifier[PU_MAXVARLEN]={0}; 377 | int i = -1; 378 | while (!is_op(c) && !is_space(L,c) && !check_source_end(c,L->source)) 379 | { 380 | if (i == 128) 381 | { 382 | error(L,28); 383 | return; 384 | } 385 | 386 | identifier[++i] = char(c); 387 | c = pu_getc(L); 388 | } 389 | pu_ungetc(L,c); 390 | 391 | newToken.type = check_token_type(identifier); 392 | if (newToken.type == VAR) 393 | { 394 | newToken.name = InsertStrPool(L, identifier); 395 | } 396 | } 397 | 398 | static void check_include(Pu *L, const char *fname) 399 | { 400 | auto it = L->current_filename.begin(); 401 | auto ite = L->current_filename.end(); 402 | 403 | while (it != ite) 404 | { 405 | int i = (int)(*it)->length() - 1; 406 | for (; i >= 0; --i) 407 | { 408 | if ((*it)->operator[](i) == '.') 409 | { 410 | break; 411 | } 412 | } 413 | 414 | if (memcmp((*it)->c_str(), fname, i) == 0) 415 | { 416 | error(L, 19); 417 | break; 418 | } 419 | ++it; 420 | } 421 | } 422 | 423 | static void get_label(Pu *L, Token &newToken) 424 | { 425 | newToken.type = LABEL; 426 | char label[PU_MAXVARLEN]={0}; 427 | pu_scanf(L->source, "%s", label); 428 | newToken.name = InsertStrPool(L, label); 429 | L->labelmap.insert(std::make_pair(label, L->cur_token)); 430 | } 431 | 432 | void parse_function_body(Pu *L, int lp, int token_from, Token &t, FILE *pbcf=0, TokenList *tl=0) 433 | { 434 | for (;;) 435 | { 436 | if (t.type == KW_IF) 437 | { 438 | L->funstack.back()++; 439 | } 440 | else if (t.type == KW_WHILE) 441 | { 442 | L->funstack.back()++; 443 | } 444 | else if (t.type == KW_END) 445 | { 446 | L->funstack.back()--; 447 | } 448 | else if (t.type == FINISH) 449 | { 450 | if (L->mode != PU_CODE_FROM_FILE) 451 | { 452 | L->uncomdef.push(lp); 453 | return; 454 | } 455 | else 456 | { 457 | error(L,17); 458 | break; 459 | } 460 | } 461 | 462 | if (L->funstack.back() == 0) 463 | { 464 | if (L->mode != PU_CODE_FROM_FILE) 465 | { 466 | L->uncomdef.pop(); 467 | } 468 | 469 | L->funstack.pop_back(); 470 | break; 471 | } 472 | 473 | if (token_from == FROM_BYTECODE) 474 | { 475 | get_nextbytetoken(L,pbcf, t); 476 | } 477 | else 478 | { 479 | t = get_token_from_file(L,tl); 480 | CHECKTOKENERROR; 481 | } 482 | } 483 | FuncPos &fps = L->funclist[lp]; 484 | fps.end = L->tokens.size(); 485 | } 486 | 487 | void parse_function(Pu *L, int token_from, FILE *pbcf, TokenList *tl) 488 | { 489 | FuncPos fps; 490 | Token fname; 491 | int funckeywords_pos = L->tokens.size()-1; 492 | if (token_from == FROM_BYTECODE) 493 | { 494 | get_nextbytetoken(L,pbcf, fname); 495 | } 496 | else 497 | { 498 | fname = get_token_from_file(L,tl); 499 | CHECKTOKENERROR; 500 | } 501 | 502 | Token t; 503 | if (fname.type != VAR) 504 | { 505 | if (fname.optype != OPT_LB) 506 | { 507 | error(L, 29); 508 | return; 509 | } 510 | 511 | if (token_from == FROM_BYTECODE) 512 | { 513 | get_nextbytetoken(L,pbcf, t); 514 | } 515 | else 516 | { 517 | t = get_token_from_file(L,tl); 518 | CHECKTOKENERROR; 519 | } 520 | } 521 | else 522 | { 523 | if (token_from == FROM_BYTECODE) 524 | { 525 | get_nextbytetoken(L,pbcf, t); 526 | get_nextbytetoken(L,pbcf, t); 527 | } 528 | else 529 | { 530 | t = get_token_from_file(L,tl); 531 | CHECKTOKENERROR; 532 | t = get_token_from_file(L,tl); 533 | CHECKTOKENERROR; 534 | } 535 | } 536 | 537 | while (!(t.type == OP && t.optype == OPT_RB))// ) 538 | { 539 | if (t.type == OP && t.optype == OPT_COM) 540 | { 541 | //pass 542 | } 543 | else 544 | { 545 | fps.argnames.push_back(t.name); 546 | } 547 | 548 | if (token_from == FROM_BYTECODE) 549 | { 550 | get_nextbytetoken(L,pbcf, t); 551 | } 552 | else 553 | { 554 | t = get_token_from_file(L,tl); 555 | CHECKTOKENERROR; 556 | } 557 | } 558 | 559 | fps.start = L->tokens.size(); 560 | if (token_from == FROM_BYTECODE) 561 | { 562 | get_nextbytetoken(L,pbcf, t); 563 | } 564 | else 565 | { 566 | t = get_token_from_file(L,tl); 567 | CHECKTOKENERROR; 568 | } 569 | 570 | L->funclist.push_back(fps); 571 | L->tokens[funckeywords_pos].endpos = L->funclist.size()-1; 572 | L->funstack.push_back(1); 573 | parse_function_body(L,L->funclist.size()-1,token_from,t,pbcf,tl); 574 | } 575 | 576 | 577 | void parse_include(Pu *L, const Token &filename) 578 | { 579 | check_include(L, filename.name->c_str()); 580 | 581 | std::string newfname = (*filename.name) + ".puc"; 582 | if (!pu_loadbytecode(L, newfname.c_str())) 583 | { 584 | Pusource old_s = L->source; 585 | std::string fsn(*filename.name); 586 | fsn += ".pu"; 587 | L->source.pf = fopen(fsn.c_str(), "r"); 588 | L->source.type = Pusource::ST_FILE; 589 | if (L->source.pf == nullptr) 590 | { 591 | error(L,20); 592 | return; 593 | } 594 | 595 | L->current_filename.push_back(InsertStrPool(L, fsn.c_str())); 596 | 597 | TokenList t; 598 | Token temp; 599 | do{ 600 | temp = get_token_from_file(L, &t); 601 | CHECKTOKENERROR; 602 | }while(temp.type != FINISH); 603 | fclose(L->source.pf); 604 | savebytecode(L,newfname.c_str(), t); 605 | t.clear(); 606 | 607 | L->source = old_s; 608 | L->current_filename.pop_back(); 609 | } 610 | L->tokens.pop_back(); 611 | } 612 | 613 | int findcurstart(Pu *L) 614 | { 615 | int max_token = L->tokens.size(); 616 | if (max_token <= 1) 617 | { 618 | return 0; 619 | } 620 | 621 | int ct = max_token; 622 | ct-=2; 623 | while (L->tokens[ct].type != FINISH) 624 | { 625 | if (ct == 0) 626 | return 0; 627 | --ct; 628 | 629 | } 630 | return ct+1; 631 | } 632 | 633 | 634 | bool check_complete(Pu *L) 635 | { 636 | int cur = L->cur_token; 637 | L->cur_token = findcurstart(L); 638 | int whh=0; 639 | NEXT_TOKEN; 640 | for (;TOKEN.type != FINISH;) 641 | { 642 | PuType tp = TOKEN.type; 643 | if (tp == KW_WHILE || tp == KW_IF || tp == KW_FUNCTION || tp == KW_FOR) 644 | { 645 | ++whh; 646 | } 647 | else if (tp == KW_END) 648 | { 649 | --whh; 650 | } 651 | NEXT_TOKEN; 652 | } 653 | L->cur_token = cur; 654 | if (whh<0) 655 | { 656 | error(L,26); 657 | } 658 | return whh==0; 659 | } 660 | 661 | Token get_token_from_file(Pu *L, TokenList *t) 662 | { 663 | Token newToken; 664 | newToken.type = UNKNOWN; 665 | bool need_include = false; 666 | for (;;) 667 | { 668 | int c; 669 | do{ 670 | c = pu_getc(L); 671 | }while (is_space(L,c)); 672 | 673 | if (check_source_end(c,L->source)) 674 | { 675 | newToken.type = FINISH; 676 | } 677 | else if (c == '\'' || c == '\"') // 678 | { 679 | get_string(L, c, newToken); 680 | } 681 | else if (c == '$') 682 | { 683 | get_label(L, newToken); 684 | } 685 | else if (is_op(c)) // 686 | { 687 | get_op(L, c, newToken); 688 | } 689 | else if (isdigit(c) || c=='-') 690 | { 691 | get_num(L, c,newToken); 692 | } 693 | else if (!is_op(c)) 694 | { 695 | get_var_key(L, c, newToken); 696 | } 697 | 698 | CHECKTOKENERROR newToken; 699 | 700 | newToken.line = L->line; 701 | newToken.filename = L->current_filename.back(); 702 | 703 | append_token(L, newToken); 704 | 705 | if (t) 706 | { 707 | t->push_back(newToken); 708 | } 709 | 710 | if (newToken.type != KW_INCLUDE) 711 | break; 712 | else 713 | need_include = true; 714 | } 715 | 716 | if (need_include) 717 | parse_include(L,newToken); 718 | else if (newToken.type == KW_FUNCTION) 719 | parse_function(L,FROM_SOURCECODE, nullptr, t); 720 | 721 | return newToken; 722 | } 723 | 724 | void Token::operator=( const Token &x ) 725 | { 726 | type = x.type; 727 | line = x.line; 728 | optype = x.optype; 729 | filename = x.filename; 730 | name = x.name; 731 | literal_value = x.literal_value; 732 | } 733 | 734 | Token::Token( const Token &x ) 735 | : filename(x.filename) 736 | , literal_value(NULL) 737 | , exp_end(-1) 738 | , exp_stack(-1) 739 | 740 | , control_flow(nullptr) 741 | { 742 | type = x.type; 743 | line = x.line; 744 | optype = x.optype; 745 | name = x.name; 746 | if (x.type >= NIL && x.type <= CPTR) 747 | { 748 | literal_value = x.literal_value; 749 | } 750 | } 751 | 752 | Token::~Token() 753 | { 754 | if (control_flow) 755 | { 756 | delete control_flow; 757 | control_flow = nullptr; 758 | } 759 | } 760 | 761 | const std::string *InsertStrPool(Pu * L, const char *sname) 762 | { 763 | const std::string *filename = nullptr; 764 | auto it = L->strpool.find(sname); 765 | if (it == L->strpool.end()) 766 | { 767 | filename = new std::string(sname); 768 | L->strpool.insert(std::make_pair(*filename, filename)); 769 | } 770 | else 771 | { 772 | filename = it->second; 773 | } 774 | 775 | return filename; 776 | } 777 | -------------------------------------------------------------------------------- /src/token.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009 Zhang li 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | 22 | MIT License: http://www.opensource.org/licenses/mit-license.php 23 | */ 24 | 25 | /* 26 | Author zhang li 27 | Email zlvbvbzl@gmail.com 28 | */ 29 | 30 | #ifndef __TOKEN_H_ 31 | #define __TOKEN_H_ 32 | 33 | #include "value.h" 34 | #include "travel.h" 35 | #include 36 | struct Token 37 | { 38 | Token() 39 | : filename(nullptr) 40 | , name(nullptr) 41 | , literal_value(nullptr) 42 | , line(0) 43 | , exp_end(-1) 44 | , exp_stack(-1) 45 | , type(UNKNOWN) 46 | , optype(OPT_UNKNOWN) 47 | , control_flow(nullptr) 48 | {} 49 | Token(const Token &x); 50 | ~Token(); 51 | void operator=(const Token &x); 52 | const std::string *filename; 53 | const std::string *name; 54 | const __pu_var *literal_value; 55 | int line; 56 | int exp_end; 57 | short exp_stack; 58 | PuType type; 59 | union 60 | { 61 | OperatorType optype; 62 | int endpos; 63 | }; 64 | 65 | std::vector > *control_flow; 66 | }; 67 | 68 | typedef std::vector TokenList; 69 | #define check_source_end(c,s) \ 70 | ( \ 71 | ((s).type == Pusource::ST_FILE && (c) == EOF)|| \ 72 | ((s).type == Pusource::ST_BUFFER && (c) =='\0') \ 73 | ) 74 | 75 | #define CHECKTOKENERROR if (L->lasterr >= 0) return 76 | #define PU_CODE_FROM_FILE 0 77 | #define PU_CODE_FROM_BUFF 1 78 | #define PU_FUNCTION_UNCOMPLETED 2 79 | 80 | const std::string *InsertStrPool(Pu *L, const char *sname); 81 | const __pu_var *get_str_literal(Pu *L, const PuString &strVal); 82 | const __pu_var *get_num_literal(Pu *L, PU_NUMBER number); 83 | const __pu_var *get_int_literal(Pu *L, PU_INT number); 84 | #endif 85 | -------------------------------------------------------------------------------- /src/travel.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009 Zhang li 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | 22 | MIT License: http://www.opensource.org/licenses/mit-license.php 23 | */ 24 | 25 | /* 26 | Author zhang li 27 | Email zlvbvbzl@gmail.com 28 | */ 29 | 30 | #include "travel.h" 31 | #include "error.h" 32 | #include "state.h" 33 | 34 | static void term_trvel(Pu *L); 35 | static void get_value_trvel(Pu *L); 36 | static void factor_trvel(Pu *L); 37 | static void cmp_trvel(Pu *L); 38 | static void logic_trvel(Pu *L); 39 | static void add_trvel(Pu *L); 40 | static void callfunction_trvel(Pu *L); 41 | static void get_arrref_trvel(Pu *L); 42 | static void get_array_trvel(Pu *L); 43 | static void get_map_trvel(Pu *L); 44 | 45 | #define _CHT PuType tp = TOKEN.type;int nv = TOKEN.optype; 46 | #define _TERM(L) {_CHT if(tp == OP && (nv==OPT_MUL||nv==OPT_DIV||nv==OPT_MOD))term_trvel(L);} 47 | #define _ADD(L) {_CHT if(tp == OP && (nv==OPT_ADD||nv==OPT_SUB))add_trvel(L);} 48 | #define _CMP(L) {_CHT if(tp == OP && (nv==OPT_GT||nv==OPT_LT||nv==OPT_EQ||nv==OPT_GTA||nv==OPT_LTA||nv==OPT_NEQ))cmp_trvel(L);} 49 | #define _LOGC(L) {_CHT if(tp == OP && (nv==OPT_OR||nv==OPT_AND))logic_trvel(L); } 50 | #define LOGC(L) factor_trvel(L); _TERM(L) _ADD(L) _CMP(L) _LOGC(L) 51 | #define CMP(L) factor_trvel(L); _TERM(L) _ADD(L) _CMP(L) 52 | #define ADD(L) factor_trvel(L); _TERM(L) _ADD(L) 53 | #define TERM(L) factor_trvel(L); _TERM(L) 54 | #define FACTOR(L) factor_trvel(L); 55 | 56 | struct AutoAddPath 57 | { 58 | AutoAddPath(Pu *L, CONTROL_PATH eTp) :L_(L), eTp_(eTp){} 59 | ~AutoAddPath() 60 | { 61 | L_->control_flow->back().push_back(eTp_); 62 | } 63 | Pu *L_; 64 | CONTROL_PATH eTp_; 65 | }; 66 | 67 | #define AddPath(eTp) AutoAddPath __aap(L, eTp); 68 | 69 | static void _exp_trvel(Pu *L); 70 | static void _doexp_trvel(Pu * L); 71 | 72 | void _doexp_trvel(Pu * L) 73 | { 74 | AddPath(CP_EXP); 75 | Token *ptoken = &TOKEN; 76 | do { 77 | if (ptoken->type == VAR) 78 | { 79 | NEXT_TOKEN; 80 | PuType tp = TOKEN.type; 81 | OperatorType nv = TOKEN.optype; 82 | if (tp == OP 83 | && (nv == OPT_SET || nv == OPT_ADDS || nv == OPT_SUBS || nv == OPT_MULS || nv == OPT_DIVS)) 84 | { 85 | break; 86 | } 87 | PREV_TOKEN; 88 | } 89 | 90 | LOGC(L); 91 | 92 | } while (false); 93 | 94 | PuType tp = TOKEN.type; 95 | OperatorType nv = TOKEN.optype; 96 | if (!(tp == OP 97 | && (nv == OPT_SET || nv == OPT_ADDS || nv == OPT_SUBS || nv == OPT_MULS || nv == OPT_DIVS))) 98 | return; 99 | 100 | NEXT_TOKEN; 101 | _exp_trvel(L); 102 | } 103 | 104 | void _exp_trvel(Pu *L) 105 | { 106 | L->control_flow->push_back(std::vector()); 107 | _doexp_trvel(L); 108 | L->control_flow->pop_back(); 109 | } 110 | 111 | void exp_control_flow_analyze(Pu *L) 112 | { 113 | L->control_flow = new std::vector >(); 114 | L->control_flow->push_back(std::vector()); 115 | _doexp_trvel(L); 116 | } 117 | 118 | void get_map_trvel(Pu *L) 119 | { 120 | __pu_var v(L); 121 | NEXT_TOKEN; 122 | for (;;) 123 | { 124 | PuType tp = TOKEN.type; 125 | OperatorType nv = TOKEN.optype; 126 | 127 | if (tp == OP) 128 | { 129 | if (nv == OPT_RBR) // } 130 | { 131 | NEXT_TOKEN; 132 | break; 133 | } 134 | else 135 | { 136 | error(L, 29); 137 | return; 138 | } 139 | } 140 | else 141 | { 142 | _exp_trvel(L); 143 | tp = TOKEN.type; 144 | nv = TOKEN.optype; 145 | if (tp == OP && nv == OPT_COL) // : 146 | { 147 | NEXT_TOKEN; 148 | } 149 | else 150 | { 151 | error(L, 29); 152 | return; 153 | } 154 | _exp_trvel(L); 155 | if (TOKEN.type != OP) 156 | { 157 | error(L, 29); 158 | return; 159 | } 160 | 161 | if (TOKEN.optype != OPT_COM) // , 162 | { 163 | if (TOKEN.optype != OPT_RBR) // } 164 | { 165 | error(L, 29); 166 | return; 167 | } 168 | else 169 | { 170 | NEXT_TOKEN; 171 | break; 172 | } 173 | } 174 | else 175 | { 176 | NEXT_TOKEN; 177 | } 178 | } 179 | } 180 | } 181 | 182 | void term_trvel(Pu * L) 183 | { 184 | AddPath(CP_TERM); 185 | PuType tp = TOKEN.type; 186 | OperatorType nv = TOKEN.optype; 187 | 188 | while (tp == OP) // */% 189 | { 190 | switch (nv) 191 | { 192 | case OPT_MUL: 193 | case OPT_DIV: 194 | case OPT_MOD: 195 | { 196 | NEXT_TOKEN; 197 | FACTOR(L); 198 | } 199 | break; 200 | default: 201 | return; 202 | } 203 | 204 | tp = TOKEN.type; 205 | nv = TOKEN.optype; 206 | } 207 | } 208 | 209 | void get_value_trvel(Pu *L) 210 | { 211 | AddPath(CP_VAL); 212 | PuType tp = TOKEN.type; 213 | OperatorType nv = TOKEN.optype; 214 | if (tp == OP && ((nv == OPT_ADD) || (nv == OPT_SUB) || (nv == OPT_NOT))) 215 | { 216 | NEXT_TOKEN; 217 | get_value_trvel(L); 218 | } 219 | else 220 | { 221 | NEXT_TOKEN; 222 | } 223 | } 224 | 225 | void factor_trvel(Pu * L) 226 | { 227 | AddPath(CP_FACTOR); 228 | PuType tp = TOKEN.type; 229 | OperatorType nv = TOKEN.optype; 230 | 231 | if (tp == OP)// ( [ 232 | { 233 | switch (nv) 234 | { 235 | case OPT_LB: 236 | { 237 | NEXT_TOKEN; 238 | _exp_trvel(L); 239 | tp = TOKEN.type; 240 | nv = TOKEN.optype; 241 | if (tp != OP || nv != OPT_RB) 242 | { 243 | error(L, 1); 244 | return; 245 | } 246 | NEXT_TOKEN; 247 | } 248 | break; 249 | case OPT_LSB: 250 | get_array_trvel(L); 251 | break; 252 | case OPT_LBR: 253 | get_map_trvel(L); 254 | break; 255 | case OPT_NOT: 256 | get_value_trvel(L); 257 | default: 258 | break; 259 | } 260 | } 261 | else 262 | { 263 | get_value_trvel(L); 264 | tp = TOKEN.type; 265 | nv = TOKEN.optype; 266 | 267 | while (tp == OP) 268 | { 269 | switch (nv) 270 | { 271 | case OPT_LB: // ( 272 | callfunction_trvel(L); 273 | break; 274 | case OPT_LSB: // [ 275 | get_arrref_trvel(L); 276 | NEXT_TOKEN; 277 | break; 278 | default: 279 | return; 280 | } 281 | tp = TOKEN.type; 282 | nv = TOKEN.optype; 283 | } 284 | } 285 | } 286 | 287 | void cmp_trvel(Pu * L) 288 | { 289 | AddPath(CP_CMP); 290 | PuType token_type = TOKEN.type; 291 | OperatorType op_type = TOKEN.optype; 292 | 293 | while (token_type == OP) 294 | { 295 | switch (op_type) 296 | { 297 | case OPT_GT: 298 | case OPT_LT: 299 | case OPT_EQ: 300 | case OPT_GTA: 301 | case OPT_LTA: 302 | case OPT_NEQ: 303 | { 304 | NEXT_TOKEN; 305 | ADD(L); 306 | } 307 | break; 308 | default: 309 | return; 310 | } 311 | token_type = TOKEN.type; 312 | op_type = TOKEN.optype; 313 | } 314 | } 315 | 316 | void logic_trvel(Pu * L) 317 | { 318 | AddPath(CP_LOGIC); 319 | PuType token_type = TOKEN.type; 320 | OperatorType op_type = TOKEN.optype; 321 | 322 | while (token_type == OP) // || && 323 | { 324 | switch (op_type) 325 | { 326 | case OPT_OR: 327 | case OPT_AND: 328 | { 329 | NEXT_TOKEN; 330 | CMP(L); 331 | } 332 | break; 333 | default: 334 | return; 335 | } 336 | token_type = TOKEN.type; 337 | op_type = TOKEN.optype; 338 | } 339 | } 340 | 341 | void add_trvel(Pu *L) 342 | { 343 | AddPath(CP_ADD); 344 | PuType token_type = TOKEN.type; 345 | OperatorType op_type = TOKEN.optype; 346 | 347 | while (token_type == OP) // +- 348 | { 349 | switch (op_type) 350 | { 351 | case OPT_ADD: 352 | case OPT_SUB: 353 | { 354 | NEXT_TOKEN; 355 | TERM(L); 356 | } 357 | break; 358 | default: 359 | return; 360 | } 361 | 362 | token_type = TOKEN.type; 363 | op_type = TOKEN.optype; 364 | } 365 | } 366 | 367 | void callfunction_trvel(Pu *L) 368 | { 369 | AddPath(CP_CALL); 370 | NEXT_TOKEN; 371 | int i = 0; 372 | for (;;)// ) 373 | { 374 | PuType tp = TOKEN.type; 375 | int nv = TOKEN.optype; 376 | 377 | if (tp == OP && nv == OPT_RB) 378 | { 379 | break; //) 380 | } 381 | if (tp == FINISH) 382 | { 383 | error(L, 1); 384 | return; 385 | } 386 | if (tp == OP && nv == OPT_COM) 387 | { 388 | NEXT_TOKEN; 389 | continue; 390 | } 391 | _exp_trvel(L); 392 | ++i; 393 | } 394 | NEXT_TOKEN; 395 | } 396 | 397 | void get_arrref_trvel(Pu *L) 398 | { 399 | AddPath(CP_ARRREF); 400 | NEXT_TOKEN; 401 | _exp_trvel(L); 402 | 403 | PuType tp = TOKEN.type; 404 | OperatorType nv = TOKEN.optype; 405 | if (tp != OP || nv != OPT_RSB) 406 | { 407 | error(L, 4); 408 | return; 409 | } 410 | } 411 | 412 | void get_array_trvel(Pu *L) 413 | { 414 | AddPath(CP_ARRAY); 415 | NEXT_TOKEN; 416 | for (;;) 417 | { 418 | PuType tp = TOKEN.type; 419 | OperatorType nv = TOKEN.optype; 420 | if (tp == OP && nv == OPT_COM) // , 421 | { 422 | NEXT_TOKEN; 423 | continue; 424 | } 425 | else if (tp == OP && nv == OPT_RSB) // ] 426 | { 427 | NEXT_TOKEN; 428 | break; 429 | } 430 | else 431 | { 432 | --L->cur_token; 433 | NEXT_TOKEN; 434 | _exp_trvel(L); 435 | } 436 | } 437 | } -------------------------------------------------------------------------------- /src/travel.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009 Zhang li 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | 22 | MIT License: http://www.opensource.org/licenses/mit-license.php 23 | */ 24 | 25 | /* 26 | Author zhang li 27 | Email zlvbvbzl@gmail.com 28 | */ 29 | 30 | #pragma once 31 | 32 | #ifndef TRAVEL_H_ 33 | #define TRAVEL_H_ 34 | 35 | struct Pu; 36 | 37 | void exp_control_flow_analyze(Pu *L); 38 | 39 | 40 | enum CONTROL_PATH 41 | { 42 | CP_EXP, 43 | CP_ADD, 44 | CP_TERM, 45 | CP_CMP, 46 | CP_LOGIC, 47 | CP_CALL, 48 | CP_VAL, 49 | CP_FACTOR, 50 | CP_ARRAY, 51 | CP_ARRREF, 52 | }; 53 | 54 | 55 | #endif 56 | 57 | -------------------------------------------------------------------------------- /src/util.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009 Zhang li 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | 22 | MIT License: http://www.opensource.org/licenses/mit-license.php 23 | */ 24 | 25 | /* 26 | Author zhang li 27 | Email zlvbvbzl@gmail.com 28 | */ 29 | 30 | #pragma once 31 | 32 | #ifndef _UTIL_H_ 33 | #define _UTIL_H_ 34 | 35 | #ifdef _DEBUG 36 | 37 | #include "state.h" 38 | #include 39 | #include 40 | 41 | template 42 | void __debug(Pu *L, const char *fn, int ln, const char *func, Args&&... args) 43 | { 44 | if (L && L->token && TOKEN.filename) 45 | { 46 | const char *pusource_fn = TOKEN.filename->c_str(); 47 | int pusource_ln = TOKEN.line; 48 | printf("[DEBUG] %s[%d](%s) | %s[%d] ", fn, ln, func, 49 | pusource_fn, pusource_ln); 50 | } 51 | else 52 | { 53 | printf("[DEBUG] %s[%d](%s) ", fn, ln, func); 54 | } 55 | 56 | printf(std::forward(args)...); 57 | putchar('\n'); 58 | } 59 | 60 | inline void __debug(Pu *L, const char *fn, int ln, const char *func, const char *s) 61 | { 62 | if (L && L->token && TOKEN.filename) 63 | { 64 | const char *pusource_fn = TOKEN.filename->c_str(); 65 | int pusource_ln = TOKEN.line; 66 | printf("[DEBUG] %s[%d](%s) | %s[%d] %s\n", fn, ln, func, 67 | pusource_fn, pusource_ln, 68 | s); 69 | } 70 | else 71 | { 72 | printf("[DEBUG] %s[%d](%s) %s\n", fn, ln, func, s); 73 | } 74 | } 75 | 76 | #define debug(L, ...) __debug(L, __FILE__, __LINE__, __func__, __VA_ARGS__) 77 | 78 | #else 79 | 80 | #define debug(...) 81 | 82 | #endif 83 | 84 | #endif 85 | 86 | -------------------------------------------------------------------------------- /src/value.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009 Zhang li 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | 22 | MIT License: http://www.opensource.org/licenses/mit-license.php 23 | */ 24 | 25 | /* 26 | Author zhang li 27 | Email zlvbvbzl@gmail.com 28 | */ 29 | 30 | #include "value.h" 31 | #include "error.h" 32 | #include "def.h" 33 | #include "util.h" 34 | 35 | const __pu_var &__pu_var::operator +=(const __pu_var &x) 36 | { 37 | if (type() == INTEGER && x.type() == INTEGER) 38 | { 39 | intVal() += x.intVal(); 40 | } 41 | else if (type() == INTEGER && x.type() == NUM) 42 | { 43 | numVal() = intVal() + x.numVal(); 44 | } 45 | else if (type() == NUM && x.type() == INTEGER) 46 | { 47 | numVal() += x.intVal(); 48 | } 49 | else if (type() == NUM && x.type() == NUM) 50 | { 51 | numVal() += x.numVal(); 52 | } 53 | else 54 | { 55 | *this = *this + x; 56 | } 57 | 58 | return *this; 59 | } 60 | 61 | const __pu_var &__pu_var::operator -=(const __pu_var &x) 62 | { 63 | if (type() == INTEGER && x.type() == INTEGER) 64 | { 65 | intVal() -= x.intVal(); 66 | } 67 | else if (type() == INTEGER && x.type() == NUM) 68 | { 69 | numVal() = intVal() - x.numVal(); 70 | } 71 | else if (type() == NUM && x.type() == INTEGER) 72 | { 73 | numVal() -= x.intVal(); 74 | } 75 | else if (type() == NUM && x.type() == NUM) 76 | { 77 | numVal() -= x.numVal(); 78 | } 79 | else 80 | { 81 | *this = *this - x; 82 | } 83 | return *this; 84 | } 85 | 86 | const __pu_var &__pu_var::operator *=(const __pu_var &x) 87 | { 88 | if (type() == INTEGER && x.type() == INTEGER) 89 | { 90 | intVal() *= x.intVal(); 91 | } 92 | else if (type() == INTEGER && x.type() == NUM) 93 | { 94 | numVal() = intVal() * x.numVal(); 95 | } 96 | else if (type() == NUM && x.type() == INTEGER) 97 | { 98 | numVal() *= x.intVal(); 99 | } 100 | else if (type() == NUM && x.type() == NUM) 101 | { 102 | numVal() *= x.numVal(); 103 | } 104 | else 105 | { 106 | *this = *this * x; 107 | } 108 | return *this; 109 | } 110 | const __pu_var &__pu_var::operator /=(const __pu_var &x) 111 | { 112 | if (type() == INTEGER && x.type() == INTEGER) 113 | { 114 | intVal() /= x.intVal(); 115 | } 116 | else if (type() == INTEGER && x.type() == NUM) 117 | { 118 | numVal() = (PU_NUMBER)intVal() / x.numVal(); 119 | } 120 | else if (type() == NUM && x.type() == INTEGER) 121 | { 122 | numVal() /= (PU_NUMBER)x.intVal(); 123 | } 124 | else if (type() == NUM && x.type() == NUM) 125 | { 126 | numVal() /= x.numVal(); 127 | } 128 | else 129 | { 130 | *this = *this / x; 131 | } 132 | return *this; 133 | } 134 | 135 | union d2ui 136 | { 137 | struct u2 138 | { 139 | unsigned int x1; 140 | unsigned int x2; 141 | }; 142 | 143 | u2 ui; 144 | int64_t li; 145 | double f; 146 | }; 147 | 148 | unsigned int __pu_var::hash() const 149 | { 150 | switch (type()) 151 | { 152 | case STR: 153 | return strVal_->hash(); 154 | case INTEGER: 155 | return (unsigned int)intVal(); 156 | case NUM: 157 | return ((d2ui*)&numVal_)->ui.x1 + ((d2ui*)&numVal_)->ui.x2; 158 | default: 159 | break; 160 | } 161 | error(L, 31); 162 | return 0; 163 | } 164 | 165 | void __pu_var::destroy() 166 | { 167 | switch (type()) 168 | { 169 | case STR: 170 | delete strVal_; 171 | strVal_ = nullptr; 172 | break; 173 | case ARRAY: 174 | delete arr_; 175 | arr_ = nullptr; 176 | break; 177 | case FUN: 178 | delete upval_; 179 | upval_ = nullptr; 180 | break; 181 | case MAP: 182 | delete map_; 183 | map_ = nullptr; 184 | break; 185 | default: 186 | break; 187 | } 188 | } 189 | 190 | void __pu_var::build() 191 | { 192 | switch (type()) 193 | { 194 | case STR: 195 | strVal_ = new PuString; 196 | break; 197 | case MAP: 198 | map_ = new ValueMap; 199 | break; 200 | case ARRAY: 201 | arr_ = new ValueArr; 202 | break; 203 | case FUN: 204 | upval_ = new _scope(L, nullptr); 205 | break; 206 | default: 207 | break; 208 | } 209 | } 210 | 211 | 212 | __pu_var __pu_var::operator +(const __pu_var &x) 213 | { 214 | __pu_var n(L); 215 | if (type() == INTEGER && x.type() == INTEGER) 216 | { 217 | n.SetType(INTEGER); 218 | n.intVal() = intVal() + x.intVal(); 219 | } 220 | else if (type() == INTEGER && x.type() == NUM) 221 | { 222 | n.SetType(NUM); 223 | n.numVal() = intVal() + x.numVal(); 224 | } 225 | else if (type() == NUM && x.type() == INTEGER) 226 | { 227 | n.SetType(NUM); 228 | n.numVal() = numVal() + x.intVal(); 229 | } 230 | else if (type() == NUM && x.type() == NUM) 231 | { 232 | n.SetType(NUM); 233 | n.numVal() = numVal() + x.numVal(); 234 | } 235 | else if (type() == STR && x.type() == STR) 236 | { 237 | n.SetType(STR); 238 | n.strVal() = strVal() + x.strVal(); 239 | } 240 | else if (type() == STR && x.type() == INTEGER) 241 | { 242 | n.SetType(STR); 243 | char temp[64]; 244 | PU_SNPRINTF(temp, sizeof(temp), "%lld", x.intVal()); 245 | n.strVal() = strVal() + temp; 246 | } 247 | else if (type() == INTEGER && x.type() == STR) 248 | { 249 | n.SetType(STR); 250 | char temp[64]; 251 | PU_SNPRINTF(temp, sizeof(temp), "%lld", intVal()); 252 | n.strVal() = PuString(temp) + x.strVal(); 253 | } 254 | else if (type() == STR && x.type() == NUM) 255 | { 256 | n.SetType(STR); 257 | char temp[64]; 258 | 259 | if (PU_INT(x.numVal()) == x.numVal()) 260 | PU_SNPRINTF(temp, sizeof(temp), "%.lf", x.numVal()); 261 | else 262 | PU_SNPRINTF(temp, sizeof(temp), "%lf", x.numVal()); 263 | 264 | n.strVal() = strVal() + temp; 265 | } 266 | else if (type() == NUM && x.type() == STR) 267 | { 268 | n.SetType(STR); 269 | char temp[64]; 270 | if (PU_INT(numVal()) == numVal()) 271 | PU_SNPRINTF(temp, sizeof(temp), "%.lf", numVal()); 272 | else 273 | PU_SNPRINTF(temp, sizeof(temp), "%lf", numVal()); 274 | n.strVal() = PuString(temp) + x.strVal(); 275 | } 276 | else if (type() == STR && x.type() == BOOLEANT) 277 | { 278 | n.SetType(STR); 279 | if (x.intVal() == 1) 280 | n.strVal() += "true"; 281 | else 282 | n.strVal() += "false"; 283 | } 284 | else if (type() == BOOLEANT && x.type() == STR) 285 | { 286 | n.SetType(STR); 287 | PuString res = n.strVal(); 288 | if (intVal() == 1) 289 | n.strVal() = "true"; 290 | else 291 | n.strVal() = "false"; 292 | 293 | n.strVal() += res; 294 | } 295 | else if (type() == ARRAY && x.type() != ARRAY) 296 | { 297 | n.SetType(ARRAY); 298 | ValueArr::iterator it = arr().begin(); 299 | ValueArr::iterator ite = arr().end(); 300 | while (it != ite) 301 | { 302 | n.arr().push_back(*it); 303 | ++it; 304 | } 305 | 306 | n.arr().push_back(x); 307 | } 308 | else 309 | { 310 | error(L, 14); 311 | } 312 | 313 | return n; 314 | } 315 | 316 | __pu_var __pu_var::operator -(const __pu_var &x) 317 | { 318 | __pu_var n(L); 319 | if(type() == INTEGER && x.type() == INTEGER) 320 | { 321 | n.SetType(INTEGER); 322 | n.intVal() = intVal() - x.intVal(); 323 | } 324 | else if(type() == NUM && x.type() == NUM) 325 | { 326 | n.SetType(NUM); 327 | n.numVal() = numVal() - x.numVal(); 328 | } 329 | else if(type() == INTEGER && x.type() == NUM) 330 | { 331 | n.SetType(NUM); 332 | n.numVal() = intVal() - x.numVal(); 333 | } 334 | else if(type() == NUM && x.type() == INTEGER) 335 | { 336 | n.SetType(NUM); 337 | n.numVal() = numVal() - x.intVal(); 338 | } 339 | else 340 | { 341 | error(L, 9); 342 | } 343 | 344 | return n; 345 | } 346 | 347 | __pu_var __pu_var::operator /(const __pu_var &x) 348 | { 349 | __pu_var n(L); 350 | if (x.type() == INTEGER) 351 | { 352 | if (x.intVal() == 0) 353 | { 354 | error(L, 35); 355 | return n; 356 | } 357 | } 358 | else if (x.type() == NUM) 359 | { 360 | if (x.numVal() == 0) 361 | { 362 | error(L, 35); 363 | return n; 364 | } 365 | } 366 | 367 | if (type() == INTEGER && x.type() == INTEGER) 368 | { 369 | n.SetType(INTEGER); 370 | n.intVal() = intVal() / x.intVal(); 371 | } 372 | else if (type() == NUM && x.type() == NUM) 373 | { 374 | n.SetType(NUM); 375 | n.numVal() = numVal() / x.numVal(); 376 | } 377 | else if (type() == INTEGER && x.type() == NUM) 378 | { 379 | n.SetType(NUM); 380 | n.numVal() = (PU_NUMBER)intVal() / x.numVal(); 381 | } 382 | else if (type() == NUM && x.type() == INTEGER) 383 | { 384 | n.SetType(NUM); 385 | n.numVal() = numVal() / (PU_NUMBER)x.intVal(); 386 | } 387 | else 388 | { 389 | error(L, 10); 390 | } 391 | 392 | return n; 393 | } 394 | 395 | __pu_var __pu_var::operator %(const __pu_var &x) 396 | { 397 | __pu_var n(L); 398 | if (type() == INTEGER && x.type() == INTEGER) 399 | { 400 | n.SetType(INTEGER); 401 | n.intVal() = intVal() % x.intVal(); 402 | } 403 | else 404 | { 405 | error(L, 11); 406 | } 407 | 408 | return n; 409 | } 410 | 411 | __pu_var __pu_var::operator *(const __pu_var &x) 412 | { 413 | __pu_var n(L); 414 | if (type() == INTEGER && x.type() == INTEGER) 415 | { 416 | n.SetType(INTEGER); 417 | n.intVal() = intVal() * x.intVal(); 418 | } 419 | else if (type() == NUM && x.type() == NUM) 420 | { 421 | n.SetType(NUM); 422 | n.numVal() = numVal() * x.numVal(); 423 | } 424 | else if (type() == INTEGER && x.type() == NUM) 425 | { 426 | n.SetType(NUM); 427 | n.numVal() = intVal() * x.numVal(); 428 | } 429 | else if (type() == NUM && x.type() == INTEGER) 430 | { 431 | n.SetType(NUM); 432 | n.numVal() = numVal() * x.intVal(); 433 | } 434 | else if (type() == STR && x.type() == INTEGER) 435 | { 436 | n.SetType(STR); 437 | n.strVal() = ""; 438 | int strvn = int(x.intVal()); 439 | for (int k=0; k(const __pu_var &x) const 531 | { 532 | return (*this < x || *this == x)? 0 : 1; 533 | } 534 | 535 | int __pu_var::operator >=(const __pu_var &x) const 536 | { 537 | return (*this < x)? 0 : 1; 538 | } 539 | 540 | int __pu_var::operator <=(const __pu_var &x) const 541 | { 542 | return ((*this < x) || (*this == x))? 1 : 0; 543 | } 544 | 545 | int __pu_var::operator !=(const __pu_var &x) const 546 | { 547 | return (*this == x) ? 0 : 1; 548 | } 549 | 550 | int __pu_var::operator ||(const __pu_var &x) const 551 | { 552 | return (VALUE_IS_TRUE(*this)) || (VALUE_IS_TRUE(x)); 553 | } 554 | 555 | int __pu_var::operator &&(const __pu_var &x) const 556 | { 557 | return (VALUE_IS_TRUE(*this)) && (VALUE_IS_TRUE(x)); 558 | } 559 | 560 | void __pu_var::operator =(const __pu_var &x) 561 | { 562 | SetType(x.type()); 563 | switch (x.type()) 564 | { 565 | case CORO: case INTEGER: case BOOLEANT: case CFUN: case CPTR: 566 | { 567 | intVal() = x.intVal(); 568 | }break; 569 | case NUM: 570 | { 571 | numVal() = x.numVal(); 572 | }break; 573 | case FUN: 574 | { 575 | intVal() = x.intVal(); 576 | up_value() = x.up_value(); 577 | }break; 578 | case STR: 579 | { 580 | strVal() = x.strVal(); 581 | }break; 582 | case ARRAY: 583 | { 584 | arr() = x.arr(); 585 | }break; 586 | case MAP: 587 | { 588 | map() = x.map(); 589 | }break; 590 | case FILEHANDLE: 591 | { 592 | pfile_ = x.pfile_; 593 | } break; 594 | default: 595 | break; 596 | } 597 | 598 | L = x.L; 599 | } 600 | 601 | __pu_var::__pu_var() 602 | :L(nullptr) 603 | , createby_(PU_SYSTEM) 604 | , type_(UNKNOWN) 605 | , arr_(nullptr) 606 | { 607 | debug(L, "waring call default __pi_var::construct"); 608 | } 609 | 610 | __pu_var::~__pu_var() 611 | { 612 | destroy(); 613 | } 614 | 615 | 616 | __pu_var::_scope::_smap::_smap(Pu *L) : vmap_(new StrKeyMap) 617 | , refcount(1) 618 | , marked(false) 619 | , L_(L) 620 | , gc_(true) 621 | { 622 | 623 | } 624 | 625 | 626 | __pu_var::_scope::_smap::_smap(Pu *L, StrKeyMap *__vmap) : vmap_(__vmap) 627 | , refcount(1) 628 | , marked(false) 629 | , L_(L) 630 | , gc_(false) 631 | { 632 | 633 | } 634 | 635 | __pu_var::_scope::_smap::~_smap() 636 | { 637 | if (gc_) 638 | { 639 | delete vmap_; 640 | vmap_ = nullptr; 641 | } 642 | } 643 | -------------------------------------------------------------------------------- /src/value.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009 Zhang li 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | 22 | MIT License: http://www.opensource.org/licenses/mit-license.php 23 | */ 24 | 25 | /* 26 | Author zhang li 27 | Email zlvbvbzl@gmail.com 28 | */ 29 | 30 | #ifndef __VM_VALUE__ 31 | #define __VM_VALUE__ 32 | 33 | #include "PuMap.h" 34 | #include "PuString.h" 35 | #include "config.h" 36 | #include 37 | #include 38 | #include 39 | #ifdef _MSC_VER 40 | #pragma warning(disable:4127) // while(1) 41 | #endif 42 | struct Pu; 43 | 44 | 45 | #define VALUE_IS_TRUE(v) \ 46 | ( \ 47 | ((v).type() == BOOLEANT)? \ 48 | ((v).intVal() != 0) \ 49 | \ 50 | :(((v).type() == INTEGER)? \ 51 | ((v).intVal() != 0) \ 52 | \ 53 | :(((v).type() == NUM)? \ 54 | ((v).numVal() != 0) \ 55 | \ 56 | :(((v).type() == CPTR)? \ 57 | (*(PU_INT*)&(v).intVal() != 0) \ 58 | \ 59 | :(((v).type() == STR)? \ 60 | ((v).strVal().length() != 0) \ 61 | \ 62 | :(((v).type() == ARRAY)? \ 63 | ((v).arr().size() != 0) \ 64 | \ 65 | :(((v).type() == MAP)? \ 66 | ((v).map().size() != 0) \ 67 | \ 68 | :(((v).type() == CORO)? \ 69 | ((v).intVal() != -1) \ 70 | \ 71 | :(((v).type() == FILEHANDLE)? \ 72 | ((v).file() != 0 ) \ 73 | \ 74 | :(((v).type() == FUN)? \ 75 | (true):(false) \ 76 | \ 77 | ))))))))) \ 78 | ) 79 | 80 | typedef enum PUVALUECREATEDBY{ 81 | PU_SYSTEM, 82 | PU_USER 83 | }PUVALUECREATEDBY; 84 | 85 | struct __pu_var 86 | { 87 | struct value_hash { 88 | size_t operator()(const __pu_var &__x) const 89 | { 90 | return __x.hash(); 91 | } 92 | }; 93 | 94 | struct value_eq { 95 | bool operator()(const __pu_var &__x, const __pu_var &__y) const 96 | { 97 | return (__x == __y) == 1; 98 | } 99 | }; 100 | 101 | struct strptr_hash { 102 | size_t operator()(const std::string *const &__x) const 103 | { 104 | return std::hash()(*__x); 105 | } 106 | }; 107 | 108 | struct strptr_eq { 109 | bool operator()(const std::string *const &__x, const std::string *const &__y) const 110 | { 111 | return *__x == *__y; 112 | } 113 | }; 114 | 115 | typedef std::unordered_map StrKeyMap; 116 | typedef PuVector<__pu_var> ValueArr; 117 | typedef PuMap<__pu_var, __pu_var, value_hash, value_eq> ValueMap; 118 | 119 | struct _scope 120 | { 121 | struct _smap 122 | { 123 | _smap(Pu *L); 124 | _smap(Pu *L, StrKeyMap *__vmap); 125 | ~_smap(); 126 | StrKeyMap *vmap_; 127 | int refcount; 128 | bool marked; 129 | Pu *L_; 130 | bool gc_; 131 | }; 132 | 133 | _scope(Pu *L) 134 | : base_(new _smap(L)) 135 | { } 136 | _scope(Pu *L, StrKeyMap *__vmap) 137 | : base_(new _smap(L, __vmap)) 138 | { } 139 | _scope(const _scope &x) 140 | : base_(x.base_) 141 | { 142 | if (base_) 143 | { 144 | base_->refcount++; 145 | } 146 | } 147 | ~_scope() 148 | { 149 | release(); 150 | } 151 | _scope &operator=(const _scope &x) 152 | { 153 | if (base_ != x.base_) 154 | { 155 | release(); 156 | base_ = x.base_; 157 | if (base_) 158 | { 159 | base_->refcount++; 160 | } 161 | } 162 | 163 | return *this; 164 | } 165 | _smap *base_; 166 | private: 167 | void release() 168 | { 169 | if (base_) 170 | { 171 | base_->refcount--; 172 | if (base_->refcount == 0) 173 | { 174 | delete base_; 175 | } 176 | base_ = nullptr; 177 | } 178 | } 179 | }; 180 | 181 | __pu_var(Pu *_L) 182 | :L(_L) 183 | , createby_(PU_SYSTEM) 184 | , type_(UNKNOWN) 185 | , arr_(nullptr) 186 | { 187 | } 188 | 189 | __pu_var(); 190 | 191 | __pu_var(const __pu_var &x) 192 | : L(x.L) 193 | , createby_(PU_SYSTEM) 194 | , type_(UNKNOWN) 195 | , arr_(nullptr) 196 | { 197 | *this = x; 198 | } 199 | 200 | ~__pu_var(); 201 | 202 | void operator =(const __pu_var &x); 203 | __pu_var operator +(const __pu_var &x); 204 | __pu_var operator -(const __pu_var &x); 205 | __pu_var operator /(const __pu_var &x); 206 | __pu_var operator %(const __pu_var &x); 207 | __pu_var operator *(const __pu_var &x); 208 | int operator >(const __pu_var &x) const; 209 | int operator <(const __pu_var &x) const; 210 | int operator >=(const __pu_var &x) const; 211 | int operator <=(const __pu_var &x) const; 212 | int operator !=(const __pu_var &x) const; 213 | int operator ==(const __pu_var &x) const; 214 | int operator ||(const __pu_var &x) const; 215 | int operator &&(const __pu_var &x) const; 216 | const __pu_var &operator +=(const __pu_var &x); 217 | const __pu_var &operator -=(const __pu_var &x); 218 | const __pu_var &operator *=(const __pu_var &x); 219 | const __pu_var &operator /=(const __pu_var &x); 220 | 221 | Pu *L; 222 | PUVALUECREATEDBY createby_; 223 | 224 | PuType type() const 225 | { 226 | return type_; 227 | } 228 | 229 | void SetType(PuType val) 230 | { 231 | if (val != type_) 232 | { 233 | destroy(); 234 | type_ = val; 235 | build(); 236 | } 237 | } 238 | 239 | unsigned int hash() const; 240 | 241 | ValueArr& arr() 242 | { 243 | #ifdef _DEBUG 244 | if (type() != ARRAY || !arr_) 245 | { 246 | assert(!"arr get value failed"); 247 | } 248 | #endif 249 | return *arr_; 250 | } 251 | 252 | const ValueArr& arr() const 253 | { 254 | #ifdef _DEBUG 255 | if (type() != ARRAY || !arr_) 256 | { 257 | assert(!"arr get value failed"); 258 | } 259 | #endif 260 | return *arr_; 261 | } 262 | 263 | ValueMap& map() 264 | { 265 | #ifdef _DEBUG 266 | if (type() != MAP || !map_) 267 | { 268 | assert(!"map get value failed"); 269 | } 270 | #endif 271 | return *map_; 272 | } 273 | 274 | const ValueMap& map() const 275 | { 276 | #ifdef _DEBUG 277 | if (type() != MAP || !map_) 278 | { 279 | assert(!"map get value failed"); 280 | } 281 | #endif 282 | return *map_; 283 | } 284 | 285 | PuString& strVal() 286 | { 287 | return *strVal_; 288 | } 289 | 290 | const PuString& strVal() const 291 | { 292 | #ifdef _DEBUG 293 | if (type() != STR || !strVal_) 294 | { 295 | assert(!"string get value failed"); 296 | } 297 | #endif 298 | return *strVal_; 299 | } 300 | 301 | PU_NUMBER& numVal() 302 | { 303 | return numVal_; 304 | } 305 | 306 | PU_INT& intVal() 307 | { 308 | return intVal_; 309 | } 310 | 311 | const PU_NUMBER& numVal() const 312 | { 313 | return numVal_; 314 | } 315 | 316 | const PU_INT& intVal() const 317 | { 318 | #ifdef _DEBUG 319 | if (type() != FUN && type() != BOOLEANT && type() != INTEGER && type() != CORO && type() != CFUN && type() != CPTR) 320 | { 321 | assert(!"integer get value failed"); 322 | } 323 | #endif 324 | return intVal_; 325 | } 326 | 327 | _scope &up_value() 328 | { 329 | return *upval_; 330 | } 331 | 332 | const _scope &up_value() const 333 | { 334 | return *upval_; 335 | } 336 | 337 | FILE *&file() 338 | { 339 | return pfile_; 340 | } 341 | 342 | FILE *const file() const 343 | { 344 | return pfile_; 345 | } 346 | 347 | void destroy(); 348 | 349 | private: 350 | 351 | void build(); 352 | PuType type_; 353 | union { 354 | PU_NUMBER numVal_; 355 | PU_INT intVal_; 356 | }; 357 | union { 358 | ValueArr *arr_; 359 | ValueMap *map_; 360 | PuString *strVal_; 361 | FILE *pfile_; 362 | _scope *upval_; 363 | }; 364 | }; 365 | 366 | typedef __pu_var::StrKeyMap StrKeyMap; 367 | typedef __pu_var::ValueArr ValueArr; 368 | typedef __pu_var::ValueMap ValueMap; 369 | typedef __pu_var::_scope _scope; 370 | 371 | 372 | #endif 373 | -------------------------------------------------------------------------------- /test/closure.pu: -------------------------------------------------------------------------------- 1 | def foo() 2 | a = 100 3 | def closure(x) 4 | return a + x 5 | end 6 | return closure 7 | end 8 | 9 | #c = foo() 10 | #write(c(4)) 11 | # write(c(200)) 12 | 13 | def ccc(x1,x2) 14 | write('ccc' + x1 + '\n') 15 | write('ccc' + x2 + '\n') 16 | write(x1+x2) 17 | end 18 | 19 | def xxx() 20 | write('xxx') 21 | x1 = 1 22 | return ccc(x1+1,1) 23 | end 24 | 25 | xxx() 26 | -------------------------------------------------------------------------------- /test/closure2.pu: -------------------------------------------------------------------------------- 1 | def gg(j) 2 | 3 | a=j 4 | 5 | def kk(p) 6 | write('kk p=' + p) 7 | return a+p 8 | end 9 | 10 | def ll(p) 11 | write('ll p=' + p) 12 | return kk(p) 13 | end 14 | 15 | return ll 16 | 17 | end 18 | 19 | v1 = gg(1) 20 | v2 = gg(2) 21 | r1 = get_var('v1')(9) 22 | r2 = v2(9) 23 | write(r2,'\n') 24 | write(r1,'\n') 25 | v1 = null 26 | v2 = null 27 | -------------------------------------------------------------------------------- /test/cmp/code1.pu: -------------------------------------------------------------------------------- 1 | start = time() 2 | i=2000000 3 | while i 4 | k=46 5 | a=1 6 | b=1 7 | while k > 1 8 | #write(a + '\n') 9 | c=b 10 | b=a+b 11 | a=c 12 | k=k-1 13 | end 14 | i=i-1 15 | end 16 | write(time() - start + '\n') 17 | write(a + '\n') 18 | -------------------------------------------------------------------------------- /test/code1.pu: -------------------------------------------------------------------------------- 1 | #计算裴波那契数列前46位,算10次 2 | 3 | i=10 4 | while i 5 | k=46 6 | a=1 7 | b=1 8 | while k 9 | write(a + '\n') 10 | c=b 11 | b=a+b 12 | a=c 13 | k=k-1 14 | end 15 | i=i-1 16 | end 17 | -------------------------------------------------------------------------------- /test/code2.pu: -------------------------------------------------------------------------------- 1 | # 输入3个数,按从小到大排列 2 | 3 | t=0 4 | x = read() 5 | y = read() 6 | z = read() 7 | 8 | if x>y 9 | t=x 10 | x=y 11 | y=t 12 | end 13 | 14 | if x>z 15 | t=z 16 | z=x 17 | x=t 18 | end 19 | 20 | if y>z 21 | t=y 22 | y=z 23 | z=t 24 | end 25 | 26 | write(x + ' ' + y + ' ' + z + '\n') 27 | -------------------------------------------------------------------------------- /test/code3.pu: -------------------------------------------------------------------------------- 1 | 2 | #输出素数 3 | #这是一个很复杂程序 4 | 5 | 6 | write('输入一个整数:') x=read() 7 | write('"'+x+'"以内所有素数\n') 8 | write(time()) 9 | i=2 10 | while i<=x 11 | k=1 is=0 12 | while k*k<=i 13 | if i % k == 0 && k>1 14 | is=0 15 | break 16 | end 17 | k+=1 18 | is=1 19 | end 20 | if is 21 | write(i + '\t') 22 | end 23 | i+=1 24 | end 25 | write('\n') 26 | write(time()) -------------------------------------------------------------------------------- /test/code4.pu: -------------------------------------------------------------------------------- 1 | #闭包 2 | def gg(j) 3 | a=j 4 | def kk(p) 5 | return a+p 6 | end 7 | return kk 8 | end 9 | 10 | v1 = gg(1) 11 | v2 = gg(2) 12 | 13 | r1 = v1(9) 14 | r2 = v2(9) 15 | 16 | write(r1+'\n') 17 | write(r2+'\n') 18 | -------------------------------------------------------------------------------- /test/code5.pu: -------------------------------------------------------------------------------- 1 | def aaa() 2 | write('111') 3 | end 4 | 5 | aaa() -------------------------------------------------------------------------------- /test/code6.pu: -------------------------------------------------------------------------------- 1 | # 文件读写 2 | o = open('code1.pu') 3 | w = open('hahah') 4 | s = read(o,'word') 5 | while s 6 | write(s+'\n') 7 | write(w,s) 8 | s = read(o,'word') 9 | end 10 | 11 | close(w) 12 | close(o) 13 | 14 | w = open('hahah') 15 | s = read(w,'word') 16 | while s 17 | write(s+'\n') 18 | s = read(w,'word') 19 | end 20 | 21 | close(w) -------------------------------------------------------------------------------- /test/code7.pu: -------------------------------------------------------------------------------- 1 | # 协程 2 | def coro1() 3 | write('1-1\n') 4 | coro_yield() 5 | write('1-2\n') 6 | end 7 | 8 | def coro2() 9 | write('2-1\n') 10 | coro_yield() 11 | write('2-2\n') 12 | end 13 | 14 | c1 = coro_create(coro1) 15 | c2 = coro_create(coro2) 16 | 17 | 18 | -------------------------------------------------------------------------------- /test/code8.pu: -------------------------------------------------------------------------------- 1 | s="12345" 2 | slen=len(s) 3 | idx=0 4 | while idx < slen 5 | if s[idx]=="3" 6 | write(idx) 7 | break 8 | end 9 | idx = idx + 1 10 | end 11 | 12 | @ 13 | if 1==2 14 | write(123) 15 | end 16 | write(333) 17 | @ 18 | -------------------------------------------------------------------------------- /test/code9.pu: -------------------------------------------------------------------------------- 1 | def fffff(b) 2 | a='ssssss\n' 3 | c = b + a 4 | return c * 100 5 | end 6 | 7 | idx = 10 8 | while idx > 0 9 | write(fffff('rr')) 10 | idx = idx - 1 11 | end 12 | -------------------------------------------------------------------------------- /test/console.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009 Zhang li 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | 22 | MIT License: http://www.opensource.org/licenses/mit-license.php 23 | */ 24 | 25 | /* 26 | Author zhang li 27 | Email zlvbvbzl@gmail.com 28 | */ 29 | 30 | #include 31 | #include 32 | #include "../puppy.h" 33 | extern void bi_return_null_func(Pu *L); 34 | // 用于控制台模式下的print函数 35 | void print(Pu *L, int argnum, pu_var *v) 36 | { 37 | if (v==nullptr) 38 | { 39 | printf("\n"); 40 | bi_return_null_func(L); 41 | return; 42 | } 43 | 44 | int i=0; 45 | while (i'); 109 | if (pu_readline(buff)) 110 | { 111 | int ret = pu_eval(L, buff); 112 | if (ret == -2) // input incompleted 113 | { 114 | putchar('>'); 115 | } 116 | } 117 | } 118 | } 119 | 120 | 121 | 122 | -------------------------------------------------------------------------------- /test/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009 Zhang li 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | 22 | MIT License: http://www.opensource.org/licenses/mit-license.php 23 | */ 24 | 25 | /* 26 | Author zhang li 27 | Email zlvbvbzl@gmail.com 28 | */ 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include "../puppy.h" 35 | 36 | void pu_console(Pu *L); 37 | 38 | int main(int argc, char **argv) 39 | { 40 | srand((unsigned int)time(nullptr)); 41 | Pu *L = pu_open(); 42 | if (argc < 2) 43 | { 44 | pu_console(L); 45 | pu_close(L); 46 | L = nullptr; 47 | } 48 | else 49 | { 50 | if (argc > 1 && strcmp(argv[1], "-c") == 0) 51 | { 52 | pu_makebytecode(L, argv[2]); 53 | pu_close(L); 54 | return 0; 55 | } 56 | 57 | if (pu_load(L, argv[1]) == PU_SUCCESS) 58 | { 59 | pu_run(L); 60 | } 61 | else 62 | { 63 | printf("%s\n", "error."); 64 | } 65 | pu_close(L); 66 | L = nullptr; 67 | 68 | #ifdef _WIN32 69 | system("pause"); 70 | #endif 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /test/map.pu: -------------------------------------------------------------------------------- 1 | a = {1:1, 's':'s'} 2 | 3 | def xx(x) 4 | write(x) 5 | end 6 | 7 | xx(a['s']) -------------------------------------------------------------------------------- /test/pertest.pu: -------------------------------------------------------------------------------- 1 | start = time() 2 | def func(x,y,z) 3 | return x*y/z 4 | end 5 | n = 3000000 6 | while n > 0 7 | a = func(n, n/2, n) 8 | n = n-1 9 | end 10 | 11 | write(time() - start + '\n') 12 | 13 | -------------------------------------------------------------------------------- /test/puppytest.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | vm 15 | {4D9EDFC1-94C2-4010-8B26-BC3A54ED08D5} 16 | zlltest 17 | Win32Proj 18 | 8.1 19 | 20 | 21 | 22 | Application 23 | v141 24 | Unicode 25 | 26 | 27 | Application 28 | v141 29 | Unicode 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | <_ProjectFileVersion>11.0.61030.0 43 | 44 | 45 | $(SolutionDir)\bin\ 46 | $(Configuration)\ 47 | puppy_d 48 | 49 | 50 | $(SolutionDir)\bin\ 51 | $(Configuration)\ 52 | puppy 53 | 54 | 55 | 56 | Disabled 57 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 58 | MultiThreadedDebug 59 | 60 | Level4 61 | EditAndContinue 62 | 63 | 64 | true 65 | Console 66 | false 67 | 68 | MachineX86 69 | 70 | 71 | md $(SolutionDir)output\ 72 | md $(SolutionDir)output\bin\ 73 | md $(SolutionDir)output\example\ 74 | copy /y $(TargetPath) $(SolutionDir)output\bin\ 75 | copy /y $(ProjectDir)*.pu $(SolutionDir)output\example\ 76 | 77 | 78 | 79 | 80 | 81 | false 82 | 83 | Level4 84 | MultiThreaded 85 | 86 | 87 | 88 | false 89 | 90 | MachineX86 91 | true 92 | Console 93 | 94 | 95 | md $(SolutionDir)output\ 96 | md $(SolutionDir)output\bin\ 97 | md $(SolutionDir)output\example\ 98 | copy /y $(TargetPath) $(SolutionDir)output\bin\ 99 | copy /y $(ProjectDir)*.pu $(SolutionDir)output\example\ 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | {e3e77aea-990a-45d8-880e-3e1a8d01b565} 117 | false 118 | 119 | 120 | 121 | 122 | 123 | -------------------------------------------------------------------------------- /test/puppytest.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /test/s.pu: -------------------------------------------------------------------------------- 1 | 2 | a = [10,9,8,7,6,5,4,3,2,1] 3 | sum = 0 4 | for i,v in a 5 | sum += v 6 | end 7 | 8 | writeln(sum) 9 | 10 | for i,v in 10 11 | sum += v 12 | end 13 | 14 | writeln(sum) 15 | 16 | a = {1:2, 2:9, 3:10} 17 | 18 | for i,v in a 19 | sum += v 20 | end 21 | 22 | writeln(sum) 23 | -------------------------------------------------------------------------------- /test/tailcall.pu: -------------------------------------------------------------------------------- 1 | def fb(a,b) 2 | write(b + '\n') 3 | return fb(b, a+b) 4 | end 5 | 6 | #fb(1,1) 7 | 8 | def kk(a) 9 | return 1 10 | end 11 | 12 | def ll(a) 13 | return 1 14 | end 15 | 16 | def gg() 17 | write('GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG\n') 18 | return kk(343+ 34) + ll(kk(23+45)+3535) 19 | end 20 | 21 | def pp() 22 | write('PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP\n') 23 | return kk(123+33) 24 | end 25 | 26 | gg() 27 | gg() 28 | pp() --------------------------------------------------------------------------------