diff options
author | Andreas Rumpf <andreas@andreas-desktop> | 2009-11-12 19:34:21 +0100 |
---|---|---|
committer | Andreas Rumpf <andreas@andreas-desktop> | 2009-11-12 19:34:21 +0100 |
commit | ac421c37ba9a973155dc5600e38d7a40553d8de6 (patch) | |
tree | 5ede0dfe1c02aa547f788a39f070614a64a3b9ab /nim | |
parent | d5acb88cccecf54bcc9a7c13f4fbaa095a8b37d4 (diff) | |
download | Nim-ac421c37ba9a973155dc5600e38d7a40553d8de6.tar.gz |
bind table
Diffstat (limited to 'nim')
-rwxr-xr-x | nim/llvmdata.pas | 139 | ||||
-rwxr-xr-x | nim/pbraces.pas | 122 | ||||
-rwxr-xr-x | nim/pendx.pas | 36 | ||||
-rwxr-xr-x | nim/pnimsyn.pas | 47 | ||||
-rwxr-xr-x | nim/semgnrc.pas | 287 | ||||
-rwxr-xr-x | nim/semtempl.pas | 14 | ||||
-rwxr-xr-x | nim/syntaxes.pas | 10 | ||||
-rwxr-xr-x | nim/vis.pas | 35 |
8 files changed, 570 insertions, 120 deletions
diff --git a/nim/llvmdata.pas b/nim/llvmdata.pas new file mode 100755 index 000000000..a8ae0f311 --- /dev/null +++ b/nim/llvmdata.pas @@ -0,0 +1,139 @@ +// +// +// The Nimrod Compiler +// (c) Copyright 2009 Andreas Rumpf +// +// See the file "copying.txt", included in this +// distribution, for details about the copyright. +// +unit llvmdata; + +// this module implements data structures for emitting LLVM. + +interface + +{$include 'config.inc'} + +uses + nsystem, ast, astalgo, idents, lists, passes; + +type + VTypeKind = ( + VoidTyID, ///< 0: type with no size + FloatTyID, ///< 1: 32 bit floating point type + DoubleTyID, ///< 2: 64 bit floating point type + X86_FP80TyID, ///< 3: 80 bit floating point type (X87) + FP128TyID, ///< 4: 128 bit floating point type (112-bit mantissa) + PPC_FP128TyID, ///< 5: 128 bit floating point type (two 64-bits) + LabelTyID, ///< 6: Labels + MetadataTyID, ///< 7: Metadata + + // Derived types... see DerivedTypes.h file... + // Make sure FirstDerivedTyID stays up to date!!! + IntegerTyID, ///< 8: Arbitrary bit width integers + FunctionTyID, ///< 9: Functions + StructTyID, ///< 10: Structures + ArrayTyID, ///< 11: Arrays + PointerTyID, ///< 12: Pointers + OpaqueTyID, ///< 13: Opaque: type with unknown structure + VectorTyID, ///< 14: SIMD 'packed' format, or other vector type + ); + VType = ^VTypeDesc; + VTypeSeq = array of VType; + VTypeDesc = object(TIdObj) + k: VTypeKind; + s: VTypeSeq; + arrayLen: int; + name: string; + end; + + VInstrKind = ( + iNone, + iAdd, + iSub, + iMul, + iDiv, + iMod, + + ); + VLocalVar = record + + + end; + VInstr = record + k: VInstrKind; + + end; + +/// This represents a single basic block in LLVM. A basic block is simply a +/// container of instructions that execute sequentially. Basic blocks are Values +/// because they are referenced by instructions such as branches and switch +/// tables. The type of a BasicBlock is "Type::LabelTy" because the basic block +/// represents a label to which a branch can jump. +/// + VBlock = ^VBlockDesc; + VBlockDesc = record // LLVM basic block + // list of instructions + end; + + VLinkage = ( + ExternalLinkage, // Externally visible function + LinkOnceLinkage, // Keep one copy of function when linking (inline) + WeakLinkage, // Keep one copy of function when linking (weak) + AppendingLinkage, // Special purpose, only applies to global arrays + InternalLinkage, // Rename collisions when linking (static functions) + DLLImportLinkage, // Function to be imported from DLL + DLLExportLinkage, // Function to be accessible from DLL + ExternalWeakLinkage, // ExternalWeak linkage description + GhostLinkage // Stand-in functions for streaming fns from bitcode + ); + VVisibility = ( + DefaultVisibility, // The GV is visible + HiddenVisibility, // The GV is hidden + ProtectedVisibility // The GV is protected + ); + TLLVMCallConv = ( + CCallConv = 0, + FastCallConv = 8, + ColdCallConv = 9, + X86StdcallCallConv = 64, + X86FastcallCallConv = 65 + ); + + VProc = ^VProcDesc; + VProcDesc = record + b: VBlock; + name: string; + sym: PSym; // proc that is generated + linkage: VLinkage; + vis: VVisibility; + callConv: VCallConv; + next: VProc; + end; + VModule = ^VModuleDesc; + VModuleDesc = object(TPassContext) // represents a C source file + sym: PSym; + filename: string; + typeCache: TIdTable; // cache the generated types + forwTypeCache: TIdTable; // cache for forward declarations of types + declaredThings: TIntSet; // things we have declared in this file + declaredProtos: TIntSet; // prototypes we have declared in this file + headerFiles: TLinkedList; // needed headers to include + typeInfoMarker: TIntSet; // needed for generating type information + initProc: VProc; // code for init procedure + typeStack: TTypeSeq; // used for type generation + dataCache: TNodeTable; + forwardedProcs: TSymSeq; // keep forwarded procs here + typeNodes, nimTypes: int;// used for type info generation + typeNodesName, nimTypesName: PRope; // used for type info generation + labels: natural; // for generating unique module-scope names + next: VModule; // to stack modules + end; + + + +implementation + + +end. + diff --git a/nim/pbraces.pas b/nim/pbraces.pas index d362fac65..2e10c50f2 100755 --- a/nim/pbraces.pas +++ b/nim/pbraces.pas @@ -146,8 +146,7 @@ begin end; end; -procedure qualifiedIdentListAux(var p: TParser; endTok: TTokType; - result: PNode); +procedure qualifiedIdentListAux(var p: TParser; endTok: TTokType; result: PNode); var a: PNode; begin @@ -216,16 +215,6 @@ begin eat(p, tkParRi); end; -procedure setBaseFlags(n: PNode; base: TNumericalBase); -begin - case base of - base10: begin end; - base2: include(n.flags, nfBase2); - base8: include(n.flags, nfBase8); - base16: include(n.flags, nfBase16); - end -end; - function identOrLiteral(var p: TParser): PNode; begin case p.tok.tokType of @@ -542,7 +531,7 @@ begin optInd(p, result); while (p.tok.tokType = tkSymbol) or (p.tok.tokType = tkAccent) do begin a := parseIdentColonEquals(p, {@set}[]); - addSon(result, a); + addSon(result, a); if p.tok.tokType <> tkComma then break; getTok(p); optInd(p, a) @@ -729,12 +718,12 @@ begin end end; -function parseImportStmt(var p: TParser): PNode; +function parseImportOrIncludeStmt(var p: TParser; kind: TNodeKind): PNode; var a: PNode; begin - result := newNodeP(nkImportStmt, p); - getTok(p); // skip `import` + result := newNodeP(kind, p); + getTok(p); // skip `import` or `include` optInd(p, result); while true do begin case p.tok.tokType of @@ -764,41 +753,6 @@ begin end; end; -function parseIncludeStmt(var p: TParser): PNode; -var - a: PNode; -begin - result := newNodeP(nkIncludeStmt, p); - getTok(p); // skip `include` - optInd(p, result); - while true do begin - case p.tok.tokType of - tkEof, tkSad, tkDed: break; - tkSymbol, tkAccent: a := parseSymbol(p); - tkRStrLit: begin - a := newStrNodeP(nkRStrLit, p.tok.literal, p); - getTok(p) - end; - tkStrLit: begin - a := newStrNodeP(nkStrLit, p.tok.literal, p); - getTok(p); - end; - tkTripleStrLit: begin - a := newStrNodeP(nkTripleStrLit, p.tok.literal, p); - getTok(p) - end; - else begin - parMessage(p, errIdentifierExpected, tokToStr(p.tok)); - break - end; - end; - addSon(result, a); - if p.tok.tokType <> tkComma then break; - getTok(p); - optInd(p, a) - end; -end; - function parseFromStmt(var p: TParser): PNode; var a: PNode; @@ -1150,6 +1104,24 @@ begin indAndComment(p, result); // XXX: special extension! end; +function parseConstSection(var p: TParser): PNode; +begin + result := newNodeP(nkConstSection, p); + getTok(p); + skipComment(p, result); + if p.tok.tokType = tkCurlyLe then begin + getTok(p); + skipComment(p, result); + while (p.tok.tokType <> tkCurlyRi) and (p.tok.tokType <> tkEof) do begin + addSon(result, parseConstant(p)) + end; + eat(p, tkCurlyRi); + end + else + addSon(result, parseConstant(p)); +end; + + function parseEnum(var p: TParser): PNode; var a, b: PNode; @@ -1379,9 +1351,9 @@ begin tkBreak: result := parseBreakOrContinue(p, nkBreakStmt); tkContinue: result := parseBreakOrContinue(p, nkContinueStmt); tkCurlyDotLe: result := parsePragma(p); - tkImport: result := parseImportStmt(p); + tkImport: result := parseImportOrIncludeStmt(p, nkImportStmt); tkFrom: result := parseFromStmt(p); - tkInclude: result := parseIncludeStmt(p); + tkInclude: result := parseImportOrIncludeStmt(p, nkIncludeStmt); tkComment: result := newCommentStmt(p); else begin if isExprStart(p) then @@ -1394,6 +1366,24 @@ begin skipComment(p, result); end; +function parseType(var p: TParser): PNode; +begin + result := newNodeP(nkTypeSection, p); + while true do begin + case p.tok.tokType of + tkComment: skipComment(p, result); + tkType: begin + // type alias: + + end; + tkEnum: + tkObject: + tkTuple: + else break; + end + end +end; + function complexOrSimpleStmt(var p: TParser): PNode; begin case p.tok.tokType of @@ -1410,8 +1400,9 @@ begin tkMacro: result := parseRoutine(p, nkMacroDef); tkTemplate: result := parseRoutine(p, nkTemplateDef); tkConverter: result := parseRoutine(p, nkConverterDef); - tkType: result := parseSection(p, nkTypeSection, parseTypeDef); - tkConst: result := parseSection(p, nkConstSection, parseConstant); + tkType, tkEnum, tkObject, tkTuple: + result := parseTypeAlias(p, nkTypeSection, parseTypeDef); + tkConst: result := parseConstSection(p); tkWhen: result := parseIfOrWhen(p, nkWhenStmt); tkVar: result := parseSection(p, nkVarSection, parseVariable); else result := simpleStmt(p); @@ -1422,15 +1413,13 @@ function parseStmt(var p: TParser): PNode; var a: PNode; begin - if p.tok.tokType = tkInd then begin + if p.tok.tokType = tkCurlyLe then begin result := newNodeP(nkStmtList, p); - pushInd(p.lex^, p.tok.indent); getTok(p); while true do begin case p.tok.tokType of - tkSad: getTok(p); - tkEof: break; - tkDed: begin getTok(p); break end; + tkSad, tkInd, tkDed: getTok(p); + tkEof, tkCurlyRi: break; else begin a := complexOrSimpleStmt(p); if a = nil then break; @@ -1438,7 +1427,7 @@ begin end end end; - popInd(p.lex^); + eat(p, tkCurlyRi); end else begin // the case statement is only needed for better error messages: @@ -1451,7 +1440,7 @@ begin else begin result := simpleStmt(p); if result = nil then parMessage(p, errExprExpected, tokToStr(p.tok)); - if p.tok.tokType = tkSad then getTok(p); + if p.tok.tokType in [tkInd, tkDed, tkSad] then getTok(p); end end end @@ -1464,8 +1453,7 @@ begin result := newNodeP(nkStmtList, p); while true do begin case p.tok.tokType of - tkSad: getTok(p); - tkDed, tkInd: parMessage(p, errInvalidIndentation); + tkDed, tkInd, tkSad: getTok(p); tkEof: break; else begin a := complexOrSimpleStmt(p); @@ -1481,11 +1469,7 @@ begin result := nil; while true do begin case p.tok.tokType of - tkSad: getTok(p); - tkDed, tkInd: begin - parMessage(p, errInvalidIndentation); - break; - end; + tkDed, tkInd, tkSad: getTok(p); tkEof: break; else begin result := complexOrSimpleStmt(p); diff --git a/nim/pendx.pas b/nim/pendx.pas new file mode 100755 index 000000000..e23229e28 --- /dev/null +++ b/nim/pendx.pas @@ -0,0 +1,36 @@ +// +// +// The Nimrod Compiler +// (c) Copyright 2009 Andreas Rumpf +// +// See the file "copying.txt", included in this +// distribution, for details about the copyright. +// +unit pendx; + +{$include config.inc} + +interface + +uses + nsystem, llstream, scanner, idents, strutils, ast, msgs, pnimsyn; + +function ParseAll(var p: TParser): PNode; + +function parseTopLevelStmt(var p: TParser): PNode; +// implements an iterator. Returns the next top-level statement or nil if end +// of stream. + +implementation + +function ParseAll(var p: TParser): PNode; +begin + result := nil +end; + +function parseTopLevelStmt(var p: TParser): PNode; +begin + result := nil +end; + +end. diff --git a/nim/pnimsyn.pas b/nim/pnimsyn.pas index bf964fda1..eeaf2a6e9 100755 --- a/nim/pnimsyn.pas +++ b/nim/pnimsyn.pas @@ -72,6 +72,7 @@ procedure optSad(var p: TParser); procedure optInd(var p: TParser; n: PNode); procedure indAndComment(var p: TParser; n: PNode); +procedure setBaseFlags(n: PNode; base: TNumericalBase); function parseSymbol(var p: TParser): PNode; function accExpr(var p: TParser): PNode; @@ -1069,12 +1070,12 @@ begin end end; -function parseImportStmt(var p: TParser): PNode; +function parseImportOrIncludeStmt(var p: TParser; kind: TNodeKind): PNode; var a: PNode; begin - result := newNodeP(nkImportStmt, p); - getTok(p); // skip `import` + result := newNodeP(kind, p); + getTok(p); // skip `import` or `include` optInd(p, result); while true do begin case p.tok.tokType of @@ -1104,42 +1105,6 @@ begin end; end; -function parseIncludeStmt(var p: TParser): PNode; -var - a: PNode; -begin - result := newNodeP(nkIncludeStmt, p); - getTok(p); // skip `include` - optInd(p, result); - while true do begin - case p.tok.tokType of - tkEof, tkSad, tkDed: break; - tkSymbol, tkAccent: a := parseSymbol(p); - tkRStrLit: begin - a := newStrNodeP(nkRStrLit, p.tok.literal, p); - getTok(p) - end; - tkStrLit: begin - a := newStrNodeP(nkStrLit, p.tok.literal, p); - getTok(p); - end; - tkTripleStrLit: begin - a := newStrNodeP(nkTripleStrLit, p.tok.literal, p); - getTok(p) - end; - else begin - parMessage(p, errIdentifierExpected, tokToStr(p.tok)); - break - end; - end; - addSon(result, a); - //optInd(p, a); - if p.tok.tokType <> tkComma then break; - getTok(p); - optInd(p, a) - end; -end; - function parseFromStmt(var p: TParser): PNode; var a: PNode; @@ -1717,9 +1682,9 @@ begin tkBreak: result := parseBreakOrContinue(p, nkBreakStmt); tkContinue: result := parseBreakOrContinue(p, nkContinueStmt); tkCurlyDotLe: result := parsePragma(p); - tkImport: result := parseImportStmt(p); + tkImport: result := parseImportOrIncludeStmt(p, nkImportStmt); tkFrom: result := parseFromStmt(p); - tkInclude: result := parseIncludeStmt(p); + tkInclude: result := parseImportOrIncludeStmt(p, nkIncludeStmt); tkComment: result := newCommentStmt(p); else begin if isExprStart(p) then diff --git a/nim/semgnrc.pas b/nim/semgnrc.pas new file mode 100755 index 000000000..ee905d444 --- /dev/null +++ b/nim/semgnrc.pas @@ -0,0 +1,287 @@ +// +// +// The Nimrod Compiler +// (c) Copyright 2009 Andreas Rumpf +// +// See the file "copying.txt", included in this +// distribution, for details about the copyright. +// + + +// This implements the first pass over the generic body; it resolves some +// symbols. Thus for generics there is a two-phase symbol lookup just like +// in C++. +// A problem is that it cannot be detected if the symbol is introduced +// as in ``var x = ...`` or used because macros/templates can hide this! +// So we have to eval templates/macros right here so that symbol +// lookup can be accurate. + +type + TSemGenericFlag = (withinBind, withinTypeDesc); + TSemGenericFlags = set of TSemGenericFlag; + +function semGenericStmt(c: PContext; n: PNode; + flags: TSemGenericFlags = {@set}[]): PNode; forward; + +function semGenericStmtScope(c: PContext; n: PNode; + flags: TSemGenericFlags = {@set}[]): PNode; +begin + openScope(c.tab); + result := semGenericStmt(c, n, flags); + closeScope(c.tab); +end; + +function semGenericStmtSymbol(c: PContext; n: PNode; s: PSym): PNode; +begin + case s.kind of + skUnknown: begin + // Introduced in this pass! Leave it as an identifier. + result := n; + end; + skProc, skMethod, skIterator, skConverter: result := symChoice(c, n, s); + skTemplate: result := semTemplateExpr(c, n, s, false); + skMacro: result := semMacroExpr(c, n, s, false); + skGenericParam: result := newSymNode(s); + skParam: result := n; + skType: begin + if (s.typ <> nil) and (s.typ.kind <> tyGenericParam) then + result := newSymNode(s) + else + result := n + end + else result := newSymNode(s) + end +end; + +function getIdentNode(n: PNode): PNode; +begin + case n.kind of + nkPostfix: result := getIdentNode(n.sons[1]); + nkPragmaExpr, nkAccQuoted: result := getIdentNode(n.sons[0]); + nkIdent: result := n; + else begin + illFormedAst(n); + result := nil + end + end +end; + +function semGenericStmt(c: PContext; n: PNode; + flags: TSemGenericFlags = {@set}[]): PNode; +var + i, j, L: int; + a: PNode; + s: PSym; +begin + result := n; + if n = nil then exit; + case n.kind of + nkIdent, nkAccQuoted: begin + s := lookUp(c, n); + if withinBind in flags then + result := symChoice(c, n, s) + else + result := semGenericStmtSymbol(c, n, s); + end; + nkDotExpr: begin + s := QualifiedLookUp(c, n, true); + if s <> nil then + result := semGenericStmtSymbol(c, n, s); + end; + nkSym..nkNilLit: begin end; + nkBind: result := semGenericStmt(c, n.sons[0], {@set}[withinBind]); + + nkCall, nkHiddenCallConv, nkInfix, nkPrefix, nkCommand, nkCallStrLit: begin + // check if it is an expression macro: + checkMinSonsLen(n, 1); + s := qualifiedLookup(c, n.sons[0], false); + if (s <> nil) then begin + case s.kind of + skMacro: begin result := semMacroExpr(c, n, s, false); exit end; + skTemplate: begin result := semTemplateExpr(c, n, s, false); exit end; + skUnknown, skParam: begin + // Leave it as an identifier. + end; + skProc, skMethod, skIterator, skConverter: begin + n.sons[0] := symChoice(c, n.sons[0], s); + end; + skGenericParam: n.sons[0] := newSymNode(s); + skType: begin + // bad hack for generics: + if (s.typ <> nil) and (s.typ.kind <> tyGenericParam) then begin + n.sons[0] := newSymNode(s); + end + end; + else n.sons[0] := newSymNode(s) + end + end; + for i := 1 to sonsLen(n)-1 do + n.sons[i] := semGenericStmt(c, n.sons[i], flags); + end; + nkMacroStmt: begin + result := semMacroStmt(c, n, false); + end; + nkIfStmt: begin + for i := 0 to sonsLen(n)-1 do + n.sons[i] := semGenericStmtScope(c, n.sons[i]); + end; + nkWhileStmt: begin + openScope(c.tab); + for i := 0 to sonsLen(n)-1 do + n.sons[i] := semGenericStmt(c, n.sons[i]); + closeScope(c.tab); + end; + nkCaseStmt: begin + openScope(c.tab); + n.sons[0] := semGenericStmt(c, n.sons[0]); + for i := 1 to sonsLen(n)-1 do begin + a := n.sons[i]; + checkMinSonsLen(a, 1); + L := sonsLen(a); + for j := 0 to L-2 do + a.sons[j] := semGenericStmt(c, a.sons[j]); + a.sons[L-1] := semGenericStmtScope(c, a.sons[L-1]); + end; + closeScope(c.tab); + end; + nkForStmt: begin + L := sonsLen(n); + openScope(c.tab); + n.sons[L-2] := semGenericStmt(c, n.sons[L-2]); + for i := 0 to L-3 do + addDecl(c, newSymS(skUnknown, n.sons[i], c)); + n.sons[L-1] := semGenericStmt(c, n.sons[L-1]); + closeScope(c.tab); + end; + nkBlockStmt, nkBlockExpr, nkBlockType: begin + checkSonsLen(n, 2); + openScope(c.tab); + if n.sons[0] <> nil then + addDecl(c, newSymS(skUnknown, n.sons[0], c)); + n.sons[1] := semGenericStmt(c, n.sons[1]); + closeScope(c.tab); + end; + nkTryStmt: begin + checkMinSonsLen(n, 2); + n.sons[0] := semGenericStmtScope(c, n.sons[0]); + for i := 1 to sonsLen(n)-1 do begin + a := n.sons[i]; + checkMinSonsLen(a, 1); + L := sonsLen(a); + for j := 0 to L-2 do + a.sons[j] := semGenericStmt(c, a.sons[j], {@set}[withinTypeDesc]); + a.sons[L-1] := semGenericStmtScope(c, a.sons[L-1]); + end; + end; + nkVarSection: begin + for i := 0 to sonsLen(n)-1 do begin + a := n.sons[i]; + if a.kind = nkCommentStmt then continue; + if (a.kind <> nkIdentDefs) and (a.kind <> nkVarTuple) then + IllFormedAst(a); + checkMinSonsLen(a, 3); + L := sonsLen(a); + a.sons[L-2] := semGenericStmt(c, a.sons[L-2], {@set}[withinTypeDesc]); + a.sons[L-1] := semGenericStmt(c, a.sons[L-1]); + for j := 0 to L-3 do + addDecl(c, newSymS(skUnknown, getIdentNode(a.sons[j]), c)); + end + end; + nkGenericParams: begin + for i := 0 to sonsLen(n)-1 do begin + a := n.sons[i]; + if (a.kind <> nkIdentDefs) then IllFormedAst(a); + checkMinSonsLen(a, 3); + L := sonsLen(a); + a.sons[L-2] := semGenericStmt(c, a.sons[L-2], {@set}[withinTypeDesc]); + // do not perform symbol lookup for default expressions + for j := 0 to L-3 do + addDecl(c, newSymS(skUnknown, getIdentNode(a.sons[j]), c)); + end + end; + nkConstSection: begin + for i := 0 to sonsLen(n)-1 do begin + a := n.sons[i]; + if a.kind = nkCommentStmt then continue; + if (a.kind <> nkConstDef) then IllFormedAst(a); + checkSonsLen(a, 3); + addDecl(c, newSymS(skUnknown, getIdentNode(a.sons[0]), c)); + a.sons[1] := semGenericStmt(c, a.sons[1], {@set}[withinTypeDesc]); + a.sons[2] := semGenericStmt(c, a.sons[2]); + end + end; + nkTypeSection: begin + for i := 0 to sonsLen(n)-1 do begin + a := n.sons[i]; + if a.kind = nkCommentStmt then continue; + if (a.kind <> nkTypeDef) then IllFormedAst(a); + checkSonsLen(a, 3); + addDecl(c, newSymS(skUnknown, getIdentNode(a.sons[0]), c)); + end; + for i := 0 to sonsLen(n)-1 do begin + a := n.sons[i]; + if a.kind = nkCommentStmt then continue; + if (a.kind <> nkTypeDef) then IllFormedAst(a); + checkSonsLen(a, 3); + if a.sons[1] <> nil then begin + openScope(c.tab); + a.sons[1] := semGenericStmt(c, a.sons[1]); + a.sons[2] := semGenericStmt(c, a.sons[2], {@set}[withinTypeDesc]); + closeScope(c.tab); + end + else + a.sons[2] := semGenericStmt(c, a.sons[2], {@set}[withinTypeDesc]); + end + end; + nkEnumTy: begin + checkMinSonsLen(n, 1); + if n.sons[0] <> nil then + n.sons[0] := semGenericStmt(c, n.sons[0], {@set}[withinTypeDesc]); + for i := 1 to sonsLen(n)-1 do begin + case n.sons[i].kind of + nkEnumFieldDef: a := n.sons[i].sons[0]; + nkIdent: a := n.sons[i]; + else illFormedAst(n); + end; + addDeclAt(c, newSymS(skUnknown, getIdentNode(a.sons[i]), c), + c.tab.tos-1); + end + end; + nkObjectTy, nkTupleTy: begin end; + nkFormalParams: begin + checkMinSonsLen(n, 1); + if n.sons[0] <> nil then + n.sons[0] := semGenericStmt(c, n.sons[0], {@set}[withinTypeDesc]); + for i := 1 to sonsLen(n)-1 do begin + a := n.sons[i]; + if (a.kind <> nkIdentDefs) then IllFormedAst(a); + checkMinSonsLen(a, 3); + L := sonsLen(a); + a.sons[L-1] := semGenericStmt(c, a.sons[L-2], {@set}[withinTypeDesc]); + a.sons[L-1] := semGenericStmt(c, a.sons[L-1]); + for j := 0 to L-3 do begin + addDecl(c, newSymS(skUnknown, getIdentNode(a.sons[j]), c)); + end + end + end; + nkProcDef, nkMethodDef, nkConverterDef, nkMacroDef, nkTemplateDef, + nkIteratorDef, nkLambda: begin + checkSonsLen(n, codePos+1); + addDecl(c, newSymS(skUnknown, getIdentNode(n.sons[0]), c)); + openScope(c.tab); + n.sons[genericParamsPos] := semGenericStmt(c, n.sons[genericParamsPos]); + if n.sons[paramsPos] <> nil then begin + if n.sons[paramsPos].sons[0] <> nil then + addDecl(c, newSym(skUnknown, getIdent('result'), nil)); + n.sons[paramsPos] := semGenericStmt(c, n.sons[paramsPos]); + end; + n.sons[pragmasPos] := semGenericStmt(c, n.sons[pragmasPos]); + n.sons[codePos] := semGenericStmtScope(c, n.sons[codePos]); + closeScope(c.tab); + end + else begin + for i := 0 to sonsLen(n)-1 do + result.sons[i] := semGenericStmt(c, n.sons[i], flags); + end + end +end; diff --git a/nim/semtempl.pas b/nim/semtempl.pas index e639960d3..fc7e12a73 100755 --- a/nim/semtempl.pas +++ b/nim/semtempl.pas @@ -147,7 +147,8 @@ begin end end; -function resolveTemplateParams(c: PContext; n: PNode; withinBind: bool): PNode; +function resolveTemplateParams(c: PContext; n: PNode; withinBind: bool; + var toBind: TIntSet): PNode; var i: int; s: PSym; @@ -155,7 +156,7 @@ begin if n = nil then begin result := nil; exit end; case n.kind of nkIdent: begin - if not withinBind then begin + if not withinBind and not IntSetContains(toBind, n.ident.id) then begin s := SymTabLocalGet(c.Tab, n.ident); if (s <> nil) then begin result := newSymNode(s); @@ -165,17 +166,18 @@ begin result := n end else begin + IntSetIncl(toBind, n.ident.id); result := symChoice(c, n, lookup(c, n)) end end; nkSym..nkNilLit: // atom result := n; nkBind: - result := resolveTemplateParams(c, n.sons[0], true); + result := resolveTemplateParams(c, n.sons[0], true, toBind); else begin result := n; for i := 0 to sonsLen(n)-1 do - result.sons[i] := resolveTemplateParams(c, n.sons[i], withinBind); + result.sons[i] := resolveTemplateParams(c, n.sons[i], withinBind, toBind); end end end; @@ -211,6 +213,7 @@ end; function semTemplateDef(c: PContext; n: PNode): PNode; var s: PSym; + toBind: TIntSet; begin if c.p.owner.kind = skModule then begin s := semIdentVis(c, skTemplate, n.sons[0], {@set}[sfStar]); @@ -248,7 +251,8 @@ begin addParams(c, s.typ.n); // resolve parameters: - n.sons[codePos] := resolveTemplateParams(c, n.sons[codePos], false); + IntSetInit(toBind); + n.sons[codePos] := resolveTemplateParams(c, n.sons[codePos], false, toBind); if not (s.typ.sons[0].kind in [tyStmt, tyTypeDesc]) then n.sons[codePos] := transformToExpr(n.sons[codePos]); diff --git a/nim/syntaxes.pas b/nim/syntaxes.pas index 19035028e..158ab8ea2 100755 --- a/nim/syntaxes.pas +++ b/nim/syntaxes.pas @@ -15,7 +15,7 @@ interface uses nsystem, strutils, llstream, ast, astalgo, idents, scanner, options, msgs, - pnimsyn, ptmplsyn, filters, rnimsyn; + pnimsyn, pbraces, ptmplsyn, filters, rnimsyn; type TFilterKind = (filtNone, filtTemplate, filtReplace, filtStrip); @@ -68,8 +68,8 @@ function parseAll(var p: TParsers): PNode; begin case p.skin of skinStandard: result := pnimsyn.parseAll(p.parser); - skinBraces, skinEndX: InternalError('parser to implement'); - // skinBraces: result := pbraces.parseAll(p.parser); + skinBraces: result := pbraces.parseAll(p.parser); + skinEndX: InternalError('parser to implement'); // skinEndX: result := pendx.parseAll(p.parser); end end; @@ -78,8 +78,8 @@ function parseTopLevelStmt(var p: TParsers): PNode; begin case p.skin of skinStandard: result := pnimsyn.parseTopLevelStmt(p.parser); - skinBraces, skinEndX: InternalError('parser to implement'); - //skinBraces: result := pbraces.parseTopLevelStmt(p.parser); + skinBraces: result := pbraces.parseTopLevelStmt(p.parser); + skinEndX: InternalError('parser to implement'); //skinEndX: result := pendx.parseTopLevelStmt(p.parser); end end; diff --git a/nim/vis.pas b/nim/vis.pas new file mode 100755 index 000000000..b8ba0fc5b --- /dev/null +++ b/nim/vis.pas @@ -0,0 +1,35 @@ +// +// +// The Nimrod Compiler +// (c) Copyright 2009 Andreas Rumpf +// +// See the file "copying.txt", included in this +// distribution, for details about the copyright. +// +unit vis; + +// Virtual instruction set for Nimrod. This is used for LLVM code generation. + +interface + +{$include 'config.inc'} + +uses + nsystem, ast, astalgo, strutils, nhashes, trees, platform, magicsys, + extccomp, options, nversion, nimsets, msgs, crc, bitsets, idents, + lists, types, ccgutils, nos, ntime, ropes, nmath, passes, rodread, + wordrecg, rnimsyn, treetab; + +type + TInstrKind = ( + insAddi, + + ); + TInstruction = record + + end; + + +implementation + +end. |