diff options
Diffstat (limited to 'nim')
-rw-r--r-- | nim/ast.pas | 110 | ||||
-rw-r--r-- | nim/ccgexprs.pas | 29 | ||||
-rw-r--r-- | nim/docgen.pas | 18 | ||||
-rw-r--r-- | nim/evals.pas | 132 | ||||
-rw-r--r-- | nim/importer.pas | 4 | ||||
-rw-r--r-- | nim/lookups.pas | 48 | ||||
-rw-r--r-- | nim/msgs.pas | 62 | ||||
-rw-r--r-- | nim/nimsets.pas | 5 | ||||
-rw-r--r-- | nim/pasparse.pas | 13 | ||||
-rw-r--r-- | nim/pnimsyn.pas | 23 | ||||
-rw-r--r-- | nim/pragmas.pas | 13 | ||||
-rw-r--r-- | nim/rnimsyn.pas | 23 | ||||
-rw-r--r-- | nim/ropes.pas | 5 | ||||
-rw-r--r-- | nim/scanner.pas | 16 | ||||
-rw-r--r-- | nim/sem.pas | 11 | ||||
-rw-r--r-- | nim/semdata.pas | 4 | ||||
-rw-r--r-- | nim/semexprs.pas | 162 | ||||
-rw-r--r-- | nim/semstmts.pas | 41 | ||||
-rw-r--r-- | nim/semtempl.pas | 57 | ||||
-rw-r--r-- | nim/sigmatch.pas | 72 | ||||
-rw-r--r-- | nim/strutils.pas | 11 | ||||
-rw-r--r-- | nim/transf.pas | 22 | ||||
-rw-r--r-- | nim/types.pas | 10 | ||||
-rw-r--r-- | nim/wordrecg.pas | 20 |
24 files changed, 544 insertions, 367 deletions
diff --git a/nim/ast.pas b/nim/ast.pas index 681bf72d5..4836a860e 100644 --- a/nim/ast.pas +++ b/nim/ast.pas @@ -78,27 +78,27 @@ type nkCurly, nkBracket, nkBracketExpr, nkPragmaExpr, nkRange, nkDotExpr, nkCheckedFieldExpr, nkDerefExpr, nkIfExpr, nkElifExpr, nkElseExpr, nkLambda, - nkAccQuoted, nkHeaderQuoted, nkTableConstr, nkQualified, - nkHiddenStdConv, nkHiddenSubConv, nkHiddenCallConv, nkConv, - nkCast, nkAddr, nkHiddenAddr, nkHiddenDeref, - nkObjDownConv, nkObjUpConv, nkChckRangeF, nkChckRange64, - nkChckRange, nkStringToCString, nkCStringToString, nkPassAsOpenArray, - nkAsgn, nkFastAsgn, nkDefaultTypeParam, nkGenericParams, - nkFormalParams, nkOfInherit, nkModule, nkProcDef, - nkConverterDef, nkMacroDef, nkTemplateDef, nkIteratorDef, - nkOfBranch, nkElifBranch, nkExceptBranch, nkElse, - nkMacroStmt, nkAsmStmt, nkPragma, nkIfStmt, - nkWhenStmt, nkForStmt, nkWhileStmt, nkCaseStmt, - nkVarSection, nkConstSection, nkConstDef, nkTypeSection, - nkTypeDef, nkYieldStmt, nkTryStmt, nkFinally, - nkRaiseStmt, nkReturnStmt, nkBreakStmt, nkContinueStmt, - nkBlockStmt, nkDiscardStmt, nkStmtList, nkImportStmt, - nkFromStmt, nkImportAs, nkIncludeStmt, nkCommentStmt, - nkStmtListExpr, nkBlockExpr, nkStmtListType, nkBlockType, - nkVm, nkTypeOfExpr, nkObjectTy, nkTupleTy, - nkRecList, nkRecCase, nkRecWhen, nkRefTy, - nkPtrTy, nkVarTy, nkAbstractTy, nkProcTy, - nkEnumTy, nkEnumFieldDef, nkReturnToken); + nkAccQuoted, nkTableConstr, nkQualified, nkBind, + nkSymChoice, nkHiddenStdConv, nkHiddenSubConv, nkHiddenCallConv, + nkConv, nkCast, nkAddr, nkHiddenAddr, + nkHiddenDeref, nkObjDownConv, nkObjUpConv, nkChckRangeF, + nkChckRange64, nkChckRange, nkStringToCString, nkCStringToString, + nkPassAsOpenArray, nkAsgn, nkFastAsgn, nkDefaultTypeParam, + nkGenericParams, nkFormalParams, nkOfInherit, nkModule, + nkProcDef, nkConverterDef, nkMacroDef, nkTemplateDef, + nkIteratorDef, nkOfBranch, nkElifBranch, nkExceptBranch, + nkElse, nkMacroStmt, nkAsmStmt, nkPragma, + nkIfStmt, nkWhenStmt, nkForStmt, nkWhileStmt, + nkCaseStmt, nkVarSection, nkConstSection, nkConstDef, + nkTypeSection, nkTypeDef, nkYieldStmt, nkTryStmt, + nkFinally, nkRaiseStmt, nkReturnStmt, nkBreakStmt, + nkContinueStmt, nkBlockStmt, nkDiscardStmt, nkStmtList, + nkImportStmt, nkFromStmt, nkImportAs, nkIncludeStmt, + nkCommentStmt, nkStmtListExpr, nkBlockExpr, nkStmtListType, + nkBlockType, nkVm, nkTypeOfExpr, nkObjectTy, + nkTupleTy, nkRecList, nkRecCase, nkRecWhen, + nkRefTy, nkPtrTy, nkVarTy, nkAbstractTy, + nkProcTy, nkEnumTy, nkEnumFieldDef, nkReturnToken); TNodeKinds = set of TNodeKind; const NodeKindToStr: array [TNodeKind] of string = ( @@ -113,48 +113,48 @@ const 'nkCurly', 'nkBracket', 'nkBracketExpr', 'nkPragmaExpr', 'nkRange', 'nkDotExpr', 'nkCheckedFieldExpr', 'nkDerefExpr', 'nkIfExpr', 'nkElifExpr', 'nkElseExpr', 'nkLambda', - 'nkAccQuoted', 'nkHeaderQuoted', 'nkTableConstr', 'nkQualified', - 'nkHiddenStdConv', 'nkHiddenSubConv', 'nkHiddenCallConv', 'nkConv', - 'nkCast', 'nkAddr', 'nkHiddenAddr', 'nkHiddenDeref', - 'nkObjDownConv', 'nkObjUpConv', 'nkChckRangeF', 'nkChckRange64', - 'nkChckRange', 'nkStringToCString', 'nkCStringToString', 'nkPassAsOpenArray', - 'nkAsgn', 'nkFastAsgn', 'nkDefaultTypeParam', 'nkGenericParams', - 'nkFormalParams', 'nkOfInherit', 'nkModule', 'nkProcDef', - 'nkConverterDef', 'nkMacroDef', 'nkTemplateDef', 'nkIteratorDef', - 'nkOfBranch', 'nkElifBranch', 'nkExceptBranch', 'nkElse', - 'nkMacroStmt', 'nkAsmStmt', 'nkPragma', 'nkIfStmt', - 'nkWhenStmt', 'nkForStmt', 'nkWhileStmt', 'nkCaseStmt', - 'nkVarSection', 'nkConstSection', 'nkConstDef', 'nkTypeSection', - 'nkTypeDef', 'nkYieldStmt', 'nkTryStmt', 'nkFinally', - 'nkRaiseStmt', 'nkReturnStmt', 'nkBreakStmt', 'nkContinueStmt', - 'nkBlockStmt', 'nkDiscardStmt', 'nkStmtList', 'nkImportStmt', - 'nkFromStmt', 'nkImportAs', 'nkIncludeStmt', 'nkCommentStmt', - 'nkStmtListExpr', 'nkBlockExpr', 'nkStmtListType', 'nkBlockType', - 'nkVm', 'nkTypeOfExpr', 'nkObjectTy', 'nkTupleTy', - 'nkRecList', 'nkRecCase', 'nkRecWhen', 'nkRefTy', - 'nkPtrTy', 'nkVarTy', 'nkAbstractTy', 'nkProcTy', - 'nkEnumTy', 'nkEnumFieldDef', 'nkReturnToken'); + 'nkAccQuoted', 'nkTableConstr', 'nkQualified', 'nkBind', + 'nkSymChoice', 'nkHiddenStdConv', 'nkHiddenSubConv', 'nkHiddenCallConv', + 'nkConv', 'nkCast', 'nkAddr', 'nkHiddenAddr', + 'nkHiddenDeref', 'nkObjDownConv', 'nkObjUpConv', 'nkChckRangeF', + 'nkChckRange64', 'nkChckRange', 'nkStringToCString', 'nkCStringToString', + 'nkPassAsOpenArray', 'nkAsgn', 'nkFastAsgn', 'nkDefaultTypeParam', + 'nkGenericParams', 'nkFormalParams', 'nkOfInherit', 'nkModule', + 'nkProcDef', 'nkConverterDef', 'nkMacroDef', 'nkTemplateDef', + 'nkIteratorDef', 'nkOfBranch', 'nkElifBranch', 'nkExceptBranch', + 'nkElse', 'nkMacroStmt', 'nkAsmStmt', 'nkPragma', + 'nkIfStmt', 'nkWhenStmt', 'nkForStmt', 'nkWhileStmt', + 'nkCaseStmt', 'nkVarSection', 'nkConstSection', 'nkConstDef', + 'nkTypeSection', 'nkTypeDef', 'nkYieldStmt', 'nkTryStmt', + 'nkFinally', 'nkRaiseStmt', 'nkReturnStmt', 'nkBreakStmt', + 'nkContinueStmt', 'nkBlockStmt', 'nkDiscardStmt', 'nkStmtList', + 'nkImportStmt', 'nkFromStmt', 'nkImportAs', 'nkIncludeStmt', + 'nkCommentStmt', 'nkStmtListExpr', 'nkBlockExpr', 'nkStmtListType', + 'nkBlockType', 'nkVm', 'nkTypeOfExpr', 'nkObjectTy', + 'nkTupleTy', 'nkRecList', 'nkRecCase', 'nkRecWhen', + 'nkRefTy', 'nkPtrTy', 'nkVarTy', 'nkAbstractTy', + 'nkProcTy', 'nkEnumTy', 'nkEnumFieldDef', 'nkReturnToken'); type TSymFlag = ( sfUsed, sfStar, sfMinus, sfInInterface, sfFromGeneric, sfGlobal, sfForward, sfImportc, sfExportc, sfVolatile, sfRegister, sfPure, - sfResult, sfNoSideEffect, sfMainModule, sfSystemModule, - sfNoReturn, sfAddrTaken, sfCompilerProc, sfCppMethod, - sfDiscriminant, sfDeprecated, sfInClosure, sfTypeCheck, - sfCompileTime, sfThreadVar, sfMerge, sfDeadCodeElim, - sfBorrow); + sfResult, sfNoSideEffect, sfSideEffect, sfMainModule, + sfSystemModule, sfNoReturn, sfAddrTaken, sfCompilerProc, + sfCppMethod, sfDiscriminant, sfDeprecated, sfInClosure, + sfTypeCheck, sfCompileTime, sfThreadVar, sfMerge, + sfDeadCodeElim, sfBorrow); TSymFlags = set of TSymFlag; const SymFlagToStr: array [TSymFlag] of string = ( 'sfUsed', 'sfStar', 'sfMinus', 'sfInInterface', 'sfFromGeneric', 'sfGlobal', 'sfForward', 'sfImportc', 'sfExportc', 'sfVolatile', 'sfRegister', 'sfPure', - 'sfResult', 'sfNoSideEffect', 'sfMainModule', 'sfSystemModule', - 'sfNoReturn', 'sfAddrTaken', 'sfCompilerProc', 'sfCppMethod', - 'sfDiscriminant', 'sfDeprecated', 'sfInClosure', 'sfTypeCheck', - 'sfCompileTime', 'sfThreadVar', 'sfMerge', 'sfDeadCodeElim', - 'sfBorrow'); + 'sfResult', 'sfNoSideEffect', 'sfSideEffect', 'sfMainModule', + 'sfSystemModule', 'sfNoReturn', 'sfAddrTaken', 'sfCompilerProc', + 'sfCppMethod', 'sfDiscriminant', 'sfDeprecated', 'sfInClosure', + 'sfTypeCheck', 'sfCompileTime', 'sfThreadVar', 'sfMerge', + 'sfDeadCodeElim', 'sfBorrow'); type TTypeKind = ( tyNone, tyBool, tyChar, tyEmpty, @@ -189,11 +189,13 @@ const 'nfAllConst', 'nfTransf', 'nfSem'); type TTypeFlag = ( - tfVarargs, tfFinal, tfAcyclic, tfEnumHasWholes); + tfVarargs, tfNoSideEffect, tfFinal, tfAcyclic, + tfEnumHasWholes); TTypeFlags = set of TTypeFlag; const TypeFlagToStr: array [TTypeFlag] of string = ( - 'tfVarargs', 'tfFinal', 'tfAcyclic', 'tfEnumHasWholes'); + 'tfVarargs', 'tfNoSideEffect', 'tfFinal', 'tfAcyclic', + 'tfEnumHasWholes'); type TSymKind = ( skUnknownSym, skConditional, skDynLib, skParam, diff --git a/nim/ccgexprs.pas b/nim/ccgexprs.pas index bf03365cd..212017d14 100644 --- a/nim/ccgexprs.pas +++ b/nim/ccgexprs.pas @@ -220,8 +220,7 @@ end; function addrLoc(const a: TLoc): PRope; begin result := a.r; - if not (lfIndirect in a.flags) then - result := con('&'+'', result) + if not (lfIndirect in a.flags) then result := con('&'+'', result) end; function rdCharLoc(const a: TLoc): PRope; @@ -2257,32 +2256,6 @@ begin end; // ---------------------- generation of complex constants --------------------- -(* -function transformRecordExpr(n: PNode): PNode; -var - i: int; - t: PType; - field: PSym; -begin - result := copyNode(n); - newSons(result, sonsLen(n)); - t := getUniqueType(skipTypes(n.Typ, abstractVarRange)); - if t.n = nil then - InternalError(n.info, 'transformRecordExpr: invalid type'); - for i := 0 to sonsLen(n)-1 do begin - assert(n.sons[i].kind = nkExprColonExpr); - assert(n.sons[i].sons[0].kind = nkSym); - field := n.sons[i].sons[0].sym; - field := lookupInRecord(t.n, field.name); - if field = nil then - InternalError(n.sons[i].info, 'transformRecordExpr: unknown field'); - if result.sons[field.position] <> nil then begin - InternalError(n.sons[i].info, 'transformRecordExpr: value twice: ' + - renderTree(n.sons[i])); - end; - result.sons[field.position] := copyTree(n.sons[i].sons[1]); - end; -end; *) function genNamedConstExpr(p: BProc; n: PNode): PRope; begin diff --git a/nim/docgen.pas b/nim/docgen.pas index 5e8ecf7a3..a72f64908 100644 --- a/nim/docgen.pas +++ b/nim/docgen.pas @@ -139,16 +139,22 @@ function ropeFormatNamedVars(const frmt: TFormatStr; const varnames: array of string; const varvalues: array of PRope): PRope; var - i, j, L, start, idx: int; + i, j, L, start, idx, num: int; id: string; begin i := strStart; L := length(frmt); result := nil; + num := 0; while i <= L + StrStart - 1 do begin if frmt[i] = '$' then begin inc(i); // skip '$' case frmt[i] of + '#': begin + app(result, varvalues[num]); + inc(num); + inc(i); + end; '$': begin app(result, '$'+''); inc(i) @@ -162,6 +168,7 @@ begin end; if j > high(varvalues) + 1 then internalError('ropeFormatNamedVars'); + num := j; app(result, varvalues[j - 1]) end; 'A'..'Z', 'a'..'z', #128..#255: begin @@ -515,17 +522,17 @@ begin result := renderRstSons(d, n); L := ropeLen(result); result := ropef('$n$1$2$n$1$3', [ind, result, - toRope(repeatChar(L, lvlToChar[n.level]))]); + toRope(repeatChar(L, lvlToChar[n.level]))]); end; rnOverline: begin result := renderRstSons(d, n); L := ropeLen(result); result := ropef('$n$1$3$n$1$2$n$1$3', [ind, result, - toRope(repeatChar(L, lvlToChar[n.level]))]); + toRope(repeatChar(L, lvlToChar[n.level]))]); end; rnTransition: result := ropef('$n$n$1$2$n$n', - [ind, toRope(repeatChar(78-d.indent, '-'))]); + [ind, toRope(repeatChar(78-d.indent, '-'))]); rnParagraph: begin result := renderRstSons(d, n); result := ropef('$n$n$1$2', [ind, result]); @@ -1003,7 +1010,4 @@ begin generateIndex(d); end; -// #FFD700 -// #9f9b75 - end. diff --git a/nim/evals.pas b/nim/evals.pas index 7c443bad6..d522dfaf0 100644 --- a/nim/evals.pas +++ b/nim/evals.pas @@ -35,8 +35,9 @@ type TEvalContext = object(passes.TPassContext) module: PSym; - tos: PStackFrame; // top of a tos tos + tos: PStackFrame; // top of stack lastException: PNode; + optEval: bool; // evaluation done for optimization purposes end; PEvalContext = ^TEvalContext; @@ -44,12 +45,15 @@ function newStackFrame(): PStackFrame; procedure pushStackFrame(c: PEvalContext; t: PStackFrame); procedure popStackFrame(c: PEvalContext); -function newEvalContext(module: PSym; const filename: string): PEvalContext; +function newEvalContext(module: PSym; const filename: string; + optEval: bool): PEvalContext; function eval(c: PEvalContext; n: PNode): PNode; // eval never returns nil! This simplifies the code a lot and // makes it faster too. +function evalConstExpr(module: PSym; e: PNode): PNode; + function evalPass(): TPass; implementation @@ -71,13 +75,15 @@ begin {@emit result.params := @[];} end; -function newEvalContext(module: PSym; const filename: string): PEvalContext; +function newEvalContext(module: PSym; const filename: string; + optEval: bool): PEvalContext; begin new(result); {@ignore} fillChar(result^, sizeof(result^), 0); {@emit} result.module := module; + result.optEval := optEval; end; procedure pushStackFrame(c: PEvalContext; t: PStackFrame); @@ -228,32 +234,35 @@ begin case result.kind of nkBreakStmt, nkReturnToken: begin end; nkExceptBranch: begin - // exception token! - exc := result; - i := 1; - len := sonsLen(n); - while (i < len) and (n.sons[i].kind = nkExceptBranch) do begin - blen := sonsLen(n.sons[i]); - if blen = 1 then begin - // general except section: - result := evalAux(c, n.sons[i].sons[0]); - exc := result; - break - end - else begin - for j := 0 to blen-2 do begin - assert(n.sons[i].sons[j].kind = nkType); - if exc.typ.id = n.sons[i].sons[j].typ.id then begin - result := evalAux(c, n.sons[i].sons[blen-1]); - exc := result; - break - end + if sonsLen(result) >= 1 then begin + // creating a nkExceptBranch without sons means that it could not be + // evaluated + exc := result; + i := 1; + len := sonsLen(n); + while (i < len) and (n.sons[i].kind = nkExceptBranch) do begin + blen := sonsLen(n.sons[i]); + if blen = 1 then begin + // general except section: + result := evalAux(c, n.sons[i].sons[0]); + exc := result; + break end + else begin + for j := 0 to blen-2 do begin + assert(n.sons[i].sons[j].kind = nkType); + if exc.typ.id = n.sons[i].sons[j].typ.id then begin + result := evalAux(c, n.sons[i].sons[blen-1]); + exc := result; + break + end + end + end; + inc(i); end; - inc(i); - end; - result := evalFinally(c, n, exc); - end; + result := evalFinally(c, n, exc); + end + end else result := evalFinally(c, n, emptyNode); end @@ -339,6 +348,7 @@ begin if n.typ <> nil then d.params[0] := getNullValue(n.typ, n.info); pushStackFrame(c, d); result := evalAux(c, prc); + if result.kind = nkExceptBranch then exit; if n.typ <> nil then result := d.params[0]; popStackFrame(c); end; @@ -572,13 +582,24 @@ begin if result.intVal <> 0 then result := evalAux(c, n.sons[2]) end; +function evalNoOpt(c: PEvalContext; n: PNode): PNode; +begin + result := newNodeI(nkExceptBranch, n.info); + // creating a nkExceptBranch without sons means that it could not be + // evaluated +end; + function evalNew(c: PEvalContext; n: PNode): PNode; var t: PType; begin - t := skipTypes(n.sons[1].typ, abstractVar); - result := newNodeIT(nkRefTy, n.info, t); - addSon(result, getNullValue(t.sons[0], n.info)); + if c.optEval then + result := evalNoOpt(c, n) + else begin + t := skipTypes(n.sons[1].typ, abstractVar); + result := newNodeIT(nkRefTy, n.info, t); + addSon(result, getNullValue(t.sons[0], n.info)); + end end; function evalDeref(c: PEvalContext; n: PNode): PNode; @@ -740,6 +761,7 @@ end; function evalSetLengthStr(c: PEvalContext; n: PNode): PNode; var a, b: PNode; + oldLen, newLen: int; begin result := evalAux(c, n.sons[1]); if result.kind = nkExceptBranch then exit; @@ -748,7 +770,16 @@ begin if result.kind = nkExceptBranch then exit; b := result; case a.kind of - nkStrLit..nkTripleStrLit: setLength(a.strVal, int(getOrdValue(b))); + nkStrLit..nkTripleStrLit: begin + {@ignore} + oldLen := length(a.strVal); + {@emit} + newLen := int(getOrdValue(b)); + setLength(a.strVal, newLen); + {@ignore} + FillChar(a.strVal[oldLen+1], newLen-oldLen, 0); + {@emit} + end else InternalError(n.info, 'evalSetLengthStr') end; result := emptyNode @@ -1241,6 +1272,7 @@ end; function evalAux(c: PEvalContext; n: PNode): PNode; var i: int; + a: PNode; begin result := emptyNode; dec(gNestedEvals); @@ -1254,13 +1286,22 @@ begin nkCall, nkHiddenCallConv, nkMacroStmt, nkCommand: result := evalMagicOrCall(c, n); nkCurly, nkBracket, nkRange: begin - result := copyNode(n); - for i := 0 to sonsLen(n)-1 do addSon(result, evalAux(c, n.sons[i])); + a := copyNode(n); + for i := 0 to sonsLen(n)-1 do begin + result := evalAux(c, n.sons[i]); + if result.kind = nkExceptBranch then exit; + addSon(a, result); + end; + result := a end; nkPar: begin - result := copyTree(n); - for i := 0 to sonsLen(n)-1 do - result.sons[i].sons[1] := evalAux(c, n.sons[i].sons[1]); + a := copyTree(n); + for i := 0 to sonsLen(n)-1 do begin + result := evalAux(c, n.sons[i].sons[1]); + if result.kind = nkExceptBranch then exit; + a.sons[i].sons[1] := result; + end; + result := a end; nkBracketExpr: result := evalArrayAccess(c, n); nkDotExpr: result := evalFieldAccess(c, n); @@ -1313,15 +1354,30 @@ begin gWhileCounter := evalMaxIterations; gNestedEvals := evalMaxRecDepth; result := evalAux(c, n); - if result.kind = nkExceptBranch then + if (result.kind = nkExceptBranch) and (sonsLen(result) >= 1) then stackTrace(c, n, errUnhandledExceptionX, typeToString(result.typ)); end; +function evalConstExpr(module: PSym; e: PNode): PNode; +var + p: PEvalContext; + s: PStackFrame; +begin + p := newEvalContext(module, '', true); + s := newStackFrame(); + s.call := e; + pushStackFrame(p, s); + result := eval(p, e); + if (result <> nil) and (result.kind = nkExceptBranch) then + result := nil; + popStackFrame(p); +end; + function myOpen(module: PSym; const filename: string): PPassContext; var c: PEvalContext; begin - c := newEvalContext(module, filename); + c := newEvalContext(module, filename, false); pushStackFrame(c, newStackFrame()); result := c; end; diff --git a/nim/importer.pas b/nim/importer.pas index 5c49259c2..fdb72fd4b 100644 --- a/nim/importer.pas +++ b/nim/importer.pas @@ -68,8 +68,8 @@ begin if (check <> nil) and (check.id <> copy.id) then begin if not (s.kind in OverloadableSyms) then begin // s and check need to be qualified: - IntSetIncl(c.AmbigiousSymbols, copy.id); - IntSetIncl(c.AmbigiousSymbols, check.id); + IntSetIncl(c.AmbiguousSymbols, copy.id); + IntSetIncl(c.AmbiguousSymbols, check.id); end end; StrTableAdd(c.tab.stack[importTablePos], copy); diff --git a/nim/lookups.pas b/nim/lookups.pas index a9a4a783b..d106ef302 100644 --- a/nim/lookups.pas +++ b/nim/lookups.pas @@ -1,7 +1,7 @@ // // // The Nimrod Compiler -// (c) Copyright 2008 Andreas Rumpf +// (c) Copyright 2009 Andreas Rumpf // // See the file "copying.txt", included in this // distribution, for details about the copyright. @@ -19,7 +19,8 @@ uses {$include 'config.inc'} type - TOverloadIterMode = (oimNoQualifier, oimSelfModule, oimOtherModule); + TOverloadIterMode = (oimDone, oimNoQualifier, oimSelfModule, oimOtherModule, + oimSymChoice); TOverloadIter = record stackPtr: int; it: TIdentIter; @@ -43,7 +44,7 @@ procedure addInterfaceOverloadableSymAt(c: PContext; sym: PSym; at: int); function lookUp(c: PContext; n: PNode): PSym; // Looks up a symbol. Generates an error in case of nil. -function QualifiedLookUp(c: PContext; n: PNode; ambigiousCheck: bool): PSym; +function QualifiedLookUp(c: PContext; n: PNode; ambiguousCheck: bool): PSym; function InitOverloadIter(out o: TOverloadIter; c: PContext; n: PNode): PSym; function nextOverloadIter(var o: TOverloadIter; c: PContext; n: PNode): PSym; @@ -139,22 +140,22 @@ begin result := SymtabGet(c.Tab, n.sym.name); if result = nil then liMessage(n.info, errUndeclaredIdentifier, n.sym.name.s); - include(result.flags, sfUsed); + //include(result.flags, sfUsed); end; nkIdent: begin result := SymtabGet(c.Tab, n.ident); if result = nil then liMessage(n.info, errUndeclaredIdentifier, n.ident.s); - include(result.flags, sfUsed); + //include(result.flags, sfUsed); end else InternalError(n.info, 'lookUp'); end; - if IntSetContains(c.AmbigiousSymbols, result.id) then + if IntSetContains(c.AmbiguousSymbols, result.id) then liMessage(n.info, errUseQualifier, result.name.s); if result.kind = skStub then loadStub(result); end; -function QualifiedLookUp(c: PContext; n: PNode; ambigiousCheck: bool): PSym; +function QualifiedLookUp(c: PContext; n: PNode; ambiguousCheck: bool): PSym; var m: PSym; ident: PIdent; @@ -164,16 +165,16 @@ begin result := SymtabGet(c.Tab, n.ident); if result = nil then liMessage(n.info, errUndeclaredIdentifier, n.ident.s) - else if ambigiousCheck - and IntSetContains(c.AmbigiousSymbols, result.id) then + else if ambiguousCheck + and IntSetContains(c.AmbiguousSymbols, result.id) then liMessage(n.info, errUseQualifier, n.ident.s) end; nkSym: begin result := SymtabGet(c.Tab, n.sym.name); if result = nil then liMessage(n.info, errUndeclaredIdentifier, n.sym.name.s) - else if ambigiousCheck - and IntSetContains(c.AmbigiousSymbols, result.id) then + else if ambiguousCheck + and IntSetContains(c.AmbiguousSymbols, result.id) then liMessage(n.info, errUseQualifier, n.sym.name.s) end; nkDotExpr, nkQualified: begin @@ -200,7 +201,7 @@ begin renderTree(n.sons[1])); end end; - nkAccQuoted: result := QualifiedLookup(c, n.sons[0], ambigiousCheck); + nkAccQuoted: result := QualifiedLookup(c, n.sons[0], ambiguousCheck); else begin result := nil; //liMessage(n.info, errIdentifierExpected, '') @@ -224,15 +225,18 @@ begin result := InitIdentIter(o.it, c.tab.stack[o.stackPtr], n.ident); end; end; - nkSym: begin + nkSym: begin + result := n.sym; + o.mode := oimDone; + (* o.stackPtr := c.tab.tos; o.mode := oimNoQualifier; while (result = nil) do begin dec(o.stackPtr); if o.stackPtr < 0 then break; result := InitIdentIter(o.it, c.tab.stack[o.stackPtr], n.sym.name); - end; - end; + end; *) + end; nkDotExpr, nkQualified: begin o.mode := oimOtherModule; o.m := qualifiedLookUp(c, n.sons[0], false); @@ -258,6 +262,11 @@ begin end end; nkAccQuoted: result := InitOverloadIter(o, c, n.sons[0]); + nkSymChoice: begin + o.mode := oimSymChoice; + result := n.sons[0].sym; + o.stackPtr := 1 + end; else begin end end; if (result <> nil) and (result.kind = skStub) then loadStub(result); @@ -266,6 +275,7 @@ end; function nextOverloadIter(var o: TOverloadIter; c: PContext; n: PNode): PSym; begin case o.mode of + oimDone: result := nil; oimNoQualifier: begin if n.kind = nkAccQuoted then result := nextOverloadIter(o, c, n.sons[0]) // BUGFIX @@ -282,6 +292,14 @@ begin end; oimSelfModule: result := nextIdentIter(o.it, c.tab.stack[ModuleTablePos]); oimOtherModule: result := nextIdentIter(o.it, o.m.tab); + oimSymChoice: begin + if o.stackPtr < sonsLen(n) then begin + result := n.sons[o.stackPtr].sym; + inc(o.stackPtr); + end + else + result := nil + end; end; if (result <> nil) and (result.kind = skStub) then loadStub(result); end; diff --git a/nim/msgs.pas b/nim/msgs.pas index 48ffc9ee5..0f47695af 100644 --- a/nim/msgs.pas +++ b/nim/msgs.pas @@ -1,7 +1,7 @@ // // // The Nimrod Compiler -// (c) Copyright 2008 Andreas Rumpf +// (c) Copyright 2009 Andreas Rumpf // // See the file "copying.txt", included in this // distribution, for details about the copyright. @@ -79,19 +79,15 @@ type errNoneSpeedOrSizeExpected, errInvalidPragma, errUnknownPragma, - errPragmaXHereNotAllowed, errUnknownDirective, errInvalidDirective, errAtPopWithoutPush, errEmptyAsm, - errAsgnInvalidInExpr, errInvalidIndentation, errExceptionExpected, errExceptionAlreadyHandled, - errReturnNotAllowedHere, errYieldNotAllowedHere, errInvalidNumberOfYieldExpr, - errReturnInvalidInIterator, errCannotReturnExpr, errAttemptToRedefine, errStmtInvalidAfterReturn, @@ -116,7 +112,6 @@ type errExprExpected, errUndeclaredIdentifier, errUseQualifier, - errTwiceForwarded, errTypeExpected, errSystemNeeds, errExecutionOfProgramFailed, @@ -126,8 +121,7 @@ type errXExpectsTypeOrValue, errXExpectsArrayType, errIteratorCannotBeInstantiated, - errExprWithNoTypeCannotBeConverted, - errExprWithNoTypeCannotBeCasted, + errExprXAmbiguous, errConstantDivisionByZero, errOrdinalTypeExpected, errOrdinalOrFloatTypeExpected, @@ -145,21 +139,17 @@ type errValueOutOfSetBounds, errFieldInitTwice, errFieldNotInit, - errExprCannotBeCalled, + errExprXCannotBeCalled, errExprHasNoType, errExprXHasNoType, errCastNotInSafeMode, errExprCannotBeCastedToX, - errUndefinedPrefixOpr, errCommaOrParRiExpected, errCurlyLeOrParLeExpected, errSectionExpected, - errImplemenationExpected, errRangeExpected, - errInvalidTypeDescription, errAttemptToRedefineX, errMagicOnlyInSystem, - errUnknownOperatorX, errPowerOfTwoExpected, errStringMayNotBeEmpty, errCallConvExpected, @@ -193,9 +183,8 @@ type errTypeMismatch, errButExpected, errButExpectedX, - errAmbigiousCallXYZ, + errAmbiguousCallXYZ, errWrongNumberOfTypeParams, - errOutParamNoDefaultValue, errInlineProcHasNoAddress, errXCannotBeInParamDecl, errPragmaOnlyInHeaderOfProc, @@ -204,21 +193,15 @@ type errNoSymbolToBorrowFromFound, errDiscardValue, errInvalidDiscard, - errUnknownPrecedence, errIllegalConvFromXtoY, - errTypeMismatchExpectedXGotY, errCannotBindXTwice, errInvalidOrderInEnumX, errEnumXHasWholes, errExceptExpected, errInvalidTry, - errEofExpectedButXFound, errOptionExpected, - errCannotEvaluateForwardConst, errXisNoLabel, - errXNeedsConcreteType, errNotAllCasesCovered, - errStringRange, errUnkownSubstitionVar, errComplexStmtRequiresInd, errXisNotCallable, @@ -279,6 +262,7 @@ type errUnhandledExceptionX, errCyclicTree, errXisNoMacroOrTemplate, + errXhasSideEffects, errUser, warnCannotOpenFile, warnOctalEscape, @@ -338,19 +322,15 @@ const '''none'', ''speed'' or ''size'' expected', 'invalid pragma', 'unknown pragma: ''$1''', - 'pragma ''$1'' here not allowed', 'unknown directive: ''$1''', 'invalid directive', '''pop'' without a ''push'' pragma', 'empty asm statement makes no sense', - '''='' invalid in an expression; probably ''=='' meant', 'invalid indentation', 'exception expected', 'exception already handled', - '''return'' only allowed in routine', '''yield'' only allowed in a loop of an iterator', 'invalid number of ''yield'' expresions', - '''return'' not allowed in iterator', 'current routine cannot return an expression', 'attempt to redefine ''$1''', 'statement not allowed after ''return'', ''break'' or ''raise''', @@ -374,19 +354,17 @@ const ''':'' or ''='' expected, but found ''$1''', 'expression expected, but found ''$1''', 'undeclared identifier: ''$1''', - 'ambigious identifier: ''$1'' -- use a qualifier', - '''$1'' is forwarded twice', + 'ambiguous identifier: ''$1'' -- use a qualifier', 'type expected', 'system module needs ''$1''', 'execution of an external program failed', - 'overloaded ''$1'' leads to ambigious calls', + 'overloaded ''$1'' leads to ambiguous calls', 'invalid argument for ''$1''', 'statement has no effect', '''$1'' expects a type or value', '''$1'' expects an array type', '''$1'' cannot be instantiated because its body has not been compiled yet', - 'expression with no type cannot be converted', - 'expression with no type cannot be casted', + 'expression ''$1'' ambiguous in this context', 'constant division by zero', 'ordinal type expected', 'ordinal or float type expected', @@ -404,21 +382,17 @@ const 'value out of set bounds', 'field initialized twice: ''$1''', 'field ''$1'' not initialized', - 'expression cannot be called', + 'expression ''$1'' cannot be called', 'expression has no type', - 'expression ''$1'' has no type', + 'expression ''$1'' has no type (or is ambiguous)', '''cast'' not allowed in safe mode', 'expression cannot be casted to $1', - 'undefined prefix operator: $1', ''','' or '')'' expected', '''{'' or ''('' expected', 'section (''type'', ''proc'', etc.) expected', - '''implementation'' or end of file expected', 'range expected', - 'invalid type description', 'attempt to redefine ''$1''', '''magic'' only allowed in system module', - 'unkown operator: ''$1''', 'power of two expected', 'string literal may not be empty', 'calling convention expected', @@ -452,9 +426,8 @@ const 'type mismatch: got (', 'but expected one of: ', 'but expected ''$1''', - 'ambigious call; both $1 and $2 match for: $3', + 'ambiguous call; both $1 and $2 match for: $3', 'wrong number of type parameters', - 'out parameters cannot have default values', 'an inline proc has no address', '$1 cannot be declared in parameter declaration', 'pragmas are only in the header of a proc allowed', @@ -463,21 +436,15 @@ const 'no symbol to borrow from found', 'value returned by statement has to be discarded', 'statement returns no value that can be discarded', - 'unknown precedence for operator; use ''infix: prec'' pragma', 'conversion from $1 to $2 is invalid', - 'type mismatch: expected ''$1'', but got ''$2''', 'cannot bind parameter ''$1'' twice', 'invalid order in enum ''$1''', 'enum ''$1'' has wholes', '''except'' or ''finally'' expected', 'after catch all ''except'' or ''finally'' no section may follow', - 'end of file expected, but found token ''$1''', 'option expected, but found ''$1''', - 'cannot evaluate forwarded constant', '''$1'' is not a label', - '''$1'' needs to be of a non-generic type', 'not all cases are covered', - 'string range in case statement not allowed', 'unknown substitution variable: ''$1''', 'complex statement requires indentation', '''$1'' is not callable', @@ -489,7 +456,7 @@ const 'no return type for $1 allowed', 'a type conversion needs exactly one argument', 'invalid pragma: $1', - '$1 here not allowed', + '$1 not allowed here', 'invalid control flow: $1', 'a type has no value', 'invalid type: ''$1''', @@ -499,11 +466,11 @@ const 'invalid expression: ''$1''', 'enum has no value ''$1''', 'named expression expected', - 'named expression here not allowed', + 'named expression not allowed here', '''$1'' expects one type parameter', 'array expects two type parameters', 'invalid invisibility: ''$1''', - 'initialization here not allowed', + 'initialization not allowed here', '''$1'' cannot be assigned to', 'iterators can only be defined at the module''s top level', 'iterator needs an implementation', @@ -538,6 +505,7 @@ const 'unhandled exception: $1', 'macro returned a cyclic abstract syntax tree', '''$1'' is no macro or template', + '''$1'' can have side effects', '$1', 'cannot open ''$1'' [CannotOpenFile]', 'octal escape sequences do not exist; leading zero is ignored [OctalEscape]', diff --git a/nim/nimsets.pas b/nim/nimsets.pas index 7fa3dbc12..9795817b8 100644 --- a/nim/nimsets.pas +++ b/nim/nimsets.pas @@ -1,15 +1,14 @@ // // // The Nimrod Compiler -// (c) Copyright 2008 Andreas Rumpf +// (c) Copyright 2009 Andreas Rumpf // // See the file "copying.txt", included in this // distribution, for details about the copyright. // unit nimsets; -// this unit handles Morpork sets; it implements symbolic sets -// the code here should be reused in the Morpork standard library +// this unit handles Nimrod sets; it implements symbolic sets interface diff --git a/nim/pasparse.pas b/nim/pasparse.pas index d0353fc86..73280aeca 100644 --- a/nim/pasparse.pas +++ b/nim/pasparse.pas @@ -40,12 +40,11 @@ const ImportBlackList: array [1..3] of string = ( 'nsystem', 'sysutils', 'charsets' ); - stdReplacements: array [1..20] of TReplaceTuple = ( + stdReplacements: array [1..19] of TReplaceTuple = ( ('include', 'incl'), ('exclude', 'excl'), ('pchar', 'cstring'), - ('close', 'closeFile'), - ('assignfile', 'openFile'), + ('assignfile', 'open'), ('integer', 'int'), ('longword', 'int32'), ('cardinal', 'int'), @@ -62,10 +61,12 @@ const ('len', 'length'), ('setlength', 'setlen') ); - nimReplacements: array [1..30] of TReplaceTuple = ( + nimReplacements: array [1..32] of TReplaceTuple = ( ('nimread', 'read'), ('nimwrite', 'write'), - ('nimclosefile', 'closeFile'), + ('nimclosefile', 'close'), + ('closefile', 'close'), + ('openfile', 'open'), ('nsystem', 'system'), ('ntime', 'times'), ('nos', 'os'), @@ -1972,7 +1973,7 @@ begin if isHandledDirective(p) then addSon(result, parseDirective(p)) else - parMessage(p, errPragmaXHereNotAllowed, p.tok.ident.s) + parMessage(p, errXNotAllowedHere, p.tok.ident.s) end else addSon(result, parseStmt(p)) end; diff --git a/nim/pnimsyn.pas b/nim/pnimsyn.pas index 51c0cd4f5..2ca411770 100644 --- a/nim/pnimsyn.pas +++ b/nim/pnimsyn.pas @@ -313,9 +313,8 @@ end; function accExpr(var p: TParser): PNode; var x, y: PNode; - info: TLineInfo; begin - info := parLineInfo(p); + result := newNodeP(nkAccQuoted, p); getTok(p); // skip ` x := nil; y := nil; @@ -343,16 +342,7 @@ begin end end; end; - if (p.tok.tokType = tkParLe) or (p.tok.tokType = tkColon) then begin - result := newNodeP(nkHeaderQuoted, p); - addSon(result, x); - addSon(result, parseParamList(p)); - end - else begin - result := newNodeP(nkAccQuoted, p); - addSon(result, x); - end; - result.info := info; + addSon(result, x); eat(p, tkAccent); end; @@ -665,6 +655,13 @@ begin optInd(p, a); addSon(result, primary(p)); exit + end + else if p.tok.tokType = tkBind then begin + result := newNodeP(nkBind, p); + getTok(p); + optInd(p, result); + addSon(result, primary(p)); + exit end; result := identOrLiteral(p); while true do begin @@ -798,7 +795,7 @@ end; function isExprStart(const p: TParser): bool; begin case p.tok.tokType of - tkSymbol, tkAccent, tkOpr, tkNot, tkNil, tkCast, tkIf, tkLambda, + tkSymbol, tkAccent, tkOpr, tkNot, tkNil, tkCast, tkIf, tkLambda, tkBind, tkParLe, tkBracketLe, tkCurlyLe, tkIntLit..tkCharLit: result := true; else result := false; end; diff --git a/nim/pragmas.pas b/nim/pragmas.pas index 9f4a543c5..f81cdd6e2 100644 --- a/nim/pragmas.pas +++ b/nim/pragmas.pas @@ -499,7 +499,11 @@ begin // otherwise header would not make sense if sym.loc.r = nil then sym.loc.r := toRope(sym.name.s) end; - wNosideeffect: begin noVal(it); Include(sym.flags, sfNoSideEffect); end; + wNosideeffect: begin + noVal(it); Include(sym.flags, sfNoSideEffect); + if sym.typ <> nil then include(sym.typ.flags, tfNoSideEffect); + end; + wSideEffect: begin noVal(it); Include(sym.flags, sfSideEffect); end; wNoReturn: begin noVal(it); Include(sym.flags, sfNoReturn); end; wDynLib: processDynLib(c, it, sym); wCompilerProc: begin @@ -597,7 +601,7 @@ end; procedure pragmaProc(c: PContext; s: PSym; n: PNode); begin pragma(c, s, n, {@set}[FirstCallConv..LastCallConv, - wImportc, wExportc, wNodecl, wMagic, wNosideEffect, + wImportc, wExportc, wNodecl, wMagic, wNosideEffect, wSideEffect, wNoreturn, wDynLib, wHeader, wCompilerProc, wPure, wCppMethod, wDeprecated, wVarargs, wCompileTime, wMerge, wBorrow]); @@ -612,7 +616,8 @@ end; procedure pragmaIterator(c: PContext; s: PSym; n: PNode); begin - pragma(c, s, n, {@set}[FirstCallConv..LastCallConv, + pragma(c, s, n, {@set}[FirstCallConv..LastCallConv, + wNosideEffect, wSideEffect, wImportc, wExportc, wNodecl, wMagic, wDeprecated, wBorrow]); end; @@ -630,7 +635,7 @@ end; procedure pragmaLambda(c: PContext; s: PSym; n: PNode); begin pragma(c, s, n, {@set}[FirstCallConv..LastCallConv, - wImportc, wExportc, wNodecl, wNosideEffect, + wImportc, wExportc, wNodecl, wNosideEffect, wSideEffect, wNoreturn, wDynLib, wHeader, wPure, wDeprecated]); end; diff --git a/nim/rnimsyn.pas b/nim/rnimsyn.pas index 5be10a0f3..0ed3cfcd7 100644 --- a/nim/rnimsyn.pas +++ b/nim/rnimsyn.pas @@ -1,7 +1,7 @@ // // // The Nimrod Compiler -// (c) Copyright 2008 Andreas Rumpf +// (c) Copyright 2009 Andreas Rumpf // // See the file "copying.txt", included in this // distribution, for details about the copyright. @@ -498,8 +498,10 @@ begin nkCommand: result := lsub(n.sons[0])+lcomma(n, 1)+1; nkExprEqExpr, nkDefaultTypeParam, nkAsgn, nkFastAsgn: result := lsons(n)+3; nkPar, nkCurly, nkBracket: result := lcomma(n)+2; + nkSymChoice: result := lsons(n) + length('()') + sonsLen(n)-1; nkTupleTy: result := lcomma(n)+length('tuple[]'); nkQualified, nkDotExpr: result := lsons(n)+1; + nkBind: result := lsons(n)+length('bind_'); nkCheckedFieldExpr: result := lsub(n.sons[0]); nkLambda: result := lsons(n)+length('lambda__=_'); nkConstDef, nkIdentDefs: begin @@ -531,7 +533,6 @@ begin nkDerefExpr: result := lsub(n.sons[0])+2; nkImportAs: result := lsons(n) + length('_as_'); nkAccQuoted: result := lsub(n.sons[0]) + 2; - nkHeaderQuoted: result := lsub(n.sons[0]) + lsub(n.sons[1]) + 2; nkIfExpr: result := lsub(n.sons[0].sons[0])+lsub(n.sons[0].sons[1]) + lsons(n, 1) + length('if_:_'); @@ -1023,6 +1024,14 @@ begin gcomma(g, n, 1); put(g, tkParRi, ')'+''); end; + nkSymChoice: begin + put(g, tkParLe, '('+''); + for i := 0 to sonsLen(n)-1 do begin + if i > 0 then put(g, tkOpr, '|'+''); + gsub(g, n.sons[i], c); + end; + put(g, tkParRi, ')'+''); + end; nkPar: begin put(g, tkParLe, '('+''); gcomma(g, n, c); @@ -1043,6 +1052,10 @@ begin put(g, tkDot, '.'+''); gsub(g, n.sons[1]); end; + nkBind: begin + putWithSpace(g, tkBind, 'bind'); + gsub(g, n.sons[0]); + end; nkCheckedFieldExpr, nkHiddenAddr, nkHiddenDeref: gsub(g, n.sons[0]); nkLambda: begin assert(n.sons[genericParamsPos] = nil); @@ -1119,12 +1132,6 @@ begin gsub(g, n.sons[0]); put(g, tkAccent, '`'+''); end; - nkHeaderQuoted: begin - put(g, tkAccent, '`'+''); - gsub(g, n.sons[0]); - gsub(g, n.sons[1]); - put(g, tkAccent, '`'+''); - end; nkIfExpr: begin putWithSpace(g, tkIf, 'if'); gsub(g, n.sons[0].sons[0]); diff --git a/nim/ropes.pas b/nim/ropes.pas index 6b6540c24..286f1b9e6 100644 --- a/nim/ropes.pas +++ b/nim/ropes.pas @@ -488,22 +488,25 @@ end; function ropef(const frmt: TFormatStr; const args: array of PRope): PRope; var - i, j, len, start: int; + i, j, len, start, num: int; begin i := strStart; len := length(frmt); result := nil; + num := 0; while i <= len + StrStart - 1 do begin if frmt[i] = '$' then begin inc(i); // skip '$' case frmt[i] of '$': begin app(result, '$'+''); inc(i); end; + '#': begin inc(i); app(result, args[num]); inc(num); end; '0'..'9': begin j := 0; repeat j := (j*10) + Ord(frmt[i]) - ord('0'); inc(i); until (i > len + StrStart - 1) or not (frmt[i] in ['0'..'9']); + num := j; if j > high(args)+1 then internalError('ropes: invalid format string $' + toString(j)); app(result, args[j-1]); diff --git a/nim/scanner.pas b/nim/scanner.pas index d1f32135c..edc9ca24a 100644 --- a/nim/scanner.pas +++ b/nim/scanner.pas @@ -53,10 +53,10 @@ type //cog.out(idents) //]]] tkAbstract, tkAddr, tkAnd, tkAs, - tkAsm, tkBlock, tkBreak, tkCase, - tkCast, tkConst, tkContinue, tkConverter, - tkDiscard, tkDiv, tkElif, tkElse, - tkEnd, tkEnum, tkExcept, tkException, + tkAsm, tkBind, tkBlock, tkBreak, + tkCase, tkCast, tkConst, tkContinue, + tkConverter, tkDiscard, tkDiv, tkElif, + tkElse, tkEnd, tkEnum, tkExcept, tkFinally, tkFor, tkFrom, tkGeneric, tkIf, tkImplies, tkImport, tkIn, tkInclude, tkIs, tkIsnot, tkIterator, @@ -97,10 +97,10 @@ const //cog.out(strings) //]]] 'abstract', 'addr', 'and', 'as', - 'asm', 'block', 'break', 'case', - 'cast', 'const', 'continue', 'converter', - 'discard', 'div', 'elif', 'else', - 'end', 'enum', 'except', 'exception', + 'asm', 'bind', 'block', 'break', + 'case', 'cast', 'const', 'continue', + 'converter', 'discard', 'div', 'elif', + 'else', 'end', 'enum', 'except', 'finally', 'for', 'from', 'generic', 'if', 'implies', 'import', 'in', 'include', 'is', 'isnot', 'iterator', diff --git a/nim/sem.pas b/nim/sem.pas index c0826bdbe..1fd141f5a 100644 --- a/nim/sem.pas +++ b/nim/sem.pas @@ -90,8 +90,6 @@ end; function semAndEvalConstExpr(c: PContext; n: PNode): PNode; var e: PNode; - p: PEvalContext; - s: PStackFrame; begin e := semExprWithType(c, n); if e = nil then begin @@ -101,12 +99,7 @@ begin result := getConstExpr(c.module, e); if result = nil then begin //writeln(output, renderTree(n)); - p := newEvalContext(c.module, ''); - s := newStackFrame(); - s.call := e; - pushStackFrame(p, s); - result := eval(p, e); - popStackFrame(p); + result := evalConstExpr(c.module, e); if (result = nil) or (result.kind = nkEmpty) then liMessage(n.info, errConstExprExpected); end @@ -135,7 +128,7 @@ var s: PStackFrame; begin include(sym.flags, sfUsed); - p := newEvalContext(c.module, ''); + p := newEvalContext(c.module, '', false); s := newStackFrame(); s.call := n; setLength(s.params, 2); diff --git a/nim/semdata.pas b/nim/semdata.pas index acca48376..acaffd3bf 100644 --- a/nim/semdata.pas +++ b/nim/semdata.pas @@ -45,7 +45,7 @@ type module: PSym; // the module sym belonging to the context filename: string; // the module's filename tab: TSymTab; // each module has its own symbol table - AmbigiousSymbols: TIntSet; // contains ids of all ambigious symbols (cannot + AmbiguousSymbols: TIntSet; // contains ids of all ambiguous symbols (cannot // store this info in the syms themselves!) generics: PNode; // a list of the things to compile; list of // nkExprEqExpr nodes which contain the generic @@ -156,7 +156,7 @@ begin fillChar(result^, sizeof(result^), 0); {@emit} InitSymTab(result.tab); - IntSetInit(result.AmbigiousSymbols); + IntSetInit(result.AmbiguousSymbols); initLinkedList(result.optionStack); initLinkedList(result.libs); append(result.optionStack, newOptionEntry()); diff --git a/nim/semexprs.pas b/nim/semexprs.pas index 74cd44b3d..de37295b7 100644 --- a/nim/semexprs.pas +++ b/nim/semexprs.pas @@ -1,6 +1,6 @@ // // -// The Ethexor Morpork Compiler +// The Nimrod Compiler // (c) Copyright 2009 Andreas Rumpf // // See the file "copying.txt", included in this @@ -110,18 +110,33 @@ begin end; function semConv(c: PContext; n: PNode; s: PSym): PNode; +var + op: PNode; + i: int; begin if sonsLen(n) <> 2 then liMessage(n.info, errConvNeedsOneArg); result := newNodeI(nkConv, n.info); result.typ := semTypeNode(c, n.sons[0], nil); addSon(result, copyTree(n.sons[0])); addSon(result, semExprWithType(c, n.sons[1])); - checkConvertible(result.info, result.typ, result.sons[1].typ); + op := result.sons[1]; + if op.kind <> nkSymChoice then + checkConvertible(result.info, result.typ, op.typ) + else begin + for i := 0 to sonsLen(op)-1 do begin + if sameType(result.typ, op.sons[i].typ) then begin + include(op.sons[i].sym.flags, sfUsed); + result := op.sons[i]; exit + end + end; + liMessage(n.info, errUseQualifier, op.sons[0].sym.name.s); + end end; function semCast(c: PContext; n: PNode): PNode; begin if optSafeCode in gGlobalOptions then liMessage(n.info, errCastNotInSafeMode); + include(c.p.owner.flags, sfSideEffect); checkSonsLen(n, 2); result := newNodeI(nkCast, n.info); result.typ := semTypeNode(c, n.sons[0], nil); @@ -354,7 +369,7 @@ function isAssignable(n: PNode): bool; begin result := false; case n.kind of - nkSym: result := n.sym.kind in [skVar, skTemp]; + nkSym: result := (n.sym.kind in [skVar, skTemp]); nkDotExpr, nkQualified, nkBracketExpr: begin checkMinSonsLen(n, 1); if skipTypes(n.sons[0].typ, abstractInst).kind in [tyVar, tyPtr, tyRef] then @@ -373,7 +388,7 @@ begin nkObjUpConv, nkObjDownConv, nkCheckedFieldExpr: result := isAssignable(n.sons[0]); else begin end - end + end; end; function newHiddenAddrTaken(c: PContext; n: PNode): PNode; @@ -442,13 +457,31 @@ begin n.sons[i] := analyseIfAddressTaken(c, n.sons[i]); end; +function semDirectCallAnalyseEffects(c: PContext; n: PNode): PNode; +var + callee: PSym; +begin + result := semDirectCall(c, n); + if result <> nil then begin + if result.sons[0].kind <> nkSym then + InternalError('semDirectCallAnalyseEffects'); + callee := result.sons[0].sym; + if not (sfNoSideEffect in callee.flags) then + if (sfForward in callee.flags) + or ([sfImportc, sfSideEffect] * callee.flags <> []) then + include(c.p.owner.flags, sfSideEffect); + end +end; + function semIndirectOp(c: PContext; n: PNode): PNode; var m: TCandidate; msg: string; i: int; + prc: PNode; begin result := nil; + prc := n.sons[0]; checkMinSonsLen(n, 1); case n.sons[0].kind of nkDotExpr, nkQualified: begin @@ -457,8 +490,7 @@ begin if n.sons[0].kind = nkDotCall then begin // it is a static call! result := n.sons[0]; result.kind := nkCall; - for i := 1 to sonsLen(n)-1 do - addSon(result, n.sons[i]); + for i := 1 to sonsLen(n)-1 do addSon(result, n.sons[i]); result := semExpr(c, result); exit end @@ -475,8 +507,8 @@ begin if m.state <> csMatch then begin msg := msgKindToString(errTypeMismatch); for i := 1 to sonsLen(n)-1 do begin + if i > 1 then add(msg, ', '); add(msg, typeToString(n.sons[i].typ)); - if i <> sonsLen(n)-1 then add(msg, ', '); end; add(msg, ')' +{&} nl +{&} msgKindToString(errButExpected) +{&} nl +{&} typeToString(n.sons[0].typ)); @@ -485,11 +517,21 @@ begin end else result := m.call; + // we assume that a procedure that calls something indirectly + // has side-effects: + include(c.p.owner.flags, sfSideEffect); end else begin result := overloadedCallOpr(c, n); - if result = nil then result := semDirectCall(c, n); - if result = nil then liMessage(n.info, errExprCannotBeCalled); + // Now that nkSym does not imply an iteration over the proc/iterator space, + // the old ``prc`` (which is likely an nkIdent) has to be restored: + if result = nil then begin + n.sons[0] := prc; + result := semDirectCallAnalyseEffects(c, n); + end; + if result = nil then + liMessage(n.info, errExprXCannotBeCalled, + renderTree(n, {@set}[renderNoComments])); end; fixAbstractType(c, result); analyseIfAddressTakenInCall(c, result); @@ -499,7 +541,7 @@ function semDirectOp(c: PContext; n: PNode): PNode; begin // this seems to be a hotspot in the compiler! semOpAux(c, n); - result := semDirectCall(c, n); + result := semDirectCallAnalyseEffects(c, n); if result = nil then begin result := overloadedCallOpr(c, n); if result = nil then @@ -508,45 +550,6 @@ begin fixAbstractType(c, result); analyseIfAddressTakenInCall(c, result); end; -(* -function semIncSucc(c: PContext; n: PNode; const opr: string): PNode; -// handles Inc, Dec, Succ and Pred -var - a: PNode; - typ: PType; -begin - checkMinSonsLen(n, 2); - n.sons[1] := semExprWithType(c, n.sons[1]); - typ := skipTypes(n.sons[1].Typ, {@set}[tyGenericInst, tyVar]); - if not isOrdinalType(typ) or enumHasWholes(typ) then - liMessage(n.sons[1].Info, errOrdinalTypeExpected); - if sonsLen(n) = 3 then begin - n.sons[2] := semExprWithType(c, n.sons[2]); - a := IndexTypesMatch(c, getSysType(tyInt), n.sons[2].typ, n.sons[2]); - if a = nil then - typeMismatch(n.sons[2], getSysType(tyInt), n.sons[2].typ); - n.sons[2] := a; - end - else if sonsLen(n) = 2 then begin // default value of 1 - a := newIntNode(nkIntLit, 1); - a.info := n.info; - a.typ := getSysType(tyInt); - addSon(n, a) - end - else - liMessage(n.info, errInvalidArgForX, opr); - result := n; -end; - -function semOrd(c: PContext; n: PNode): PNode; -begin - checkSonsLen(n, 2); - n.sons[1] := semExprWithType(c, n.sons[1]); - if not isOrdinalType(skipTypes(n.sons[1].Typ, {@set}[tyGenericInst, tyVar])) then - liMessage(n.Info, errOrdinalTypeExpected); - n.typ := getSysType(tyInt); - result := n -end; *) function semEcho(c: PContext; n: PNode): PNode; var @@ -632,18 +635,6 @@ begin mSizeOf: result := semSizeof(c, setMs(n, s)); mIs: result := semIs(c, setMs(n, s)); mEcho: result := semEcho(c, setMs(n, s)); - (* - mSucc: begin - result := semIncSucc(c, setMs(n, s), 'succ'); - result.typ := n.sons[1].typ; - end; - mPred: begin - result := semIncSucc(c, setMs(n, s), 'pred'); - result.typ := n.sons[1].typ; - end; - mInc: result := semIncSucc(c, setMs(n, s), 'inc'); - ast.mDec: result := semIncSucc(c, setMs(n, s), 'dec'); - mOrd: result := semOrd(c, setMs(n, s)); *) else result := semDirectOp(c, n); end; end; @@ -655,16 +646,14 @@ end; function semSym(c: PContext; n: PNode; s: PSym; flags: TExprFlags): PNode; begin - result := newSymNode(s); - result.info := n.info; - result.typ := s.typ; - include(s.flags, sfUsed); if (s.kind = skType) and not (efAllowType in flags) then liMessage(n.info, errATypeHasNoValue); case s.kind of - skProc, skIterator, skConverter: + skProc, skIterator, skConverter: begin if (s.magic <> mNone) then liMessage(n.info, errInvalidContextForBuiltinX, s.name.s); + result := symChoice(c, n, s); + end; skConst: begin (* Consider:: @@ -678,20 +667,40 @@ begin copy `x`'s AST into each context, so that the type fixup phase can deal with two different ``[]``. *) + include(s.flags, sfUsed); if s.typ.kind in ConstAbstractTypes then begin result := copyTree(s.ast); result.info := n.info; result.typ := s.typ; end + else begin + result := newSymNode(s); + result.info := n.info; + end + end; + skMacro: begin + include(s.flags, sfUsed); + result := semMacroExpr(c, n, s); end; - skMacro: result := semMacroExpr(c, n, s); skTemplate: begin + include(s.flags, sfUsed); // Templates and macros can be invoked without ``()`` pushInfoContext(n.info); result := evalTemplate(c, n, s); popInfoContext(); end; - else begin end + skVar: begin + include(s.flags, sfUsed); + // if a proc accesses a global variable, it is not side effect free + if sfGlobal in s.flags then include(c.p.owner.flags, sfSideEffect); + result := newSymNode(s); + result.info := n.info; + end; + else begin + include(s.flags, sfUsed); + result := newSymNode(s); + result.info := n.info; + end end; checkDeprecated(n, s); end; @@ -1266,6 +1275,7 @@ begin result := semExpr(c, result, flags) end; end; + nkBind: result := semExpr(c, n.sons[0], flags); nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand: begin // check if it is an expression macro: checkMinSonsLen(n, 1); @@ -1326,11 +1336,7 @@ begin end; nkCurly: result := semSetConstr(c, n); nkBracket: result := semArrayConstr(c, n); - nkLambda: result := semLambda(c, n); // handled in semstmts - nkExprColonExpr: begin - internalError(n.info, 'semExpr() to implement'); - // XXX: to implement for array constructors! - end; + nkLambda: result := semLambda(c, n); nkDerefExpr: begin checkSonsLen(n, 1); n.sons[0] := semExprWithType(c, n.sons[0]); @@ -1357,11 +1363,6 @@ begin checkSonsLen(n, 1); result := semExpr(c, n.sons[0]); end; - nkHeaderQuoted: begin - // look up the proc: - internalError(n.info, 'semExpr() to implement'); - // XXX: to implement - end; nkIfExpr: result := semIfExpr(c, n); nkStmtListExpr: result := semStmtListExpr(c, n); nkBlockExpr: result := semBlockExpr(c, n); @@ -1374,6 +1375,11 @@ begin checkSonsLen(n, 3); nkCheckedFieldExpr: checkMinSonsLen(n, 2); + nkSymChoice: begin + liMessage(n.info, errExprXAmbiguous, + renderTree(n, {@set}[renderNoComments])); + result := nil + end else begin //InternalError(n.info, nodeKindToStr[n.kind]); liMessage(n.info, errInvalidExpressionX, diff --git a/nim/semstmts.pas b/nim/semstmts.pas index c8b942df8..686ff775d 100644 --- a/nim/semstmts.pas +++ b/nim/semstmts.pas @@ -257,7 +257,7 @@ begin addSon(result, newIdentNode(getIdent(id.s+'='), n.info)); addSon(result, semExpr(c, a.sons[0])); addSon(result, semExpr(c, n.sons[1])); - result := semDirectCall(c, result); + result := semDirectCallAnalyseEffects(c, result); if result <> nil then begin fixAbstractType(c, result); analyseIfAddressTakenInCall(c, result); @@ -277,7 +277,7 @@ begin addSonIfNotNil(result, semExpr(c, a.sons[1].sons[0])); addSonIfNotNil(result, semExpr(c, a.sons[1].sons[1])); addSon(result, semExpr(c, n.sons[1])); - result := semDirectCall(c, result); + result := semDirectCallAnalyseEffects(c, result); if result <> nil then begin fixAbstractType(c, result); analyseIfAddressTakenInCall(c, result); @@ -289,7 +289,7 @@ begin addSon(result, semExpr(c, a.sons[0])); addSon(result, semExpr(c, a.sons[1])); addSon(result, semExpr(c, n.sons[1])); - result := semDirectCall(c, result); + result := semDirectCallAnalyseEffects(c, result); if result <> nil then begin fixAbstractType(c, result); analyseIfAddressTakenInCall(c, result); @@ -322,7 +322,7 @@ begin result := n; checkSonsLen(n, 1); if not (c.p.owner.kind in [skConverter, skProc, skMacro]) then - liMessage(n.info, errReturnNotAllowedHere); + liMessage(n.info, errXNotAllowedHere, '''return'''); if (n.sons[0] <> nil) then begin n.sons[0] := SemExprWithType(c, n.sons[0]); // check for type compatibility: @@ -624,9 +624,28 @@ begin end end; -function resolveGenericParams(c: PContext; n: PNode): PNode; +function resolveGenericParams(c: PContext; n: PNode; + withinBind: bool = false): PNode; +var + i: int; + s: PSym; begin - result := n; + if n = nil then begin result := nil; exit end; + case n.kind of + nkIdent: begin + if not withinBind then + result := n + else + result := symChoice(c, n, lookup(c, n)) + end; + nkSym..nkNilLit: result := n; + nkBind: result := resolveGenericParams(c, n.sons[0], true); + else begin + result := n; + for i := 0 to sonsLen(n)-1 do + result.sons[i] := resolveGenericParams(c, n.sons[i], withinBind); + end + end end; function SemTypeSection(c: PContext; n: PNode): PNode; @@ -682,7 +701,7 @@ begin addSon(s.typ, nil); // process the type body for symbol lookup of generic params // we can use the same algorithm as for template parameters: - a.sons[2] := resolveTemplateParams(c, a.sons[2]); + a.sons[2] := resolveTemplateParams(c, a.sons[2], false); s.ast := a; if s.typ.containerID <> 0 then InternalError(a.info, 'semTypeSection: containerID'); @@ -754,6 +773,13 @@ begin n.sons[codePos] := newSymNode(b); end; +procedure sideEffectsCheck(c: PContext; s: PSym); +begin + if [sfNoSideEffect, sfSideEffect] * s.flags = + [sfNoSideEffect, sfSideEffect] then + liMessage(s.info, errXhasSideEffects, s.name.s); +end; + function semIterator(c: PContext; n: PNode): PNode; var s: PSym; @@ -972,6 +998,7 @@ begin else if sfBorrow in s.flags then semBorrow(c, n, s); end; + sideEffectsCheck(c, s); closeScope(c.tab); // close scope for parameters popOwner(); c.p := oldP; // restore diff --git a/nim/semtempl.pas b/nim/semtempl.pas index ebc5e1ebb..b8107095f 100644 --- a/nim/semtempl.pas +++ b/nim/semtempl.pas @@ -1,7 +1,7 @@ // // // The Nimrod Compiler -// (c) Copyright 2008 Andreas Rumpf +// (c) Copyright 2009 Andreas Rumpf // // See the file "copying.txt", included in this // distribution, for details about the copyright. @@ -90,7 +90,37 @@ begin dec(evalTemplateCounter); end; -function resolveTemplateParams(c: PContext; n: PNode): PNode; +function symChoice(c: PContext; n: PNode; s: PSym): PNode; +var + a: PSym; + o: TOverloadIter; + i: int; +begin + i := 0; + a := initOverloadIter(o, c, n); + while a <> nil do begin + a := nextOverloadIter(o, c, n); + inc(i); + end; + if i <= 1 then begin + result := newSymNode(s); + result.info := n.info; + include(s.flags, sfUsed); + end + else begin + // semantic checking requires a type; ``fitNode`` deal with it + // appropriately + result := newNodeIT(nkSymChoice, n.info, newTypeS(tyNone, c)); + a := initOverloadIter(o, c, n); + while a <> nil do begin + addSon(result, newSymNode(a)); + a := nextOverloadIter(o, c, n); + end + end +end; + +function resolveTemplateParams(c: PContext; n: PNode; + withinBind: bool): PNode; var i: int; s: PSym; @@ -98,20 +128,27 @@ begin if n = nil then begin result := nil; exit end; case n.kind of nkIdent: begin - s := SymTabLocalGet(c.Tab, n.ident); - if (s <> nil) then begin - result := newSymNode(s); - result.info := n.info + if not withinBind then begin + s := SymTabLocalGet(c.Tab, n.ident); + if (s <> nil) then begin + result := newSymNode(s); + result.info := n.info + end + else + result := n + end + else begin + result := symChoice(c, n, lookup(c, n)) end - else - result := n end; nkSym..nkNilLit: // atom result := n; + nkBind: + result := resolveTemplateParams(c, n.sons[0], true); else begin result := n; for i := 0 to sonsLen(n)-1 do - result.sons[i] := resolveTemplateParams(c, n.sons[i]); + result.sons[i] := resolveTemplateParams(c, n.sons[i], withinBind); end end end; @@ -200,7 +237,7 @@ begin if n.sons[genericParamsPos] <> nil then liMessage(n.info, errNoGenericParamsAllowedForX, 'template'); // resolve parameters: - n.sons[codePos] := resolveTemplateParams(c, n.sons[codePos]); + n.sons[codePos] := resolveTemplateParams(c, n.sons[codePos], false); if params.sons[0].ident.id = ord(wExpr) then n.sons[codePos] := transformToExpr(n.sons[codePos]); diff --git a/nim/sigmatch.pas b/nim/sigmatch.pas index d95745e0c..ccd05d413 100644 --- a/nim/sigmatch.pas +++ b/nim/sigmatch.pas @@ -46,6 +46,21 @@ begin assert(c.callee <> nil); end; +procedure copyCandidate(var a: TCandidate; const b: TCandidate); +begin + a.exactMatches := b.exactMatches; + a.subtypeMatches := b.subtypeMatches; + a.convMatches := b.convMatches; + a.intConvMatches := b.intConvMatches; + a.genericMatches := b.genericMatches; + a.state := b.state; + a.callee := b.callee; + a.calleeSym := b.calleeSym; + a.call := copyTree(b.call); + a.baseTypeMatch := b.baseTypeMatch; + copyIdTable(a.bindings, b.bindings); +end; + function cmpCandidates(const a, b: TCandidate): int; begin result := a.exactMatches - b.exactMatches; @@ -552,8 +567,8 @@ begin end end; -function ParamTypesMatch(c: PContext; var m: TCandidate; f, a: PType; - arg: PNode): PNode; +function ParamTypesMatchAux(c: PContext; var m: TCandidate; f, a: PType; + arg: PNode): PNode; var r: TTypeRelation; begin @@ -608,6 +623,57 @@ begin end end; +function ParamTypesMatch(c: PContext; var m: TCandidate; f, a: PType; + arg: PNode): PNode; +var + i, cmp, best: int; + x, y, z: TCandidate; + r: TTypeRelation; +begin + if (arg = nil) or (arg.kind <> nkSymChoice) then + result := ParamTypesMatchAux(c, m, f, a, arg) + else begin + // CAUTION: The order depends on the used hashing scheme. Thus it is + // incorrect to simply use the first fitting match. However, to implement + // this correctly is inefficient. We have to copy `m` here to be able to + // roll back the side effects of the unification algorithm. + initCandidate(x, m.callee); + initCandidate(y, m.callee); + initCandidate(z, m.callee); + x.calleeSym := m.calleeSym; + y.calleeSym := m.calleeSym; + z.calleeSym := m.calleeSym; + best := -1; + for i := 0 to sonsLen(arg)-1 do begin + copyCandidate(z, m); + r := typeRel(z.bindings, f, arg.sons[i].typ); + if r <> isNone then begin + case x.state of + csEmpty, csNoMatch: begin x := z; best := i; x.state := csMatch; end; + csMatch: begin + cmp := cmpCandidates(x, z); + if cmp < 0 then begin best := i; x := z end // z is better than x + else if cmp = 0 then y := z // z is as good as x + else begin end // z is worse than x + end + end + end + end; + if x.state = csEmpty then + result := nil + else if (y.state = csMatch) and (cmpCandidates(x, y) = 0) then begin + if x.state <> csMatch then InternalError(arg.info, 'x.state is not csMatch'); + // ambiguous: more than one symbol fits + result := nil + end + else begin + // only one valid interpretation found: + include(arg.sons[best].sym.flags, sfUsed); + result := ParamTypesMatchAux(c, m, f, arg.sons[best].typ, arg.sons[best]); + end + end +end; + function IndexTypesMatch(c: PContext; f, a: PType; arg: PNode): PNode; var m: TCandidate; @@ -796,7 +862,7 @@ begin //writeMatches(x); //writeMatches(y); liMessage(n.Info, errGenerated, - format(msgKindToString(errAmbigiousCallXYZ), + format(msgKindToString(errAmbiguousCallXYZ), [getProcHeader(x.calleeSym), getProcHeader(y.calleeSym), x.calleeSym.Name.s])) end diff --git a/nim/strutils.pas b/nim/strutils.pas index 377d3abc6..f34379fcb 100644 --- a/nim/strutils.pas +++ b/nim/strutils.pas @@ -502,18 +502,25 @@ procedure addf(var result: string; const f: string; args: array of string); const PatternChars = ['a'..'z', 'A'..'Z', '0'..'9', '_', #128..#255]; var - i, j, x: int; + i, j, x, num: int; begin i := 1; + num := 0; while i <= length(f) do if f[i] = '$' then begin case f[i+1] of + '#': begin + inc(i, 2); + add(result, args[num]); + inc(num); + end; '$': begin addChar(result, '$'); inc(i, 2); end; '1'..'9': begin - add(result, args[ord(f[i+1]) - ord('0') - 1]); + num := ord(f[i+1]) - ord('0'); + add(result, args[num - 1]); inc(i, 2); end; '{': begin diff --git a/nim/transf.pas b/nim/transf.pas index b1812d52c..3e3b2a611 100644 --- a/nim/transf.pas +++ b/nim/transf.pas @@ -15,6 +15,7 @@ unit transf; // * inlines constants // * performes contant folding // * introduces nkHiddenDeref, nkHiddenSubConv, etc. +// * aggressive compile-time evaluation based on the side-effect analysis interface @@ -22,7 +23,7 @@ interface uses sysutils, nsystem, charsets, strutils, - lists, options, ast, astalgo, trees, treetab, + lists, options, ast, astalgo, trees, treetab, evals, msgs, nos, idents, rnimsyn, types, passes, semfold, magicsys; const @@ -822,7 +823,24 @@ begin end; if sonsLen(result) = 2 then result := result.sons[1]; - end; + end + (* + else if result.sons[0].kind = nkSym then begin + // optimization still too aggressive + op := result.sons[0].sym; + if (op.magic = mNone) and (op.kind = skProc) + and ([sfSideEffect, sfForward, sfNoReturn, sfImportc] * op.flags = []) + then begin + for i := 1 to sonsLen(result)-1 do + if not isConstExpr(result.sons[i]) then exit; + // compile-time evaluation: + a := evalConstExpr(c.module, result); + if (a <> nil) and (a.kind <> nkEmpty) then begin + messageout('evaluated at compile time: ' + rendertree(result)); + result := a + end + end + end *) end; function transform(c: PTransf; n: PNode): PNode; diff --git a/nim/types.pas b/nim/types.pas index b4558fe82..d2aee2413 100644 --- a/nim/types.pas +++ b/nim/types.pas @@ -65,16 +65,6 @@ function equalParams(a, b: PNode): TParamsEquality; function isOrdinalType(t: PType): Boolean; function enumHasWholes(t: PType): Boolean; -(* -function skipRange(t: PType): PType; -function skipGeneric(t: PType): PType; -function skipGenericRange(t: PType): PType; -function skipVar(t: PType): PType; -function skipVarGeneric(t: PType): PType; -function skipVarGenericRange(t: PType): PType; -function skipPtrsGeneric(t: PType): PType; -*) - const abstractPtrs = {@set}[tyVar, tyPtr, tyRef, tyGenericInst, tyAbstract, tyOrdinal]; abstractVar = {@set}[tyVar, tyGenericInst, tyAbstract, tyOrdinal]; diff --git a/nim/wordrecg.pas b/nim/wordrecg.pas index cd31a64e4..1f4513ed5 100644 --- a/nim/wordrecg.pas +++ b/nim/wordrecg.pas @@ -40,10 +40,10 @@ type //cog.out(idents) //]]] wAbstract, wAddr, wAnd, wAs, - wAsm, wBlock, wBreak, wCase, - wCast, wConst, wContinue, wConverter, - wDiscard, wDiv, wElif, wElse, - wEnd, wEnum, wExcept, wException, + wAsm, wBind, wBlock, wBreak, + wCase, wCast, wConst, wContinue, + wConverter, wDiscard, wDiv, wElif, + wElse, wEnd, wEnum, wExcept, wFinally, wFor, wFrom, wGeneric, wIf, wImplies, wImport, wIn, wInclude, wIs, wIsnot, wIterator, @@ -62,7 +62,7 @@ type // pragmas and command line options: wMagic, wTypeCheck, wFinal, wProfiler, wObjChecks, wImportc, wExportc, wAlign, wNodecl, wPure, - wVolatile, wRegister, wNostatic, wHeader, wNosideeffect, wNoreturn, + wVolatile, wRegister, wSideeffect, wHeader, wNosideeffect, wNoreturn, wMerge, wLib, wDynlib, wCompilerproc, wCppmethod, wFatal, wError, wWarning, wHint, wLine, wPush, wPop, wDefine, wUndef, wLinedir, wStacktrace, wLinetrace, wPragma, @@ -114,10 +114,10 @@ const //cog.out(strings) //]]] 'abstract', 'addr', 'and', 'as', - 'asm', 'block', 'break', 'case', - 'cast', 'const', 'continue', 'converter', - 'discard', 'div', 'elif', 'else', - 'end', 'enum', 'except', 'exception', + 'asm', 'bind', 'block', 'break', + 'case', 'cast', 'const', 'continue', + 'converter', 'discard', 'div', 'elif', + 'else', 'end', 'enum', 'except', 'finally', 'for', 'from', 'generic', 'if', 'implies', 'import', 'in', 'include', 'is', 'isnot', 'iterator', @@ -136,7 +136,7 @@ const // pragmas and command line options: 'magic', 'typecheck', 'final', 'profiler', 'objchecks', 'importc', 'exportc', 'align', 'nodecl', 'pure', - 'volatile', 'register', 'nostatic', 'header', 'nosideeffect', 'noreturn', + 'volatile', 'register', 'sideeffect', 'header', 'nosideeffect', 'noreturn', 'merge', 'lib', 'dynlib', 'compilerproc', 'cppmethod', 'fatal', 'error', 'warning', 'hint', 'line', 'push', 'pop', 'define', 'undef', 'linedir', 'stacktrace', 'linetrace', 'pragma', |