Overview
SHA1 Hash: | 423f3083500d5e084547be815e518ea59b9908ac |
---|---|
Date: | 2010-11-07 19:18:02 |
User: | kinaba |
Comment: | Initial commit. Just for setting up the environment. |
Timelines: | family | ancestors | descendants | both | trunk |
Downloads: | Tarball | ZIP archive |
Other Links: | files | file ages | manifest |
Tags And Properties
- branch=trunk inherited from [f65680e1d2]
- sym-trunk inherited from [f65680e1d2]
Changes
Added .poseidon version [632d1802d130c7c4]
> 1 <?xml version="1.0" encoding="UTF-8" ?> > 2 <projectDescription> > 3 <style>0</style> > 4 <name>Polemy</name> > 5 <targetName>bin\polemy</targetName> > 6 <comment /> > 7 <filter>*.d</filter> > 8 <showemptyfolder>0</showemptyfolder> > 9 <buildSpec> > 10 <buildType>0</buildType> > 11 <mainFile>main.d</mainFile> > 12 <Args /> > 13 <options> > 14 <dmd> -g -unittest </dmd> > 15 <tool /> > 16 <lib /> > 17 <implib /> > 18 <extra /> > 19 <toolextra /> > 20 <merge>0</merge> > 21 <nonfiles>0</nonfiles> > 22 <useimplib>0</useimplib> > 23 <mapfile>0</mapfile> > 24 <gcstub>0</gcstub> > 25 </options> > 26 <dmdpath /> > 27 <dmcpath /> > 28 <buildtoolexe /> > 29 <projectFiles> > 30 <source> > 31 <name>d2stacktrace\dbghelp.d</name> > 32 <name>d2stacktrace\stacktrace.d</name> > 33 <name>main.d</name> > 34 <name>polemy\_common.d</name> > 35 <name>polemy\ast.d</name> > 36 <name>polemy\eval.d</name> > 37 <name>polemy\lex.d</name> > 38 <name>polemy\parse.d</name> > 39 <name>polemy\runtime.d</name> > 40 <name>polemy\tricks.d</name> > 41 </source> > 42 <interface /> > 43 <resource /> > 44 <othersDMD /> > 45 <others> > 46 <name>build.bat</name> > 47 <name>build.sh</name> > 48 <name>readme.txt</name> > 49 </others> > 50 </projectFiles> > 51 <includePaths /> > 52 <linkLibrarys /> > 53 <importExpressions /> > 54 </buildSpec> > 55 </projectDescription>
Added build.bat version [89e64358f6690364]
Added d2stacktrace/dbghelp.d version [8a71f59402b61712]
> 1 /************************************************************* > 2 Copyright (c) 2010 > 3 > 4 Benjamin Thaut. All rights reserved. > 5 > 6 Redistribution and use in source and binary forms, with or without modification, > 7 provided that the following conditions are met: > 8 > 9 1. Redistributions of source code must retain the above copyright notice, this > 10 and the following disclaimer. > 11 > 12 2. Redistributions in binary form must reproduce the above copyright notice, t > 13 and the following disclaimer in the documentation and/or other materials pr > 14 > 15 THIS SOFTWARE IS PROVIDED BY BENJAMIN THAUT "AS IS" AND ANY EXPRESS OR IMPLIED W > 16 BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A > 17 IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT > 18 OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITU > 19 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF > 20 STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY > 21 EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > 22 > 23 web: http://3d.benjamin-thaut.de > 24 *************************************************************/ > 25 module dbghelp; > 26 > 27 version (Windows){ > 28 > 29 import std.c.windows.windows; > 30 import core.runtime; > 31 > 32 class Dbghelp { > 33 public: > 34 typedef char TCHAR; > 35 typedef ulong DWORD64; > 36 typedef char* CTSTR; > 37 typedef char* PTSTR; > 38 typedef const(char)* PCSTR; > 39 > 40 enum ADDRESS_MODE : DWORD { > 41 AddrMode1616 = 0, > 42 AddrMode1632 = 1, > 43 AddrModeReal = 2, > 44 AddrModeFlat = 3 > 45 }; > 46 > 47 enum : DWORD { > 48 SYMOPT_FAIL_CRITICAL_ERRORS = 0x00000200, > 49 SYMOPT_LOAD_LINES = 0x00000010 > 50 }; > 51 > 52 struct GUID { > 53 uint Data1; > 54 ushort Data2; > 55 ushort Data3; > 56 ubyte[8] Data4; > 57 }; > 58 > 59 struct ADDRESS64 { > 60 DWORD64 Offset; > 61 WORD Segment; > 62 ADDRESS_MODE Mode; > 63 }; > 64 > 65 struct KDHELP64 { > 66 DWORD64 Thread; > 67 DWORD ThCallbackStack; > 68 DWORD ThCallbackBStore; > 69 DWORD NextCallback; > 70 DWORD FramePointer; > 71 DWORD64 KiCallUserMode; > 72 DWORD64 KeUserCallbackDispatcher; > 73 DWORD64 SystemRangeStart; > 74 DWORD64 KiUserExceptionDispatcher; > 75 DWORD64[7] Reserved; > 76 }; > 77 > 78 struct STACKFRAME64 { > 79 ADDRESS64 AddrPC; > 80 ADDRESS64 AddrReturn; > 81 ADDRESS64 AddrFrame; > 82 ADDRESS64 AddrStack; > 83 ADDRESS64 AddrBStore; > 84 PVOID FuncTableEntry; > 85 DWORD64[4] Params; > 86 BOOL Far; > 87 BOOL Virtual; > 88 DWORD64[3] Reserved; > 89 KDHELP64 KdHelp; > 90 }; > 91 > 92 enum : DWORD { > 93 IMAGE_FILE_MACHINE_I386 = 0x014c, > 94 IMGAE_FILE_MACHINE_IA64 = 0x0200, > 95 IMAGE_FILE_MACHINE_AMD64 = 0x8664 > 96 }; > 97 > 98 struct IMAGEHLP_LINE64 { > 99 DWORD SizeOfStruct; > 100 PVOID Key; > 101 DWORD LineNumber; > 102 PTSTR FileName; > 103 DWORD64 Address; > 104 }; > 105 > 106 enum SYM_TYPE : int { > 107 SymNone = 0, > 108 SymCoff, > 109 SymCv, > 110 SymPdb, > 111 SymExport, > 112 SymDeferred, > 113 SymSym, > 114 SymDia, > 115 SymVirtual, > 116 NumSymTypes > 117 }; > 118 > 119 struct IMAGEHLP_MODULE64 { > 120 DWORD SizeOfStruct; > 121 DWORD64 BaseOfImage; > 122 DWORD ImageSize; > 123 DWORD TimeDateStamp; > 124 DWORD CheckSum; > 125 DWORD NumSyms; > 126 SYM_TYPE SymType; > 127 TCHAR[32] ModuleName; > 128 TCHAR[256] ImageName; > 129 TCHAR[256] LoadedImageName; > 130 TCHAR[256] LoadedPdbName; > 131 DWORD CVSig; > 132 TCHAR[MAX_PATH*3] CVData; > 133 DWORD PdbSig; > 134 GUID PdbSig70; > 135 DWORD PdbAge; > 136 BOOL PdbUnmatched; > 137 BOOL DbgUnmachted; > 138 BOOL LineNumbers; > 139 BOOL GlobalSymbols; > 140 BOOL TypeInfo; > 141 BOOL SourceIndexed; > 142 BOOL Publics; > 143 }; > 144 > 145 struct IMAGEHLP_SYMBOL64 { > 146 DWORD SizeOfStruct; > 147 DWORD64 Address; > 148 DWORD Size; > 149 DWORD Flags; > 150 DWORD MaxNameLength; > 151 TCHAR[1] Name; > 152 }; > 153 > 154 extern(System){ > 155 typedef BOOL function(HANDLE hProcess, DWORD64 lpBaseAddress, PV > 156 typedef PVOID function(HANDLE hProcess, DWORD64 AddrBase) Functi > 157 typedef DWORD64 function(HANDLE hProcess, DWORD64 Address) GetMo > 158 typedef DWORD64 function(HANDLE hProcess, HANDLE hThread, ADDRES > 159 > 160 typedef BOOL function(HANDLE hProcess, PCSTR UserSearchPath, boo > 161 typedef BOOL function(HANDLE hProcess) SymCleanupFunc; > 162 typedef DWORD function(DWORD SymOptions) SymSetOptionsFunc; > 163 typedef DWORD function() SymGetOptionsFunc; > 164 typedef PVOID function(HANDLE hProcess, DWORD64 AddrBase) SymFun > 165 typedef BOOL function(DWORD MachineType, HANDLE hProcess, HANDLE > 166 ReadProcessMemoryProc64 ReadMemoryRoutine, > 167 GetModuleBaseProc64 GetModuleBaseRoutine, > 168 typedef BOOL function(HANDLE hProcess, DWORD64 dwAddr, PDWORD pd > 169 typedef DWORD64 function(HANDLE hProcess, DWORD64 dwAddr) SymGet > 170 typedef BOOL function(HANDLE hProcess, DWORD64 dwAddr, IMAGEHLP_ > 171 typedef BOOL function(HANDLE hProcess, DWORD64 Address, DWORD64 > 172 typedef DWORD function(CTSTR *DecoratedName, PTSTR UnDecoratedNa > 173 typedef DWORD64 function(HANDLE hProcess, HANDLE hFile, PCSTR Im > 174 typedef BOOL function(HANDLE HProcess, PTSTR SearchPath, DWORD S > 175 typedef BOOL function(HANDLE hProcess, DWORD64 Address) SymUnloa > 176 } > 177 > 178 private static bool isInit = false; > 179 private static HANDLE dbghelp_lib = cast(HANDLE)null; > 180 static SymInitializeFunc SymInitialize; > 181 static SymCleanupFunc SymCleanup; > 182 static StackWalk64Func StackWalk64; > 183 static SymGetOptionsFunc SymGetOptions; > 184 static SymSetOptionsFunc SymSetOptions; > 185 static SymFunctionTableAccess64Func SymFunctionTableAccess64; > 186 static SymGetLineFromAddr64Func SymGetLineFromAddr64; > 187 static SymGetModuleBase64Func SymGetModuleBase64; > 188 static SymGetModuleInfo64Func SymGetModuleInfo64; > 189 static SymGetSymFromAddr64Func SymGetSymFromAddr64; > 190 static UnDecorateSymbolNameFunc UnDecorateSymbolName; > 191 static SymLoadModule64Func SymLoadModule64; > 192 static SymGetSearchPathFunc SymGetSearchPath; > 193 static SymUnloadModule64Func SymUnloadModule64; > 194 > 195 static bool Init(){ > 196 if(isInit) > 197 return true; > 198 > 199 dbghelp_lib = cast(HANDLE)Runtime.loadLibrary("dbghelp.dll"); > 200 if(dbghelp_lib == null) > 201 return false; > 202 > 203 SymInitialize = cast(SymInitializeFunc) GetProcAddress(dbghelp_l > 204 SymCleanup = cast(SymCleanupFunc) GetProcAddress(dbghelp_lib,"Sy > 205 StackWalk64 = cast(StackWalk64Func) GetProcAddress(dbghelp_lib," > 206 SymGetOptions = cast(SymGetOptionsFunc) GetProcAddress(dbghelp_l > 207 SymSetOptions = cast(SymSetOptionsFunc) GetProcAddress(dbghelp_l > 208 SymFunctionTableAccess64 = cast(SymFunctionTableAccess64Func) Ge > 209 SymGetLineFromAddr64 = cast(SymGetLineFromAddr64Func) GetProcAdd > 210 SymGetModuleBase64 = cast(SymGetModuleBase64Func) GetProcAddress > 211 SymGetModuleInfo64 = cast(SymGetModuleInfo64Func) GetProcAddress > 212 SymGetSymFromAddr64 = cast(SymGetSymFromAddr64Func) GetProcAddre > 213 SymLoadModule64 = cast(SymLoadModule64Func) GetProcAddress(dbghe > 214 SymGetSearchPath = cast(SymGetSearchPathFunc) GetProcAddress(dbg > 215 SymUnloadModule64 = cast(SymUnloadModule64Func) GetProcAddress(d > 216 > 217 if(!SymInitialize || !SymCleanup || !StackWalk64 || !SymGetOptio > 218 || !SymGetLineFromAddr64 || !SymGetModuleBase64 || !SymGetMod > 219 || !SymLoadModule64 || !SymGetSearchPath || !SymUnloadModule6 > 220 return false; > 221 } > 222 > 223 isInit = true; > 224 return true; > 225 > 226 } > 227 > 228 void DeInit(){ > 229 if(isInit){ > 230 Runtime.unloadLibrary(dbghelp_lib); > 231 isInit = false; > 232 } > 233 } > 234 }; > 235 > 236 }
Added d2stacktrace/licence.txt version [f2d95378cd571501]
> 1 Copyright (c) 2010 > 2 > 3 Benjamin Thaut. All rights reserved. > 4 > 5 Redistribution and use in source and binary forms, with or without modification, > 6 provided that the following conditions are met: > 7 > 8 1. Redistributions of source code must retain the above copyright notice, this > 9 and the following disclaimer. > 10 > 11 2. Redistributions in binary form must reproduce the above copyright notice, t > 12 and the following disclaimer in the documentation and/or other materials pr > 13 > 14 THIS SOFTWARE IS PROVIDED BY BENJAMIN THAUT "AS IS" AND ANY EXPRESS OR IMPLIED W > 15 BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A > 16 IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT > 17 OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITU > 18 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF > 19 STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY > 20 EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > 21 > 22 web: http://3d.benjamin-thaut.de
Added d2stacktrace/readme.txt version [f18562976753621a]
> 1 I wrote a small piece of sourcecode that generates stacktraces in D 2.0 under wi > 2 > 3 > 4 It is very easy to use, just copy the two files from the zip archive to your roo > 5 > 6 import stacktrace; > 7 > 8 void main(string[] argv){ > 9 ... > 10 } > 11 > 12 Now all Errors will get trace information. > 13 If you need a backtrace at a certain point in your code just do the following: > 14 > 15 module foo; > 16 > 17 import stacktrace; > 18 > 19 void blup(){ > 20 ... > 21 StackTrace trace = new StackTrace(); > 22 auto stack = trace.GetCallstack(); > 23 foreach(char[] s;stack) > 24 writefln("%s",s); > 25 ... > 26 } > 27 > 28 It is released under the BSD license. If this licence causes any problems for yo > 29 > 30 XP Users: > 31 If you get a stacktrace with numbers only download a new version of dbghelp.dll
Added d2stacktrace/stacktrace.d version [02abce9abb958e1c]
> 1 /************************************************************* > 2 Copyright (c) 2010 > 3 > 4 Benjamin Thaut. All rights reserved. > 5 > 6 Redistribution and use in source and binary forms, with or without modification, > 7 provided that the following conditions are met: > 8 > 9 1. Redistributions of source code must retain the above copyright notice, this > 10 and the following disclaimer. > 11 > 12 2. Redistributions in binary form must reproduce the above copyright notice, t > 13 and the following disclaimer in the documentation and/or other materials pr > 14 > 15 THIS SOFTWARE IS PROVIDED BY BENJAMIN THAUT "AS IS" AND ANY EXPRESS OR IMPLIED W > 16 BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A > 17 IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT > 18 OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITU > 19 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF > 20 STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY > 21 EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > 22 > 23 web: http://3d.benjamin-thaut.de > 24 *************************************************************/ > 25 module stacktrace; > 26 > 27 import std.c.windows.windows; > 28 import std.c.string; > 29 import std.string; > 30 import dbghelp; > 31 import core.runtime; > 32 import std.stdio; > 33 import std.c.stdlib; > 34 import std.demangle; > 35 import std.conv; > 36 > 37 extern(Windows){ > 38 DWORD GetEnvironmentVariableA(LPCSTR lpName, LPSTR pBuffer, DWORD nSize) > 39 void RtlCaptureContext(CONTEXT* ContextRecord); > 40 typedef LONG function(void*) UnhandeledExceptionFilterFunc; > 41 void* SetUnhandledExceptionFilter(void* handler); > 42 } > 43 > 44 class StackTrace { > 45 private: > 46 enum : uint { > 47 MAX_MODULE_NAME32 = 255, > 48 TH32CS_SNAPMODULE = 0x00000008, > 49 MAX_NAMELEN = 1024 > 50 }; > 51 > 52 struct MODULEENTRY32 { > 53 DWORD dwSize; > 54 DWORD th32ModuleID; > 55 DWORD th32ProcessID; > 56 DWORD GlblcntUsage; > 57 DWORD ProccntUsage; > 58 BYTE* modBaseAddr; > 59 DWORD modBaseSize; > 60 HMODULE hModule; > 61 CHAR[MAX_MODULE_NAME32 + 1] szModule; > 62 CHAR[MAX_PATH] szExePath; > 63 }; > 64 > 65 string m_UserSymPath; > 66 static bool isInit = false; > 67 static bool modulesLoaded = false; > 68 > 69 extern(System){ > 70 typedef HANDLE function(DWORD dwFlags, DWORD th32ProcessID) Crea > 71 typedef BOOL function(HANDLE hSnapshot, MODULEENTRY32 *lpme) Mod > 72 typedef BOOL function(HANDLE hSnapshot, MODULEENTRY32 *lpme) Mod > 73 } > 74 > 75 extern(Windows) static LONG UnhandeledExceptionFilterHandler(void* info) > 76 printStackTrace(); > 77 return 0; > 78 } > 79 > 80 static void printStackTrace(){ > 81 auto stack = TraceHandler(null); > 82 foreach(char[] s;stack){ > 83 writefln("%s",s); > 84 } > 85 } > 86 > 87 bool LoadModules(HANDLE hProcess, DWORD pid){ > 88 if(modulesLoaded) > 89 return true; > 90 > 91 CreateToolhelp32SnapshotFunc CreateToolhelp32Snapshot = null; > 92 Module32FirstFunc Module32First = null; > 93 Module32NextFunc Module32Next = null; > 94 > 95 HMODULE hDll = null; > 96 > 97 string[] searchDlls = [ "kernel32.dll", "tlhelp32.dll" ]; > 98 foreach(dll;searchDlls){ > 99 hDll = cast(HMODULE)Runtime.loadLibrary(dll); > 100 if(hDll == null) > 101 break; > 102 CreateToolhelp32Snapshot = cast(CreateToolhelp32Snapshot > 103 Module32First = cast(Module32FirstFunc) GetProcAddress(h > 104 Module32Next = cast(Module32NextFunc) GetProcAddress(hDl > 105 if(CreateToolhelp32Snapshot != null && Module32First != > 106 break; > 107 Runtime.unloadLibrary(hDll); > 108 hDll = null; > 109 } > 110 > 111 if(hDll == null){ > 112 return false; > 113 } > 114 > 115 HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid); > 116 if(hSnap == cast(HANDLE) -1) > 117 return false; > 118 > 119 MODULEENTRY32 ModuleEntry; > 120 memset(&ModuleEntry,0,MODULEENTRY32.sizeof); > 121 ModuleEntry.dwSize = MODULEENTRY32.sizeof; > 122 > 123 bool more = cast(bool)Module32First(hSnap,&ModuleEntry); > 124 int count = 0; > 125 while(more){ > 126 LoadModule(hProcess, ModuleEntry.szExePath.ptr, ModuleEn > 127 count++; > 128 more = cast(bool)Module32Next(hSnap,&ModuleEntry); > 129 } > 130 > 131 CloseHandle(hSnap); > 132 Runtime.unloadLibrary(hDll); > 133 > 134 if(count <= 0) > 135 return false; > 136 > 137 modulesLoaded = true; > 138 return true; > 139 } > 140 > 141 void LoadModule(HANDLE hProcess, LPCSTR img, LPCSTR mod, Dbghelp.DWORD64 > 142 char[] szImg = new char[strlen(img)]; > 143 char[] szMod = new char[strlen(mod)]; > 144 szImg[0..szImg.length] = img[0..(strlen(img))]; > 145 szMod[0..szMod.length] = mod[0..(strlen(mod))]; > 146 > 147 Dbghelp.DWORD64 moduleAddr = Dbghelp.SymLoadModule64(hProcess,HA > 148 if(moduleAddr == 0) > 149 return; > 150 > 151 Dbghelp.IMAGEHLP_MODULE64 ModuleInfo; > 152 memset(&ModuleInfo,0,typeof(ModuleInfo).sizeof); > 153 ModuleInfo.SizeOfStruct = typeof(ModuleInfo).sizeof; > 154 if(Dbghelp.SymGetModuleInfo64(hProcess,moduleAddr,&ModuleInfo) = > 155 if(ModuleInfo.SymType == Dbghelp.SYM_TYPE.SymNone){ > 156 Dbghelp.SymUnloadModule64(hProcess,moduleAddr); > 157 moduleAddr = Dbghelp.SymLoadModule64(hProcess,HA > 158 if(moduleAddr == 0) > 159 return; > 160 } > 161 } > 162 > 163 //writefln("Successfully loaded module %s",szImg); > 164 } > 165 > 166 string GenereateSearchPath(){ > 167 string path; > 168 if(m_UserSymPath.length){ > 169 path = m_UserSymPath ~ ";"; > 170 } > 171 > 172 char[1024] temp; > 173 if(GetCurrentDirectoryA(temp.length,temp.ptr) > 0){ > 174 temp[temp.length-1] = 0; > 175 path ~= temp ~ ";"; > 176 } > 177 > 178 if(GetModuleFileNameA(null,temp.ptr,temp.length) > 0){ > 179 temp[temp.length-1] = 0; > 180 foreach_reverse(ref char e;temp){ > 181 if(e == '\\' || e == '/' || e == ':'){ > 182 e = 0; > 183 break; > 184 } > 185 } > 186 if(strlen(temp.ptr) > 0){ > 187 path ~= temp ~ ";"; > 188 } > 189 } > 190 > 191 string[] systemVars = [ "_NT_SYMBOL_PATH", "_NT_ALTERNATE_SYMBOL > 192 > 193 foreach(e;systemVars){ > 194 if(GetEnvironmentVariableA(toStringz(e),temp.ptr,temp.le > 195 temp[temp.length-1] = 0; > 196 path ~= temp ~ ";"; > 197 } > 198 } > 199 > 200 return path; > 201 } > 202 > 203 static class Callstack : Throwable.TraceInfo { > 204 private: > 205 string[] info = null; > 206 public: > 207 int opApply(scope int delegate(ref char[]) dg){ > 208 int result = 0; > 209 foreach(e;info){ > 210 char[] temp = to!(char[])(e); > 211 result = dg(temp); > 212 if(result) > 213 break; > 214 } > 215 return result; > 216 } > 217 > 218 override string toString(){ > 219 string result = ""; > 220 foreach(e;info){ > 221 result ~= e ~ "\n"; > 222 } > 223 return result; > 224 } > 225 > 226 void append(string str){ > 227 if(info is null){ > 228 info = new string[1]; > 229 info[0] = str; > 230 } > 231 else { > 232 info.length = info.length + 1; > 233 info[info.length-1] = str; > 234 } > 235 } > 236 } > 237 > 238 static Throwable.TraceInfo TraceHandler(void* ptr){ > 239 StackTrace trace = new StackTrace(); > 240 return trace.GetCallstack(); > 241 } > 242 > 243 public: > 244 static this(){ > 245 Runtime.traceHandler(&TraceHandler); > 246 SetUnhandledExceptionFilter(&UnhandeledExceptionFilterHandler); > 247 } > 248 > 249 this(){ > 250 if(isInit) > 251 return; > 252 HANDLE hProcess = GetCurrentProcess(); > 253 DWORD pid = GetCurrentProcessId(); > 254 > 255 Dbghelp.Init(); > 256 string symPath = GenereateSearchPath(); > 257 if(Dbghelp.SymInitialize(hProcess,cast(Dbghelp.PCSTR)toStringz(s > 258 isInit = true; > 259 > 260 DWORD symOptions = Dbghelp.SymGetOptions(); > 261 symOptions |= Dbghelp.SYMOPT_LOAD_LINES; > 262 symOptions |= Dbghelp.SYMOPT_FAIL_CRITICAL_ERRORS; > 263 symOptions = Dbghelp.SymSetOptions(symOptions); > 264 > 265 LoadModules(hProcess,pid); > 266 } > 267 } > 268 > 269 Throwable.TraceInfo GetCallstack(){ > 270 if(!isInit){ > 271 writefln("Is not init!"); > 272 return null; > 273 } > 274 > 275 HANDLE hThread = GetCurrentThread(); > 276 HANDLE hProcess = GetCurrentProcess(); > 277 > 278 //Capture the current context > 279 CONTEXT c; > 280 memset(&c, 0, CONTEXT.sizeof); > 281 c.ContextFlags = CONTEXT_FULL; > 282 RtlCaptureContext(&c); > 283 > 284 Dbghelp.STACKFRAME64 stackframe; > 285 memset(&stackframe,0,typeof(stackframe).sizeof); > 286 DWORD imageType; > 287 //x86 > 288 imageType = Dbghelp.IMAGE_FILE_MACHINE_I386; > 289 stackframe.AddrPC.Offset = cast(Dbghelp.DWORD64)c.Eip; > 290 stackframe.AddrPC.Mode = Dbghelp.ADDRESS_MODE.AddrModeFlat; > 291 stackframe.AddrFrame.Offset = cast(Dbghelp.DWORD64)c.Ebp; > 292 stackframe.AddrFrame.Mode = Dbghelp.ADDRESS_MODE.AddrModeFlat; > 293 stackframe.AddrStack.Offset = cast(Dbghelp.DWORD64)c.Esp; > 294 stackframe.AddrStack.Mode = Dbghelp.ADDRESS_MODE.AddrModeFlat; > 295 > 296 size_t SymbolSize = Dbghelp.IMAGEHLP_SYMBOL64.sizeof + MAX_NAMEL > 297 Dbghelp.IMAGEHLP_SYMBOL64 *Symbol = cast(Dbghelp.IMAGEHLP_SYMBOL > 298 memset(Symbol,0,SymbolSize); > 299 Symbol.SizeOfStruct = SymbolSize; > 300 Symbol.MaxNameLength = MAX_NAMELEN; > 301 > 302 Dbghelp.IMAGEHLP_LINE64 Line; > 303 memset(&Line,0,typeof(Line).sizeof); > 304 Line.SizeOfStruct = typeof(Line).sizeof; > 305 > 306 Dbghelp.IMAGEHLP_MODULE64 Module; > 307 memset(&Module,0,typeof(Module).sizeof); > 308 Module.SizeOfStruct = typeof(Module).sizeof; > 309 > 310 auto stack = new Callstack(); > 311 > 312 //writefln("Callstack:"); > 313 for(int frameNum=0;;frameNum++){ > 314 if(Dbghelp.StackWalk64(imageType, hProcess, hThread, > 315 &stackframe, &c, > 316 null, > 317 cast(Dbghelp.FunctionTableAccessProc > 318 cast(Dbghelp.GetModuleBaseProc64)Dbg > 319 null) != TRUE ) > 320 { > 321 //writefln("End of Callstack"); > 322 break; > 323 } > 324 > 325 if(stackframe.AddrPC.Offset == stackframe.AddrReturn.Off > 326 //writefln("Endless callstack"); > 327 stack.append("Endless callstack"); > 328 break; > 329 } > 330 > 331 if(stackframe.AddrPC.Offset != 0){ > 332 string lineStr = ""; > 333 Dbghelp.DWORD64 offsetFromSymbol = cast(Dbghelp. > 334 if( Dbghelp.SymGetSymFromAddr64(hProcess,stackfr > 335 char[] symName = new char[strlen(cast(co > 336 memcpy(symName.ptr,Symbol.Name.ptr,symNa > 337 string symString = ""; > 338 if(symName[0] == 'D') > 339 symString = "_"; > 340 symString ~= symName; > 341 > 342 string demangeledName = demangle(symStri > 343 lineStr ~= demangeledName; > 344 > 345 DWORD zeichen = 0; > 346 if(Dbghelp.SymGetLineFromAddr64(hProcess > 347 char[] fileName = new char[strle > 348 fileName[] = Line.FileName[0..fi > 349 lineStr = to!string(fileName ~ " > 350 } > 351 } > 352 else { > 353 lineStr = to!string(cast(ulong)stackfram > 354 } > 355 lineStr = to!string(frameNum-2) ~ " " ~ lineStr; > 356 if(frameNum-2 < 10) > 357 lineStr = "0" ~ lineStr; > 358 if(frameNum >= 2) > 359 stack.append(lineStr); > 360 } > 361 } > 362 > 363 free(Symbol); > 364 return stack; > 365 } > 366 };
Added main.d version [a3deb465ebfdf083]
> 1 /* > 2 * Author: k.inaba > 3 * License: NYSL 0.9982 (http://www.kmonos.net/nysl/ > 4 * Entry point for the polemy interpreter > 5 */ > 6 > 7 import std.stdio; > 8 import polemy.lex; > 9 import polemy.parse; > 10 > 11 static ~this() { readln(); } // workaround for enabling "pause" under Poseidon > 12 > 13 void main() > 14 { > 15 writeln( "test ok" ); > 16 }
Added polemy/_common.d version [6dd1b05b349c9906]
> 1 module polemy._common; > 2 /* > 3 * Author: k.inaba > 4 * License: NYSL 0.9982 (http://www.kmonos.net/nysl/ > 5 * "Always-opend" modules inside polemy > 6 */ > 7 > 8 public import std.array; > 9 public import std.range; > 10 public import std.algorithm; > 11 public import std.conv : to; > 12 public import std.bigint; > 13 public import polemy.tricks;
Added polemy/ast.d version [cc116d74213b45fc]
> 1 module polemy.ast; > 2 import polemy._common; > 3 /* > 4 * Author: k.inaba > 5 * License: NYSL 0.9982 (http://www.kmonos.net/nysl/ > 6 * Syntax tree for the polemy programming language > 7 */ > 8 > 9 import polemy.lex : LexPosition; > 10 > 11 alias Statement[] Program; > 12 > 13 abstract class Statement > 14 { > 15 immutable LexPosition pos; > 16 mixin SimpleConstructor; > 17 } > 18 > 19 class DeclStatement : Statement > 20 { > 21 string var; > 22 Expression expr; > 23 mixin SimpleConstructor; > 24 mixin SimpleCompare; // do not take "pos" into account > 25 } > 26 > 27 class ExprStatement : Statement > 28 { > 29 Expression expr; > 30 mixin SimpleConstructor; > 31 mixin SimpleCompare; // do not take "pos" into account > 32 } > 33 > 34 abstract class Expression > 35 { > 36 immutable LexPosition pos; > 37 mixin SimpleConstructor; > 38 mixin SimpleCompare; // do not take "pos" into account > 39 } > 40 > 41 class StrLiteralExpression : Expression > 42 { > 43 string data; > 44 mixin SimpleConstructor; > 45 mixin SimpleCompare; // do not take "pos" into account > 46 } > 47 > 48 class IntLiteralExpression : Expression > 49 { > 50 BigInt data; > 51 mixin SimpleConstructor; > 52 mixin SimpleCompare; // do not take "pos" into account > 53 } > 54 > 55 class VarExpression : Expression > 56 { > 57 string var; > 58 mixin SimpleConstructor; > 59 mixin SimpleCompare; // do not take "pos" into account > 60 } > 61 > 62 class BinOpExpression : Expression > 63 { > 64 string op; > 65 Expression lhs; > 66 Expression rhs; > 67 mixin SimpleConstructor; > 68 mixin SimpleCompare; // do not take "pos" into account > 69 }
Added polemy/eval.d version [bedecb22284cfae9]
> 1 module polemy.eval; > 2 import polemy._common; > 3 /* > 4 * Author: k.inaba > 5 * License: NYSL 0.9982 (http://www.kmonos.net/nysl/ > 6 * Evaluator for the polemy programming language > 7 */ > 8 import polemy.ast; > 9 import polemy.runtime; > 10 > 11 Context eval(Program prog) > 12 { > 13 return eval(prog, new Context); > 14 } > 15 > 16 Context eval(Program prog, Context ctx) > 17 { > 18 foreach(s; prog) > 19 ctx = eval(s, ctx); > 20 return ctx; > 21 } > 22 > 23 Context eval(Statement _s, Context ctx) > 24 { > 25 if( auto s = cast(DeclStatement)_s ) > 26 { > 27 auto v = eval(s.expr, ctx); > 28 ctx.add(s.var, v); > 29 return ctx; > 30 } > 31 else > 32 if( auto s = cast(ExprStatement)_s ) > 33 { > 34 eval(s.expr, ctx); > 35 return ctx; > 36 } > 37 throw new PolemyRuntimeException(sprintf!"Unknown Kind of Statement %s a > 38 } > 39 > 40 Value eval(Expression _e, Context ctx) > 41 { > 42 if( auto e = cast(StrLiteralExpression)_e ) > 43 { > 44 return new StrValue(e.data); > 45 } > 46 else > 47 if( auto e = cast(IntLiteralExpression)_e ) > 48 { > 49 return new IntValue(e.data); > 50 } > 51 else > 52 if( auto e = cast(VarExpression)_e ) > 53 { > 54 return ctx[e.var]; > 55 } > 56 else > 57 if( auto e = cast(BinOpExpression)_e ) > 58 { > 59 if( e.op == "=" ) > 60 { > 61 if( auto ev = cast(VarExpression)e.lhs ) > 62 { > 63 Value r = eval(e.rhs, ctx); > 64 ctx[ev.var] = r; > 65 return r; > 66 } > 67 throw new PolemyRuntimeException(sprintf!"Lhs of assignm > 68 } > 69 > 70 Value l = eval(e.lhs, ctx); > 71 Value r = eval(e.rhs, ctx); > 72 if( auto lv = cast(IntValue)l ) > 73 if( auto rv = cast(IntValue)r ) > 74 final switch(e.op) > 75 { > 76 case "+": return new IntValue(lv.data+rv.data); > 77 case "-": return new IntValue(lv.data-rv.data); > 78 case "*": return new IntValue(lv.data*rv.data); > 79 case "/": return new IntValue(lv.data/rv.data); > 80 } > 81 else > 82 throw new PolemyRuntimeException(sprintf!"rhs of > 83 else > 84 throw new PolemyRuntimeException(sprintf!"lhs of %s must > 85 } > 86 throw new PolemyRuntimeException(sprintf!"Unknown Kind of Expression %s > 87 } > 88 > 89 > 90 version(unittest) import polemy.parse; > 91 version(unittest) import std.stdio; > 92 version(unittest) import std.exception; > 93 unittest > 94 { > 95 auto parser = parserFromString(`var x = 21; x = x + x*x;`); > 96 auto prog = parser.parseProgram(); > 97 auto ctx = eval(prog); > 98 assert( ctx["x"] == new IntValue(BigInt(21+21*21)) ); > 99 assert( !collectException(ctx["x"]) ); > 100 assert( collectException(ctx["y"]) ); > 101 } > 102 unittest > 103 { > 104 auto parser = parserFromString(`var x = 21; x = x + x*y;`); > 105 auto prog = parser.parseProgram(); > 106 assert( collectException(eval(prog)) ); > 107 } > 108 unittest > 109 { > 110 auto parser = parserFromString(`var x = 21; y = x + x*x;`); > 111 auto prog = parser.parseProgram(); > 112 assert( collectException(eval(prog)) ); > 113 }
Added polemy/lex.d version [fb194a438f1088e9]
> 1 module polemy.lex; > 2 import polemy._common; > 3 /* > 4 * Author: k.inaba > 5 * License: NYSL 0.9982 (http://www.kmonos.net/nysl/ > 6 * Lexer for the polemy programming language > 7 */ > 8 > 9 import std.file : readText; > 10 import std.string : munch; > 11 import std.ctype; > 12 > 13 /// Represents a position in a source code > 14 > 15 class LexPosition > 16 { > 17 immutable string filename; ///< name of the source file > 18 immutable int lineno; ///< line number: 1, 2, ... > 19 immutable int column; ///< column: 1, 2, ... > 20 > 21 override string toString() const > 22 { return sprintf!"%s:%d:%d"(filename, lineno, column); } > 23 > 24 mixin SimpleConstructor; > 25 mixin SimpleCompare; > 26 } > 27 > 28 unittest > 29 { > 30 auto p = new LexPosition("hello.cpp", 123, 45); > 31 auto q = new LexPosition("hello.cpp", 123, 46); > 32 > 33 assert( p.filename == "hello.cpp" ); > 34 assert( p.lineno == 123 ); > 35 assert( p.column == 45 ); > 36 assert( to!string(p) == "hello.cpp:123:45" ); > 37 assert( p < q ); > 38 assert( p != q ); > 39 > 40 assert( !__traits(compiles, new LexPosition) ); > 41 assert( !__traits(compiles, p.filename="foo") ); > 42 assert( !__traits(compiles, p.lineno =789) ); > 43 assert( !__traits(compiles, p.column =222) ); > 44 } > 45 > 46 /// Represents a lexer token > 47 > 48 class Token > 49 { > 50 enum Kind {identifier, stringLiteral, number}; > 51 immutable LexPosition pos; ///< position where the token occurred in th > 52 immutable string str; ///< the token string itself > 53 immutable Kind kind; ///< which kind of token? > 54 > 55 mixin SimpleConstructor; > 56 mixin SimpleCompare; > 57 } > 58 > 59 unittest > 60 { > 61 auto p = new immutable(LexPosition)("hello.cpp", 123, 45); > 62 auto t = new Token(p, "class", Token.Kind.identifier); > 63 > 64 assert( t.pos == p ); > 65 assert( t.str == "class" ); > 66 assert( t == new Token(p, "class", Token.Kind.identifier) ); > 67 assert( t < new Token(p, "struct", Token.Kind.identifier) ); > 68 > 69 assert( !__traits(compiles, new Token) ); > 70 assert( !__traits(compiles, t.pos=p) ); > 71 assert( !__traits(compiles, t.str=789) ); > 72 } > 73 > 74 /// Named Construtor for Lexer > 75 > 76 Lexer lexerFromFile(T...)( string filename, T rest ) > 77 { > 78 return lexerFromString( std.file.readText(filename), filename, rest ); > 79 } > 80 > 81 /// Named Construtor for Lexer > 82 > 83 Lexer lexerFromString( string str, string filename="<unnamed>", int lineno=1, in > 84 { > 85 return new Lexer(str, filename, lineno, column); > 86 } > 87 > 88 /// Lexer is a forward range of Tokens > 89 > 90 class Lexer > 91 { > 92 bool empty() /*@property*/ > 93 { > 94 return current is null; > 95 } > 96 > 97 Token front() /*@property*/ > 98 { > 99 return std.exception.enforce(current, "Lexer has already reached > 100 } > 101 > 102 void popFront() /*@property*/ > 103 { > 104 std.exception.enforce(current, "Lexer has already reached the en > 105 current = readNext(); > 106 } > 107 > 108 Lexer save() /*@property*/ > 109 { > 110 return new Lexer(buffer, filename, lineno, column, current); > 111 } > 112 > 113 private: // implementation > 114 > 115 string buffer; > 116 string filename; > 117 int lineno; > 118 int column; > 119 Token current; > 120 > 121 invariant() > 122 { > 123 assert( buffer.empty || !std.ctype.isspace(buffer[0]) ); > 124 } > 125 > 126 this( string buffer, string filename, int lineno, int column, Token curr > 127 { > 128 this.buffer = buffer; > 129 this.filename = filename; > 130 this.lineno = lineno; > 131 this.column = column; > 132 skipws(); > 133 this.current = (current is null ? readNext() : current); > 134 } > 135 > 136 void skipws() > 137 { > 138 bool progress = false; > 139 do > 140 { > 141 string ws = buffer.munch(" \t"); > 142 column += ws.length; > 143 progress = !ws.empty; > 144 while( !buffer.empty && (buffer[0]=='\r' || buffer[0]==' > 145 { > 146 progress = true; > 147 if( buffer[0] == '\n' ) > 148 buffer = buffer[1..$]; > 149 else // if( buffer.front == '\r' ) > 150 { > 151 buffer = buffer[1..$]; > 152 if( !buffer.empty && buffer[0]=='\n' ) > 153 buffer = buffer[1..$]; > 154 } > 155 lineno ++; > 156 column = 1; > 157 } > 158 }while( progress ); > 159 } > 160 > 161 char readChar() > 162 { > 163 scope(exit) { > 164 buffer = buffer[1..$]; > 165 column ++; > 166 } > 167 return buffer[0]; > 168 } > 169 > 170 /// This is the main lexing routine > 171 Token readNext() > 172 { > 173 if( buffer.empty ) > 174 return null; > 175 scope(exit) > 176 skipws(); > 177 > 178 if( isSymbol(buffer[0]) ) > 179 { > 180 if( buffer[0] == '#' ) > 181 { > 182 // skip comment > 183 while( !buffer.empty && (buffer[0]!='\n' && buff > 184 readChar(); > 185 skipws(); > 186 return readNext(); > 187 } > 188 else if( buffer[0] == '"' ) > 189 { > 190 // string literal > 191 auto pos = currentPosition(); > 192 string lit; > 193 readChar(); > 194 while( !buffer.empty && buffer[0]!='"' ) > 195 { > 196 // read one char > 197 char c = readChar(); > 198 if( c == '\\' ) > 199 { > 200 if( !buffer.empty && (buffer[0]= > 201 lit ~= readChar(); > 202 else > 203 lit ~= c; > 204 } > 205 else if( c == '\n' ) > 206 { > 207 lit ~= c; > 208 lineno++; > 209 column = 1; > 210 } > 211 else if( c == '\r' ) > 212 { > 213 if( !buffer.empty && buffer[0]== > 214 readChar(); > 215 lit ~= '\n'; > 216 lineno++; > 217 column = 1; > 218 } > 219 else > 220 lit ~= c; > 221 } > 222 if( !buffer.empty ) > 223 readChar(); > 224 return new Token(pos, lit, Token.Kind.stringLite > 225 } > 226 else > 227 { > 228 // normal symbol > 229 auto pos = currentPosition(); > 230 auto str = ""~readChar(); > 231 return new Token(pos, str, Token.Kind.identifier > 232 } > 233 } > 234 else > 235 { > 236 auto pos = currentPosition(); > 237 int i = 0; > 238 while( i<buffer.length && !std.ctype.isspace(buffer[i]) > 239 ++i; > 240 auto str = buffer[0 .. i]; > 241 buffer = buffer[i .. $]; > 242 column += i; > 243 bool isNumber = find!(`a<'0' || '9'<a`)(str).empty; > 244 return new Token(pos, str, isNumber ? Token.Kind.number > 245 } > 246 } > 247 > 248 bool isSymbol(char c) > 249 { > 250 return (0x21<=c && c<=0x7f && !std.ctype.isalnum(c) && c!='_'); > 251 } > 252 > 253 immutable(LexPosition) currentPosition() > 254 { > 255 return new immutable(LexPosition)(filename, lineno, column); > 256 } > 257 } > 258 > 259 unittest > 260 { > 261 assert( std.range.isForwardRange!(Lexer) ); > 262 } > 263 > 264 unittest > 265 { > 266 auto lex = lexerFromString("this is a \t\n pen :-( "); > 267 Token[] ts = std.array.array(lex); > 268 > 269 assert( ts[0].pos.lineno == 1 ); > 270 assert( ts[0].pos.column == 1 ); > 271 assert( ts[0].kind == Token.Kind.identifier ); > 272 assert( ts[0].str == "this" ); > 273 > 274 assert( ts[1].pos.lineno == 1 ); > 275 assert( ts[1].pos.column == 6 ); > 276 assert( ts[1].kind == Token.Kind.identifier ); > 277 assert( ts[1].str == "is" ); > 278 > 279 assert( ts[2].pos.lineno == 1 ); > 280 assert( ts[2].pos.column == 9 ); > 281 assert( ts[2].kind == Token.Kind.identifier ); > 282 assert( ts[2].str == "a" ); > 283 > 284 assert( ts[3].pos.lineno == 2 ); > 285 assert( ts[3].pos.column == 2 ); > 286 assert( ts[3].kind == Token.Kind.identifier ); > 287 assert( ts[3].str == "pen" ); > 288 > 289 // consecutive symbols are always separated > 290 // hence, no "++" or "<<" or ... > 291 > 292 assert( ts[4].pos.lineno == 2 ); > 293 assert( ts[4].pos.column == 6 ); > 294 assert( ts[4].str == ":" ); > 295 > 296 assert( ts[5].pos.lineno == 2 ); > 297 assert( ts[5].pos.column == 7 ); > 298 assert( ts[5].str == "-" ); > 299 > 300 assert( ts[6].pos.lineno == 2 ); > 301 assert( ts[6].pos.column == 8 ); > 302 assert( ts[6].str == "(" ); > 303 > 304 assert( ts.length == 7 ); > 305 } > 306 > 307 unittest > 308 { > 309 auto lex2 = lexerFromString(" a12\n3a 5 "); > 310 assert( lex2.front.str == "a12" ); > 311 assert( lex2.front.kind == Token.Kind.identifier ); > 312 lex2.popFront; > 313 auto lex3 = lex2.save; > 314 assert( lex2.front.str == "3a" ); > 315 assert( lex2.front.kind == Token.Kind.identifier ); > 316 lex2.popFront; > 317 assert( lex3.front.str == "3a" ); > 318 assert( lex3.front.kind == Token.Kind.identifier ); > 319 assert( lex2.front.str == "5" ); > 320 assert( lex2.front.kind == Token.Kind.number ); > 321 lex2.popFront; > 322 lex3.popFront; > 323 assert( lex2.empty ); > 324 assert( !lex3.empty ); > 325 assert( lex3.front.str == "5" ); > 326 assert( lex3.front.kind == Token.Kind.number ); > 327 } > 328 > 329 unittest > 330 { > 331 //!! be sure to run the unittest on the root of the source directory > 332 auto lexf = lexerFromFile("polemy/lex.d"); > 333 assert( lexf.front.str == "module", lexf.front.str ); > 334 assert( lexf.front.pos.filename == "polemy/lex.d" ); > 335 assert( lexf.front.pos.lineno == 1 ); > 336 assert( lexf.front.pos.column == 1 ); > 337 lexf.popFront; > 338 assert( lexf.front.str == "polemy" ); > 339 assert( lexf.front.pos.lineno == 1 ); > 340 assert( lexf.front.pos.column == 8 ); > 341 lexf.popFront; > 342 assert( lexf.front.str == "." ); > 343 lexf.popFront; > 344 assert( lexf.front.str == "lex" ); > 345 lexf.popFront; > 346 assert( lexf.front.str == ";" ); > 347 lexf.popFront; > 348 assert( lexf.front.str == "import" ); > 349 assert( lexf.front.pos.lineno == 2 ); > 350 assert( lexf.front.pos.column == 1 ); > 351 } > 352 > 353 unittest > 354 { > 355 auto lex = lexerFromString(`my # comment should > 356 # hey!! > 357 be ignored. > 358 hahaha"hihihi""hu\\\"huhu"#123 aa > 359 123 aa "aaa > 360 bbb # 123 > 361 eee" > 362 zzz > 363 `); > 364 Token[] ts = std.array.array(lex); > 365 assert( ts[0].str == "my" ); > 366 assert( ts[0].pos.lineno == 1 ); > 367 assert( ts[1].str == "be" ); > 368 assert( ts[1].pos.lineno == 3 ); > 369 assert( ts[2].str == "ignored" ); > 370 assert( ts[3].str == "." ); > 371 assert( ts[4].str == "hahaha" ); > 372 assert( ts[4].pos.lineno == 4 ); > 373 assert( ts[4].kind == Token.Kind.identifier ); > 374 assert( ts[5].str == "hihihi" ); > 375 assert( ts[5].pos.lineno == 4 ); > 376 assert( ts[5].kind == Token.Kind.stringLiteral ); > 377 assert( ts[6].str == `hu\"huhu` ); > 378 assert( ts[6].kind == Token.Kind.stringLiteral ); > 379 assert( ts[6].pos.lineno == 4 ); > 380 assert( ts[7].str == "123" ); > 381 assert( ts[7].pos.lineno == 5 ); > 382 assert( ts[7].kind == Token.Kind.number ); > 383 assert( ts[8].str == "aa" ); > 384 assert( ts[9].pos.lineno == 5 ); > 385 assert( ts[9].str == "aaa\nbbb # 123\neee" ); > 386 assert( ts[9].kind == Token.Kind.stringLiteral ); > 387 assert( ts[10].pos.lineno == 8 ); > 388 assert( ts.length == 11 ); > 389 }
Added polemy/parse.d version [6a76d51cc68a610b]
> 1 module polemy.parse; > 2 import polemy._common; > 3 /* > 4 * Author: k.inaba > 5 * License: NYSL 0.9982 (http://www.kmonos.net/nysl/ > 6 * Parser for the polemy programming language > 7 */ > 8 > 9 import polemy.lex; > 10 import polemy.ast; > 11 import std.bigint; > 12 > 13 /// Parsing Failure > 14 > 15 class ParserException : Exception > 16 { > 17 private: > 18 this(string msg) { super(msg); } > 19 static ParserException create(Lexer)(Lexer lex, string msg) > 20 { > 21 return new ParserException(sprintf!"[%s] %s"( > 22 lex.empty ? "EOF" : to!string(lex.front.pos), msg)); > 23 } > 24 } > 25 > 26 /// Named Constructor of Parser > 27 > 28 auto parserFromLexer(Lexer)(Lexer lex) > 29 { > 30 return new Parser!Lexer(lex); > 31 } > 32 > 33 /// Named Constructor of Parser (just fwd to lexerFromString) > 34 > 35 auto parserFromString(T...)(T params) > 36 { > 37 return parserFromLexer(polemy.lex.lexerFromString(params)); > 38 } > 39 > 40 /// Named Constructor of Parser (just fwd to lexerFromFile) > 41 > 42 auto parserFromFile(T...)(T params) > 43 { > 44 return parserFromLexer(polemy.lex.lexerFromFile(params)); > 45 } > 46 > 47 /// Parser > 48 > 49 class Parser(Lexer) > 50 { > 51 this(Lexer lex) > 52 { > 53 this.lex = lex; > 54 } > 55 > 56 Program parseProgram() > 57 { > 58 Program p; > 59 while( !lex.empty ) > 60 p ~= parseStatement(); > 61 return p; > 62 } > 63 > 64 Statement parseStatement() > 65 { > 66 auto saved = lex.save; > 67 scope(failure) lex = saved; > 68 > 69 if( lex.empty ) > 70 throw new ParserException("EOF during parsing a statemen > 71 auto pos = lex.front.pos; > 72 > 73 if( lex.front.kind==Token.Kind.identifier && lex.front.str=="var > 74 { > 75 // "var" Var "=" Expression ";" > 76 lex.popFront; > 77 string var = lex.front.str; > 78 lex.popFront; > 79 eat("=", "for variable declaration"); > 80 auto parsed = new DeclStatement(pos, var, parseExpressio > 81 eat(";", "after variable declaration"); > 82 return parsed; > 83 } > 84 else > 85 { > 86 // Expression ";" > 87 auto parsed = new ExprStatement(pos, parseExpression()); > 88 eat(";", "after statement"); > 89 return parsed; > 90 } > 91 } > 92 > 93 Expression parseExpression() > 94 { > 95 auto saved = lex.save; > 96 scope(failure) lex = saved; > 97 > 98 // Expr ::= E0 > 99 // E0 ::= (E1 "=")* E1 > 100 // E1 ::= (E2 "+"|"-")* E2 > 101 // E2 ::= (E3 "*"|"/")* E3 > 102 // E3 ::= int | str | id | "(" Expr ")" > 103 > 104 return parseE0(); > 105 } > 106 > 107 Expression parseE0() > 108 { > 109 auto lhs = parseE1(); > 110 if( tryEat("=") ) > 111 lhs = new BinOpExpression(lhs.pos, "=", lhs, parseE0()); > 112 return lhs; > 113 } > 114 > 115 Expression parseE1() > 116 { > 117 for(auto lhs = parseE2();;) > 118 { > 119 if( tryEat("+") ) > 120 lhs = new BinOpExpression(lhs.pos, "+", lhs, par > 121 else if( tryEat("-") ) > 122 lhs = new BinOpExpression(lhs.pos, "-", lhs, par > 123 else > 124 return lhs; > 125 } > 126 } > 127 > 128 Expression parseE2() > 129 { > 130 for(auto lhs = parseE3();;) > 131 { > 132 if( tryEat("*") ) > 133 lhs = new BinOpExpression(lhs.pos, "*", lhs, par > 134 else if( tryEat("/") ) > 135 lhs = new BinOpExpression(lhs.pos, "/", lhs, par > 136 else > 137 return lhs; > 138 } > 139 } > 140 > 141 Expression parseE3() > 142 { > 143 if( lex.empty ) > 144 throw new ParserException("EOF during parsing an express > 145 auto pos = lex.front.pos; > 146 > 147 if( lex.front.kind == Token.Kind.number ) > 148 { > 149 scope(exit) lex.popFront; > 150 return new IntLiteralExpression(pos, BigInt(cast(string) > 151 } > 152 if( lex.front.kind == Token.Kind.stringLiteral ) > 153 { > 154 scope(exit) lex.popFront; > 155 return new StrLiteralExpression(pos, lex.front.str); > 156 } > 157 if( tryEat("(") ) > 158 { > 159 auto e = parseE0(); > 160 eat(")", "after parenthesized expression"); > 161 return e; > 162 } > 163 scope(exit) lex.popFront; > 164 return new VarExpression(pos, lex.front.str); > 165 } > 166 > 167 private: > 168 Lexer lex; > 169 > 170 void eat(string kwd, lazy string msg) > 171 { > 172 if( !tryEat(kwd) ) > 173 { > 174 auto e = ParserException.create(lex, "'"~kwd~"' is expec > 175 ~(lex.empty ? "EOF" : lex.front.str)~"' occured" > 176 throw e; > 177 } > 178 } > 179 > 180 bool tryEat(string kwd) > 181 { > 182 if( lex.empty || lex.front.kind!=Token.Kind.identifier || lex.fr > 183 return false; > 184 lex.popFront; > 185 return true; > 186 } > 187 } > 188 > 189 unittest > 190 { > 191 auto p = parserFromString(` > 192 var x = 100; > 193 var y = 200; > 194 `); > 195 Program prog = p.parseProgram(); > 196 assert( prog.length == 2 ); > 197 auto p0 = cast(DeclStatement)prog[0]; > 198 auto p1 = cast(DeclStatement)prog[1]; > 199 assert( p0.var == "x" ); > 200 assert( p1.var == "y" ); > 201 assert( (cast(IntLiteralExpression)p0.expr).data == 100 ); > 202 assert( (cast(IntLiteralExpression)p1.expr).data == 200 ); > 203 } > 204 > 205 unittest > 206 { > 207 auto p = parserFromString(` > 208 var zzz = 100; # comment > 209 zzz = zzz + zzz * "fo\no"; # comment > 210 42; > 211 `); > 212 > 213 auto s0 = new DeclStatement(null, "zzz", new IntLiteralExpression(null, > 214 auto s1 = new ExprStatement(null, new BinOpExpression(null, "=", > 215 new VarExpression(null, "zzz"), > 216 new BinOpExpression(null, "+", > 217 new VarExpression(null, "zzz"), > 218 new BinOpExpression(null, "*", > 219 new VarExpression(null, "zzz"), > 220 new StrLiteralExpression(null, "fo\\no") > 221 )))); > 222 auto s2 = new ExprStatement(null, new IntLiteralExpression(null, BigInt( > 223 > 224 Program prog = p.parseProgram(); > 225 assert( prog.length == 3 ); > 226 assert( prog[0] == s0 ); > 227 assert( prog[1] == s1 ); > 228 assert( prog[2] == s2 ); > 229 }
Added polemy/runtime.d version [b0c768679677d7d5]
> 1 module polemy.runtime; > 2 import polemy._common; > 3 /* > 4 * Author: k.inaba > 5 * License: NYSL 0.9982 (http://www.kmonos.net/nysl/ > 6 * Runtime data structures for the polemy programming language > 7 */ > 8 > 9 class PolemyRuntimeException : Exception > 10 { > 11 this(string msg) { super(msg); } > 12 } > 13 > 14 abstract class Value > 15 { > 16 } > 17 > 18 class IntValue : Value > 19 { > 20 BigInt data; > 21 mixin SimpleConstructor; > 22 mixin SimpleCompare; > 23 } > 24 > 25 class StrValue : Value > 26 { > 27 string data; > 28 mixin SimpleConstructor; > 29 mixin SimpleCompare; > 30 } > 31 > 32 class Context > 33 { > 34 Context parent; > 35 Value[string] table; > 36 this(Context parent = null) { this.parent = parent; } > 37 > 38 void add(string i, Value v) > 39 { > 40 table[i] = v; > 41 } > 42 > 43 Value opIndex(string i) > 44 { > 45 if( i in table ) > 46 return table[i]; > 47 if( parent is null ) > 48 throw new PolemyRuntimeException(sprintf!"variable %s no > 49 return parent[i]; > 50 } > 51 > 52 void opIndexAssign(Value v, string i) > 53 { > 54 if( i in table ) > 55 return table[i] = v; > 56 if( parent is null ) > 57 throw new PolemyRuntimeException(sprintf!"variable %s no > 58 return parent[i] = v; > 59 } > 60 }
Added polemy/tricks.d version [bd0c6e24fe1ad6ba]
> 1 module polemy.tricks; > 2 /* > 3 * Author: k.inaba > 4 * License: NYSL 0.9982 (http://www.kmonos.net/nysl/ > 5 * Tricks and utilities for D programming > 6 */ > 7 static import std.array; > 8 static import std.format; > 9 > 10 /// Simple Wrapper for std.format.doFormat > 11 > 12 string sprintf(string fmt, T...)(T params) > 13 { > 14 auto writer = std.array.appender!string(); > 15 std.format.formattedWrite(writer, fmt, params); > 16 return writer.data; > 17 } > 18 > 19 unittest > 20 { > 21 assert( sprintf!"%s == %d"("1+2", 3) == "1+2 == 3" ); > 22 assert( sprintf!"%s == %04d"("1+2", 3) == "1+2 == 0003" ); > 23 } > 24 > 25 /// Mixing-in the bean constructor for a class > 26 > 27 /*mixin*/ template SimpleConstructor() > 28 { > 29 static if( is(typeof(super) == Object) || super.tupleof.length==0 ) > 30 this( typeof(this.tupleof) params ) > 31 { > 32 this.tupleof = params; > 33 } > 34 else > 35 // this parameter list is not always desirable but should work f > 36 this( typeof(super.tupleof) ps, typeof(this.tupleof) params ) > 37 { > 38 super(ps); > 39 this.tupleof = params; > 40 } > 41 } > 42 > 43 /// Mixing-in the (MOST-DERIVED) member-wise comparator for a class > 44 > 45 /*mixin*/ template SimpleCompare() > 46 { > 47 override bool opEquals(Object rhs_) const > 48 { > 49 if( auto rhs = cast(typeof(this))rhs_ ) > 50 { > 51 foreach(i,_; this.tupleof) > 52 if( this.tupleof[i] != rhs.tupleof[i] ) > 53 return false; > 54 return true; > 55 } > 56 assert(false, sprintf!"Cannot compare %s with %s"(typeid(this), > 57 } > 58 > 59 override hash_t toHash() const > 60 { > 61 hash_t h = 0; > 62 foreach(mem; this.tupleof) > 63 h += typeid(mem).getHash(&mem); > 64 return h; > 65 } > 66 > 67 override int opCmp(Object rhs_) const > 68 { > 69 if( auto rhs = cast(typeof(this))rhs_ ) > 70 { > 71 foreach(i,_; this.tupleof) > 72 if(auto c = typeid(_).compare(&this.tupleof[i],& > 73 return c; > 74 return 0; > 75 } > 76 assert(false, sprintf!"Cannot compare %s with %s"(typeid(this), > 77 } > 78 } > 79 > 80 unittest > 81 { > 82 class Temp > 83 { > 84 int x; > 85 string y; > 86 mixin SimpleConstructor; > 87 mixin SimpleCompare; > 88 } > 89 assert( (new Temp(1,"foo")).x == 1 ); > 90 assert( (new Temp(1,"foo")).y == "foo" ); > 91 assert( !__traits(compiles, new Temp) ); > 92 assert( !__traits(compiles, new Temp(1)) ); > 93 assert( !__traits(compiles, new Temp("foo",1)) ); > 94 assert( new Temp(1,"foo") == new Temp(1,"foo") ); > 95 assert( (new Temp(1,"foo")).toHash == (new Temp(1,"foo")).toHash ); > 96 assert( new Temp(1,"foo") != new Temp(2,"foo") ); > 97 assert( new Temp(1,"foo") != new Temp(1,"bar") ); > 98 assert( new Temp(1,"foo") > new Temp(1,"bar") ); > 99 assert( new Temp(1,"foo") < new Temp(2,"bar") ); > 100 }
Added readme.txt version [f8fe981026f3c9cf]
> 1 ----------------------------------------------------------------------------- > 2 Polemy 0.1.0 > 3 by k.inaba (www.kmonos.net) > 4 Nov 7, 2010 > 5 ----------------------------------------------------------------------------- > 6 > 7 > 8 > 9 <<How to Build>> > 10 > 11 - Install DMD > 12 http://www.digitalmars.com/d/2.0/changelog.html > 13 Version 2.050 is recommended. Older and/or newer version may not work. > 14 > 15 - Build > 16 (for Poseidon IDE users) Open the project and build > 17 (for Windows) Run build.bat > 18 (for Unix) Run build.sh > 19 or use your favorite build tools upon main.d and polemy/*.d. > 20 > 21 Then you will get the executable "polemy" in the "bin" directory. > 22 > 23 > 24 > 25 <<License>> > 26 > 27 d2stacktrace/* > 28 > 29 is written by Benjamin Thaut and licensed under 2-clause BSD License. > 30 See http://3d.benjamin-thaut.de/?p=15 for the detail. > 31 > 32 (this package is used only for enabling stack-traces during printing excepti > 33 if it is not needed, please just simply remove the sources from your build) > 34 > 35 polemy/* > 36 main.d > 37 > 38 All the other parts are written by Kazuhiro Inaba and > 39 licensed under NYSL 0.9982 ( http://www.kmonos.net/nysl/ ). > 40 > 41 > 42 > 43 <<How to Use>> > 44 > 45 I don't know.