diff --git a/cedast/src/ast.d b/cedast/src/ast.d index a590b771..1c7530d2 100644 --- a/cedast/src/ast.d +++ b/cedast/src/ast.d @@ -1,7 +1,7 @@ module ast; import std.d.lexer, std.d.parser, std.d.ast; -import std.json, std.array, std.conv; +import std.json, std.array, std.conv, std.parallelism; import iz.enumset, iz.memory; import common; @@ -294,7 +294,7 @@ private } -struct Ast +class Ast { private: @@ -304,6 +304,8 @@ private: LexerConfig config; StringCache strcache; Module mod; + AstNotification notif; + void* notifparam; bool scanned; CachedInfos cachedInfos; @@ -325,49 +327,55 @@ private: { cachedInfos = 0; modName = modName.init; + jsonErrors = jsonErrors.init; + pasErrors = pasErrors.init; + todosPas = todosPas.init; + todosJson = todosJson.init; + symsPas = symsPas.init; + symsJson = symsJson.init; errors = errors.init; } - final void scan() + final void taskScan() { - resetCachedInfo; - scanned = false; - scope(success) scanned = true; - config = LexerConfig(fname, StringBehavior.source, WhitespaceBehavior.skip); mod = parseModule(getTokensForParser(src, config, &strcache), fname, null, &parserError); + if (notif) notif(notifparam); + scanned = true; } public: - this(string filename) - { - fname = filename; - strcache = StringCache(StringCache.defaultBucketCount); - rescanFile(); - } - - this(ubyte[] buffer) + this() { strcache = StringCache(StringCache.defaultBucketCount); - rescanBuffer(buffer); } - final void rescanFile() + final void scanFile(string filename) { resetCachedInfo; + fname = filename; import std.file; - src = cast(ubyte[]) read(fname, size_t.max); - scan; + try src = cast(ubyte[]) read(fname, size_t.max); + catch(Exception e){} + scanned = false; + task(&taskScan).executeInNewThread; } - final void rescanBuffer(ubyte[] buffer) + final void scanBuffer(ubyte[] buffer) { resetCachedInfo; src = buffer.dup; - scan; + scanned = false; + task(&taskScan).executeInNewThread; } + @property AstNotification notification(){return notif;} + @property void notification(AstNotification value){notif = value;} + + @property void* notificationParameter(){return notifparam;} + @property void notificationParameter(void* value){notifparam = value;} + final string moduleName() { string result; @@ -423,3 +431,4 @@ public: } } + diff --git a/cedast/src/cedast.d b/cedast/src/cedast.d index f8649ef3..876c8192 100644 --- a/cedast/src/cedast.d +++ b/cedast/src/cedast.d @@ -3,17 +3,19 @@ module cedast; import core.runtime, common, ast; import iz.memory; -__gshared Ast*[] modules; +__gshared Ast[] modules; + extern(C) export -AstToken scanFile(char* filename) +AstHandle newAst(void* param, AstNotification clbck) { - AstToken result; + AstHandle result; try { - import std.string: fromStringz; import std.algorithm: countUntil; - Ast* ast = construct!Ast(filename.fromStringz.idup); + Ast ast = construct!Ast; + ast.notification = clbck; + ast.notificationParameter = param; result = countUntil(modules, null); if (result == -1) { @@ -28,115 +30,92 @@ AstToken scanFile(char* filename) } catch(Exception e) { - if (result != 0) unleash(result); - result = invalidAstToken; + if (result != 0) deleteAst(result); + result = invalidAstHandle; } return result; } extern(C) export -AstToken scanBuffer(ubyte* buffer, size_t len) +void deleteAst(AstHandle hdl) { - AstToken result; - try - { - import std.algorithm: countUntil; - Ast* ast = construct!Ast(buffer[0 .. len]); - result = countUntil(modules, null); - if (result == -1) - { - modules ~= ast; - result = modules.length; - } - else - { - modules[result] = ast; - ++result; - } - } - catch(Exception e) - { - if (result != 0) unleash(result); - result = invalidAstToken; - } - return result; -} + if (hdl < 1 || hdl > modules.length) + return; + if (modules[hdl - 1] is null) + return; -extern(C) export -void rescanFile(AstToken tok) -{ - if (tok < 1 || tok > modules.length) - return; - modules[tok - 1].rescanFile; -} - -extern(C) export -void rescanBuffer(AstToken tok, ubyte* buffer, size_t len) -{ - if (tok < 1 || tok > modules.length) - return; - modules[tok - 1].rescanBuffer(buffer[0 .. len]); -} - -extern(C) export -void unleash(AstToken tok) -{ - mixin(logcall); - if (tok < 1 || tok > modules.length) - return; - if (modules[tok - 1] == null) - return; - destruct(modules[tok - 1]); - modules[tok - 1] = null; - if (tok == modules.length) + destruct(modules[hdl - 1]); + modules[hdl - 1] = null; + if (hdl == modules.length) modules.length -= 1; } extern(C) export -immutable(char*) moduleName(AstToken tok) +void scanFile(AstHandle hdl, char* filename) { - if (tok < 1 || tok > modules.length) - return null; - Ast* mod = modules[tok - 1]; - if (mod == null) - return null; - import std.string: toStringz; - return toStringz(mod.moduleName); + if (hdl < 1 || hdl > modules.length) + return; + if (modules[hdl - 1] is null) + return; + + import std.string: fromStringz; + modules[hdl - 1].scanFile(fromStringz(filename).idup); } extern(C) export -ubyte* symbolList(AstToken tok, ref size_t len, SerializationFormat fmt) +void scanBuffer(AstHandle hdl, ubyte* buffer, size_t len) { - if (tok < 1 || tok > modules.length) + if (hdl < 1 || hdl > modules.length) + return; + if (modules[hdl - 1] is null) + return; + + modules[hdl - 1].scanBuffer(buffer[0 .. len]); +} + +extern(C) export +immutable(char*) moduleName(AstHandle hdl) +{ + if (hdl < 1 || hdl > modules.length) return null; - Ast* mod = modules[tok - 1]; - if (mod == null) + if (modules[hdl - 1] is null) + return null; + + import std.string: toStringz; + return toStringz(modules[hdl - 1].moduleName); +} + +extern(C) export +ubyte* symbolList(AstHandle hdl, ref size_t len, SerializationFormat fmt) +{ + if (hdl < 1 || hdl > modules.length) + return null; + if (modules[hdl - 1] is null) return null; ubyte[] result; if (fmt == SerializationFormat.json) - result = mod.symbolListJson; + result = modules[hdl - 1].symbolListJson; else - result = mod.symbolListPas; + result = modules[hdl - 1].symbolListPas; len = result.length; return result.ptr; } extern(C) export -ubyte* todoList(AstToken tok, ref size_t len, SerializationFormat fmt) +ubyte* todoList(AstHandle hdl, ref size_t len, SerializationFormat fmt) { - if (tok < 1 || tok > modules.length) + if (hdl < 1 || hdl > modules.length) return null; - Ast* mod = modules[tok - 1]; - if (mod == null) + if (modules[hdl - 1] is null) return null; ubyte[] result; if (fmt == SerializationFormat.json) - result = mod.todoListJson; + result = modules[hdl - 1].todoListJson; else - result = mod.todoListPas; + result = modules[hdl - 1].todoListPas; len = result.length; return result.ptr; @@ -177,4 +156,3 @@ version(Windows) } } - diff --git a/cedast/src/common.d b/cedast/src/common.d index 405a4804..fa485ca8 100644 --- a/cedast/src/common.d +++ b/cedast/src/common.d @@ -1,8 +1,10 @@ module common; -alias AstToken = ptrdiff_t; +alias AstHandle = ptrdiff_t; -__gshared immutable AstToken invalidAstToken = 0; +alias AstNotification = extern(C) void function(void* param); + +__gshared immutable AstHandle invalidAstHandle = 0; enum SerializationFormat : byte { diff --git a/lazproj/cedast_loader.pas b/lazproj/cedast_loader.pas index de0b0496..5f10d646 100644 --- a/lazproj/cedast_loader.pas +++ b/lazproj/cedast_loader.pas @@ -1,41 +1,52 @@ program cedast_loader; +{$MODE OBJFPC} + uses dynlibs, classes, sysutils; type - TAstToken = NativeInt; + TAstHandle = NativeInt; + + TAstNotification = procedure(param: pointer); cdecl; {$Z1} + TSerializationFormat = (json, pas); - TScanFile = function(filename: PChar): TAstToken; cdecl; - TScanBuffer = function(buffer: PByte; len: NativeUint): TAstToken; cdecl; - TRescanFile = procedure(tok: TAstToken); cdecl; - TRescanBuffer = procedure(tok: TAstToken; buffer: PByte; len: NativeUint); cdecl; - TUnleash = procedure(tok: TAstToken); cdecl; + TNewAst = function(param: Pointer; clbck: TAstNotification): TAstHandle; cdecl; + TDeleteAst = procedure(tok: TAstHandle); cdecl; - TModuleName = function(tok: TAstToken): PChar; cdecl; - TSymbolList = function(tok: TAstToken; var len: NativeUint ; fmt: TSerializationFormat): PByte; cdecl; + TScanFile = procedure(tok: TAstHandle; filename: PChar); cdecl; + TScanBuffer = procedure(tok: TAstHandle; buffer: PByte; len: NativeUint); cdecl; + + + TModuleName = function(tok: TAstHandle): PChar; cdecl; + TSymbolList = function(tok: TAstHandle; var len: NativeUint ; fmt: TSerializationFormat): PByte; cdecl; var dast: TLibHandle; - scanfile: TScanFile; - scanbuffer: TScanBuffer; - rescanfile: TRescanFile; - rescanbuffer: TRescanBuffer; - unleash: TUnleash; + newAst: TNewAst; + deleteast: TDeleteAst; + scanFile: TScanFile; + scanBuffer: TScanBuffer; moduleName: TModuleName; - symlist: TSymbolList; - tok: TAstToken; + symbolList: TSymbolList; + hdl: TAstHandle; len: NativeUint = 0; ptr: PByte; + done: boolean; const testModule = 'module a.b.c.d.e.f.g.h; import std.stdio; uint a; struct F{long c;}'; +procedure notif(param: Pointer); cdecl; +begin + done := true; +end; + begin @@ -43,39 +54,44 @@ begin if dast = NilHandle then writeln('dast invalid handle') else begin - scanfile := TScanFile(GetProcAddress(dast, 'scanFile')); + + newAst := TNewAst(GetProcAddress(dast, 'newAst')); + if newAst = nil then writeln('invalid newAst proc ptr') + else hdl := newAst(nil, @notif); + + scanFile := TScanFile(GetProcAddress(dast, 'scanFile')); if scanFile = nil then writeln('invalid scanfile proc ptr') - else tok := scanfile(PChar('exception in call so ticket value is 0')); + else begin + done := false; + scanFile(hdl, PChar('exception in call')); + while not done do sleep(20); + end; - rescanfile := TRescanFile(GetProcAddress(dast, 'rescanFile')); - if rescanfile = nil then writeln('invalid rescanFile proc ptr') - else rescanfile(tok); - - scanbuffer := TScanBuffer(GetProcAddress(dast, 'scanBuffer')); - if scanbuffer = nil then writeln('invalid scanBuffer proc ptr') - else tok := scanbuffer(@testModule[1], length(testModule)); - - rescanbuffer := TRescanBuffer(GetProcAddress(dast, 'rescanBuffer')); - if rescanbuffer = nil then writeln('invalid rescanBuffer proc ptr') - else rescanbuffer(tok, @testmodule[1], length(testModule)); + scanBuffer := TScanBuffer(GetProcAddress(dast, 'scanBuffer')); + if scanBuffer = nil then writeln('invalid scanBuffer proc ptr') + else begin + done := false; + scanBuffer(hdl, @testModule[1], length(testModule)); + while not done do sleep(20); + end; moduleName := TModuleName(GetProcAddress(dast, 'moduleName')); if moduleName = nil then writeln('invalid moduleName proc ptr') - else if tok <> 0 then writeln(moduleName(tok)); + else if hdl <> 0 then writeln(moduleName(hdl)); - symlist := TSymbolList(GetProcAddress(dast, 'symbolList')); - if symlist = nil then writeln('invalid symbolList proc ptr') - else if tok <> 0 then with TMemoryStream.Create do try - ptr := symlist(tok, len, TSerializationFormat.json); + symbolList := TSymbolList(GetProcAddress(dast, 'symbolList')); + if symbolList = nil then writeln('invalid symbolList proc ptr') + else if hdl <> 0 then with TMemoryStream.Create do try + ptr := symbolList(hdl, len, TSerializationFormat.json); write(ptr^, len); SaveToFile('testsymlist.txt'); finally free; end; - unleash := TUnleash(GetProcAddress(dast, 'unleash')); - if unleash = nil then writeln('invalid unleash proc ptr') - else unleash(tok); + deleteAst := TDeleteAst(GetProcAddress(dast, 'deleteAst')); + if deleteAst = nil then writeln('invalid deleteAst proc ptr') + else deleteAst(hdl); end;