Check-in [423f308350]
Not logged in
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
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]

1 +@setlocal ENABLEDELAYEDEXPANSION 2 +@set ARGS= 3 +@for %%I in (main.d polemy\*.d d2stacktrace\*.d) do @set ARGS=!ARGS! %%I 4 +@if not exist bin mkdir bin 5 +@echo dmd -ofbin\polemy.exe -O -release -inline %ARGS% 6 +@dmd -ofbin\polemy.exe -O -release -inline %ARGS%

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, are permitted 7 +provided that the following conditions are met: 8 + 9 + 1. Redistributions of source code must retain the above copyright notice, this list of conditions 10 + and the following disclaimer. 11 + 12 + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions 13 + and the following disclaimer in the documentation and/or other materials provided with the distribution. 14 + 15 +THIS SOFTWARE IS PROVIDED BY BENJAMIN THAUT "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, 16 +BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 +IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 18 +OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 19 +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 20 +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 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, PVOID lpBuffer, DWORD nSize, LPDWORD lpNumberOfBytesRead) ReadProcessMemoryProc64; 156 + typedef PVOID function(HANDLE hProcess, DWORD64 AddrBase) FunctionTableAccessProc64; 157 + typedef DWORD64 function(HANDLE hProcess, DWORD64 Address) GetModuleBaseProc64; 158 + typedef DWORD64 function(HANDLE hProcess, HANDLE hThread, ADDRESS64 *lpaddr) TranslateAddressProc64; 159 + 160 + typedef BOOL function(HANDLE hProcess, PCSTR UserSearchPath, bool fInvadeProcess) SymInitializeFunc; 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) SymFunctionTableAccess64Func; 165 + typedef BOOL function(DWORD MachineType, HANDLE hProcess, HANDLE hThread, STACKFRAME64 *StackFrame, PVOID ContextRecord, 166 + ReadProcessMemoryProc64 ReadMemoryRoutine, FunctionTableAccessProc64 FunctoinTableAccess, 167 + GetModuleBaseProc64 GetModuleBaseRoutine, TranslateAddressProc64 TranslateAddress) StackWalk64Func; 168 + typedef BOOL function(HANDLE hProcess, DWORD64 dwAddr, PDWORD pdwDisplacement, IMAGEHLP_LINE64 *line) SymGetLineFromAddr64Func; 169 + typedef DWORD64 function(HANDLE hProcess, DWORD64 dwAddr) SymGetModuleBase64Func; 170 + typedef BOOL function(HANDLE hProcess, DWORD64 dwAddr, IMAGEHLP_MODULE64 *ModuleInfo) SymGetModuleInfo64Func; 171 + typedef BOOL function(HANDLE hProcess, DWORD64 Address, DWORD64 *Displacement, IMAGEHLP_SYMBOL64 *Symbol) SymGetSymFromAddr64Func; 172 + typedef DWORD function(CTSTR *DecoratedName, PTSTR UnDecoratedName, DWORD UndecoratedLength, DWORD Flags) UnDecorateSymbolNameFunc; 173 + typedef DWORD64 function(HANDLE hProcess, HANDLE hFile, PCSTR ImageName, PCSTR ModuleName, DWORD64 BaseOfDll, DWORD SizeOfDll) SymLoadModule64Func; 174 + typedef BOOL function(HANDLE HProcess, PTSTR SearchPath, DWORD SearchPathLength) SymGetSearchPathFunc; 175 + typedef BOOL function(HANDLE hProcess, DWORD64 Address) SymUnloadModule64Func; 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_lib,"SymInitialize"); 204 + SymCleanup = cast(SymCleanupFunc) GetProcAddress(dbghelp_lib,"SymCleanup"); 205 + StackWalk64 = cast(StackWalk64Func) GetProcAddress(dbghelp_lib,"StackWalk64"); 206 + SymGetOptions = cast(SymGetOptionsFunc) GetProcAddress(dbghelp_lib,"SymGetOptions"); 207 + SymSetOptions = cast(SymSetOptionsFunc) GetProcAddress(dbghelp_lib,"SymSetOptions"); 208 + SymFunctionTableAccess64 = cast(SymFunctionTableAccess64Func) GetProcAddress(dbghelp_lib,"SymFunctionTableAccess64"); 209 + SymGetLineFromAddr64 = cast(SymGetLineFromAddr64Func) GetProcAddress(dbghelp_lib,"SymGetLineFromAddr64"); 210 + SymGetModuleBase64 = cast(SymGetModuleBase64Func) GetProcAddress(dbghelp_lib,"SymGetModuleBase64"); 211 + SymGetModuleInfo64 = cast(SymGetModuleInfo64Func) GetProcAddress(dbghelp_lib,"SymGetModuleInfo64"); 212 + SymGetSymFromAddr64 = cast(SymGetSymFromAddr64Func) GetProcAddress(dbghelp_lib,"SymGetSymFromAddr64"); 213 + SymLoadModule64 = cast(SymLoadModule64Func) GetProcAddress(dbghelp_lib,"SymLoadModule64"); 214 + SymGetSearchPath = cast(SymGetSearchPathFunc) GetProcAddress(dbghelp_lib,"SymGetSearchPath"); 215 + SymUnloadModule64 = cast(SymUnloadModule64Func) GetProcAddress(dbghelp_lib,"SymUnloadModule64"); 216 + 217 + if(!SymInitialize || !SymCleanup || !StackWalk64 || !SymGetOptions || !SymSetOptions || !SymFunctionTableAccess64 218 + || !SymGetLineFromAddr64 || !SymGetModuleBase64 || !SymGetModuleInfo64 || !SymGetSymFromAddr64 219 + || !SymLoadModule64 || !SymGetSearchPath || !SymUnloadModule64){ 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, are permitted 6 +provided that the following conditions are met: 7 + 8 + 1. Redistributions of source code must retain the above copyright notice, this list of conditions 9 + and the following disclaimer. 10 + 11 + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions 12 + and the following disclaimer in the documentation and/or other materials provided with the distribution. 13 + 14 +THIS SOFTWARE IS PROVIDED BY BENJAMIN THAUT "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, 15 +BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 16 +IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 17 +OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 18 +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 19 +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 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 windows. It works both with the pdb and cv debug symbol format. For Exceptions that are derived from the Error class the trace information is automatically appended, this causes all builtin D errors to get a stacktrace information. The only point where this does not work is the Access Vioaltion error, as it does not call the stacktrace callback function for some reason. 2 + 3 + 4 +It is very easy to use, just copy the two files from the zip archive to your root source directory and import the stacktrace module inside your main file. 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 you, feel free to contact me and we will fix the problem. 29 + 30 +XP Users: 31 +If you get a stacktrace with numbers only download a new version of dbghelp.dll and put it into your project root directory. That should fix it.

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, are permitted 7 +provided that the following conditions are met: 8 + 9 + 1. Redistributions of source code must retain the above copyright notice, this list of conditions 10 + and the following disclaimer. 11 + 12 + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions 13 + and the following disclaimer in the documentation and/or other materials provided with the distribution. 14 + 15 +THIS SOFTWARE IS PROVIDED BY BENJAMIN THAUT "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, 16 +BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 +IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 18 +OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 19 +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 20 +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 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) CreateToolhelp32SnapshotFunc; 71 + typedef BOOL function(HANDLE hSnapshot, MODULEENTRY32 *lpme) Module32FirstFunc; 72 + typedef BOOL function(HANDLE hSnapshot, MODULEENTRY32 *lpme) Module32NextFunc; 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(CreateToolhelp32SnapshotFunc) GetProcAddress(hDll,"CreateToolhelp32Snapshot"); 103 + Module32First = cast(Module32FirstFunc) GetProcAddress(hDll,"Module32First"); 104 + Module32Next = cast(Module32NextFunc) GetProcAddress(hDll,"Module32Next"); 105 + if(CreateToolhelp32Snapshot != null && Module32First != null && Module32Next != null) 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, ModuleEntry.szModule.ptr, cast(Dbghelp.DWORD64)ModuleEntry.modBaseAddr, ModuleEntry.modBaseSize); 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 baseAddr, DWORD size){ 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,HANDLE.init,cast(Dbghelp.PCSTR)toStringz(szImg),cast(Dbghelp.PCSTR)toStringz(szMod),baseAddr,size); 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) == TRUE){ 155 + if(ModuleInfo.SymType == Dbghelp.SYM_TYPE.SymNone){ 156 + Dbghelp.SymUnloadModule64(hProcess,moduleAddr); 157 + moduleAddr = Dbghelp.SymLoadModule64(hProcess,HANDLE.init,cast(Dbghelp.PCSTR)toStringz(szImg),null,cast(Dbghelp.DWORD64)0,0); 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_PATH", "SYSTEMROOT" ]; 192 + 193 + foreach(e;systemVars){ 194 + if(GetEnvironmentVariableA(toStringz(e),temp.ptr,temp.length) > 0){ 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(symPath),FALSE) != FALSE){ 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_NAMELEN; 297 + Dbghelp.IMAGEHLP_SYMBOL64 *Symbol = cast(Dbghelp.IMAGEHLP_SYMBOL64*) malloc(SymbolSize); 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.FunctionTableAccessProc64)Dbghelp.SymFunctionTableAccess64, 318 + cast(Dbghelp.GetModuleBaseProc64)Dbghelp.SymGetModuleBase64, 319 + null) != TRUE ) 320 + { 321 + //writefln("End of Callstack"); 322 + break; 323 + } 324 + 325 + if(stackframe.AddrPC.Offset == stackframe.AddrReturn.Offset){ 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.DWORD64)0; 334 + if( Dbghelp.SymGetSymFromAddr64(hProcess,stackframe.AddrPC.Offset,&offsetFromSymbol,Symbol) == TRUE){ 335 + char[] symName = new char[strlen(cast(const(char)*)Symbol.Name.ptr)+1]; 336 + memcpy(symName.ptr,Symbol.Name.ptr,symName.length); 337 + string symString = ""; 338 + if(symName[0] == 'D') 339 + symString = "_"; 340 + symString ~= symName; 341 + 342 + string demangeledName = demangle(symString); 343 + lineStr ~= demangeledName; 344 + 345 + DWORD zeichen = 0; 346 + if(Dbghelp.SymGetLineFromAddr64(hProcess,stackframe.AddrPC.Offset,&zeichen,&Line) == TRUE){ 347 + char[] fileName = new char[strlen(Line.FileName)]; 348 + fileName[] = Line.FileName[0..fileName.length]; 349 + lineStr = to!string(fileName ~ "::" ~ to!string(Line.LineNumber) ~ "(" ~ to!string(zeichen) ~ ") " ~ lineStr); 350 + } 351 + } 352 + else { 353 + lineStr = to!string(cast(ulong)stackframe.AddrPC.Offset); 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 at [%s]"(typeid(_s), _s.pos)); 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 assignment must be a variable: %s"(e.pos)); 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 %s must be an integer but was %s at [%s]"(e.op, typeid(r), e.rhs.pos)); 83 + else 84 + throw new PolemyRuntimeException(sprintf!"lhs of %s must be an integer but was %s at [%s]"(e.op, typeid(l), e.lhs.pos)); 85 + } 86 + throw new PolemyRuntimeException(sprintf!"Unknown Kind of Expression %s at [%s]"(typeid(_e), _e.pos)); 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 the source 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, int column=1 ) 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 the end"); 100 + } 101 + 102 + void popFront() /*@property*/ 103 + { 104 + std.exception.enforce(current, "Lexer has already reached the end"); 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 current=null ) 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]=='\n') ) 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' && buffer[0]!='\r') ) 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]=='\\' || 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]=='\n' ) 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.stringLiteral); 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]) && !isSymbol(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 : Token.Kind.identifier); 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 statement"); 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, parseExpression()); 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, parseE2()); 121 + else if( tryEat("-") ) 122 + lhs = new BinOpExpression(lhs.pos, "-", lhs, parseE2()); 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, parseE3()); 134 + else if( tryEat("/") ) 135 + lhs = new BinOpExpression(lhs.pos, "/", lhs, parseE3()); 136 + else 137 + return lhs; 138 + } 139 + } 140 + 141 + Expression parseE3() 142 + { 143 + if( lex.empty ) 144 + throw new ParserException("EOF during parsing an expression"); 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)lex.front.str)); 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 expected "~msg~" but '" 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.front.str!=kwd ) 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, BigInt(100))); 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(42))); 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 not found"(i)); 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 not found"(i)); 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 for many cases 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), typeid(rhs_))); 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],&rhs.tupleof[i])) 73 + return c; 74 + return 0; 75 + } 76 + assert(false, sprintf!"Cannot compare %s with %s"(typeid(this), typeid(rhs_))); 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 exceptions; 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.