diff options
author | Andreas Rumpf <andreasrumpf@noname> | 2009-09-15 23:22:22 +0200 |
---|---|---|
committer | Andreas Rumpf <andreasrumpf@noname> | 2009-09-15 23:22:22 +0200 |
commit | 66a7e3d37c0303997a6b1a3b7ec263dfb8c07748 (patch) | |
tree | 40ae1ab8aeb9086b7310ea73ab8a2ed6b597f88b /nim | |
parent | 300430fbba28b408f7ac86ca46b03d9d50839399 (diff) | |
download | Nim-66a7e3d37c0303997a6b1a3b7ec263dfb8c07748.tar.gz |
added tools and web dirs
Diffstat (limited to 'nim')
-rwxr-xr-x[-rw-r--r--] | nim/ast.pas | 174 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/astalgo.pas | 37 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/bitsets.pas | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/ccgexprs.pas | 49 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/ccgstmts.pas | 80 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/ccgtypes.pas | 4 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/ccgutils.pas | 2 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/cgen.pas | 121 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/charsets.pas | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/commands.pas | 10 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/condsyms.pas | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/config.inc | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/crc.pas | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/depends.pas | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/docgen.pas | 556 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/ecmasgen.pas | 21 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/evals.pas | 6 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/extccomp.pas | 5 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/hashtest.pas | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/highlite.pas | 7 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/idents.pas | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/importer.pas | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/interact.pas | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/lexbase.pas | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/lists.pas | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/llstream.pas | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/llvmdyn.pas | 2 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/llvmstat.pas | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/lookups.pas | 18 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/magicsys.pas | 2 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/main.pas | 6 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/msgs.pas | 789 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/nhashes.pas | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/nimconf.pas | 2 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/nimrod.pas | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/nimsets.pas | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/nmath.pas | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/nos.pas | 4 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/nstrtabs.pas | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/nsystem.pas | 7 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/ntime.pas | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/nversion.pas | 6 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/options.pas | 8 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/osproc.pas | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/parsecfg.pas | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/parseopt.pas | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/paslex.pas | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/pasparse.pas | 4 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/passaux.pas | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/passes.pas | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/platform.pas | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/pnimsyn.pas | 86 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/pragmas.pas | 122 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/procfind.pas | 10 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/ptmplsyn.pas | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/readme.txt | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/rnimsyn.pas | 38 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/rodread.pas | 8 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/rodwrite.pas | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/ropes.pas | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/rst.pas | 15 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/scanner.pas | 33 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/sem.pas | 60 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/semdata.pas | 34 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/semexprs.pas | 254 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/semfold.pas | 2 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/seminst.pas | 369 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/semstmts.pas | 344 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/semtempl.pas | 109 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/semtypes.pas | 180 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/sigmatch.pas | 125 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/strutils.pas | 10 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/syntaxes.pas | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/tigen.pas | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/transf.pas | 47 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/transtmp.pas | 2 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/trees.pas | 13 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/treetab.pas | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/types.pas | 144 | ||||
-rwxr-xr-x[-rw-r--r--] | nim/wordrecg.pas | 31 |
80 files changed, 2195 insertions, 1761 deletions
diff --git a/nim/ast.pas b/nim/ast.pas index 4836a860e..aec165585 100644..100755 --- a/nim/ast.pas +++ b/nim/ast.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. @@ -72,32 +72,31 @@ type nkInt16Lit, nkInt32Lit, nkInt64Lit, nkFloatLit, nkFloat32Lit, nkFloat64Lit, nkStrLit, nkRStrLit, nkTripleStrLit, nkMetaNode, nkNilLit, nkDotCall, - nkCommand, nkCall, nkGenericCall, nkExplicitTypeListCall, - nkExprEqExpr, nkExprColonExpr, nkIdentDefs, nkVarTuple, - nkInfix, nkPrefix, nkPostfix, nkPar, - nkCurly, nkBracket, nkBracketExpr, nkPragmaExpr, - nkRange, nkDotExpr, nkCheckedFieldExpr, nkDerefExpr, - nkIfExpr, nkElifExpr, nkElseExpr, nkLambda, - 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, + nkCommand, nkCall, nkCallStrLit, nkExprEqExpr, + nkExprColonExpr, nkIdentDefs, nkVarTuple, nkInfix, + nkPrefix, nkPostfix, nkPar, nkCurly, + nkBracket, nkBracketExpr, nkPragmaExpr, nkRange, + nkDotExpr, nkCheckedFieldExpr, nkDerefExpr, nkIfExpr, + nkElifExpr, nkElseExpr, nkLambda, nkAccQuoted, + nkTableConstr, nkQualified, nkBind, nkSymChoice, + nkHiddenStdConv, nkHiddenSubConv, nkHiddenCallConv, nkConv, + nkCast, nkAddr, nkHiddenAddr, nkHiddenDeref, + nkObjDownConv, nkObjUpConv, nkChckRangeF, nkChckRange64, + nkChckRange, nkStringToCString, nkCStringToString, nkPassAsOpenArray, + nkAsgn, nkFastAsgn, 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, + nkIncludeStmt, nkCommentStmt, nkStmtListExpr, nkBlockExpr, + nkStmtListType, nkBlockType, nkTypeOfExpr, nkObjectTy, nkTupleTy, nkRecList, nkRecCase, nkRecWhen, - nkRefTy, nkPtrTy, nkVarTy, nkAbstractTy, + nkRefTy, nkPtrTy, nkVarTy, nkDistinctTy, nkProcTy, nkEnumTy, nkEnumFieldDef, nkReturnToken); TNodeKinds = set of TNodeKind; const @@ -107,32 +106,31 @@ const 'nkInt16Lit', 'nkInt32Lit', 'nkInt64Lit', 'nkFloatLit', 'nkFloat32Lit', 'nkFloat64Lit', 'nkStrLit', 'nkRStrLit', 'nkTripleStrLit', 'nkMetaNode', 'nkNilLit', 'nkDotCall', - 'nkCommand', 'nkCall', 'nkGenericCall', 'nkExplicitTypeListCall', - 'nkExprEqExpr', 'nkExprColonExpr', 'nkIdentDefs', 'nkVarTuple', - 'nkInfix', 'nkPrefix', 'nkPostfix', 'nkPar', - 'nkCurly', 'nkBracket', 'nkBracketExpr', 'nkPragmaExpr', - 'nkRange', 'nkDotExpr', 'nkCheckedFieldExpr', 'nkDerefExpr', - 'nkIfExpr', 'nkElifExpr', 'nkElseExpr', 'nkLambda', - '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', + 'nkCommand', 'nkCall', 'nkCallStrLit', 'nkExprEqExpr', + 'nkExprColonExpr', 'nkIdentDefs', 'nkVarTuple', 'nkInfix', + 'nkPrefix', 'nkPostfix', 'nkPar', 'nkCurly', + 'nkBracket', 'nkBracketExpr', 'nkPragmaExpr', 'nkRange', + 'nkDotExpr', 'nkCheckedFieldExpr', 'nkDerefExpr', 'nkIfExpr', + 'nkElifExpr', 'nkElseExpr', 'nkLambda', 'nkAccQuoted', + 'nkTableConstr', 'nkQualified', 'nkBind', 'nkSymChoice', + 'nkHiddenStdConv', 'nkHiddenSubConv', 'nkHiddenCallConv', 'nkConv', + 'nkCast', 'nkAddr', 'nkHiddenAddr', 'nkHiddenDeref', + 'nkObjDownConv', 'nkObjUpConv', 'nkChckRangeF', 'nkChckRange64', + 'nkChckRange', 'nkStringToCString', 'nkCStringToString', 'nkPassAsOpenArray', + 'nkAsgn', 'nkFastAsgn', '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', + 'nkIncludeStmt', 'nkCommentStmt', 'nkStmtListExpr', 'nkBlockExpr', + 'nkStmtListType', 'nkBlockType', 'nkTypeOfExpr', 'nkObjectTy', 'nkTupleTy', 'nkRecList', 'nkRecCase', 'nkRecWhen', - 'nkRefTy', 'nkPtrTy', 'nkVarTy', 'nkAbstractTy', + 'nkRefTy', 'nkPtrTy', 'nkVarTy', 'nkDistinctTy', 'nkProcTy', 'nkEnumTy', 'nkEnumFieldDef', 'nkReturnToken'); type TSymFlag = ( @@ -158,8 +156,9 @@ const type TTypeKind = ( tyNone, tyBool, tyChar, tyEmpty, - tyArrayConstr, tyNil, tyGeneric, tyGenericInst, - tyGenericParam, tyAbstract, tyEnum, tyOrdinal, + tyArrayConstr, tyNil, tyExpr, tyStmt, + tyTypeDesc, tyGenericInvokation, tyGenericBody, tyGenericInst, + tyGenericParam, tyDistinct, tyEnum, tyOrdinal, tyArray, tyObject, tyTuple, tySet, tyRange, tyPtr, tyRef, tyVar, tySequence, tyProc, tyPointer, tyOpenArray, @@ -170,8 +169,9 @@ type const TypeKindToStr: array [TTypeKind] of string = ( 'tyNone', 'tyBool', 'tyChar', 'tyEmpty', - 'tyArrayConstr', 'tyNil', 'tyGeneric', 'tyGenericInst', - 'tyGenericParam', 'tyAbstract', 'tyEnum', 'tyOrdinal', + 'tyArrayConstr', 'tyNil', 'tyExpr', 'tyStmt', + 'tyTypeDesc', 'tyGenericInvokation', 'tyGenericBody', 'tyGenericInst', + 'tyGenericParam', 'tyDistinct', 'tyEnum', 'tyOrdinal', 'tyArray', 'tyObject', 'tyTuple', 'tySet', 'tyRange', 'tyPtr', 'tyRef', 'tyVar', 'tySequence', 'tyProc', 'tyPointer', 'tyOpenArray', @@ -198,16 +198,16 @@ const 'tfEnumHasWholes'); type TSymKind = ( - skUnknownSym, skConditional, skDynLib, skParam, - skTypeParam, skTemp, skType, skConst, + skUnknown, skConditional, skDynLib, skParam, + skGenericParam, skTemp, skType, skConst, skVar, skProc, skIterator, skConverter, skMacro, skTemplate, skField, skEnumField, skForVar, skModule, skLabel, skStub); TSymKinds = set of TSymKind; const SymKindToStr: array [TSymKind] of string = ( - 'skUnknownSym', 'skConditional', 'skDynLib', 'skParam', - 'skTypeParam', 'skTemp', 'skType', 'skConst', + 'skUnknown', 'skConditional', 'skDynLib', 'skParam', + 'skGenericParam', 'skTemp', 'skType', 'skConst', 'skVar', 'skProc', 'skIterator', 'skConverter', 'skMacro', 'skTemplate', 'skField', 'skEnumField', 'skForVar', 'skModule', 'skLabel', 'skStub'); @@ -253,14 +253,15 @@ type mNewString, mArray, mOpenArray, mRange, mSet, mSeq, mOrdinal, mInt, mInt8, mInt16, mInt32, mInt64, mFloat, mFloat32, mFloat64, mBool, mChar, mString, - mCstring, mPointer, mEmptySet, mIntSetBaseType, mNil, mIsMainModule, - mCompileDate, mCompileTime, mNimrodVersion, mNimrodMajor, mNimrodMinor, mNimrodPatch, - mCpuEndian, mHostOS, mHostCPU, mNaN, mInf, mNegInf, - mNLen, mNChild, mNSetChild, mNAdd, mNAddMultiple, mNDel, - mNKind, mNIntVal, mNFloatVal, mNSymbol, mNIdent, mNGetType, - mNStrVal, mNSetIntVal, mNSetFloatVal, mNSetSymbol, mNSetIdent, mNSetType, - mNSetStrVal, mNNewNimNode, mNCopyNimNode, mNCopyNimTree, mStrToIdent, mIdentToStr, - mEqIdent, mNHint, mNWarning, mNError + mCstring, mPointer, mEmptySet, mIntSetBaseType, mNil, mExpr, + mStmt, mTypeDesc, mIsMainModule, mCompileDate, mCompileTime, mNimrodVersion, + mNimrodMajor, mNimrodMinor, mNimrodPatch, mCpuEndian, mHostOS, mHostCPU, + mNaN, mInf, mNegInf, mNLen, mNChild, mNSetChild, + mNAdd, mNAddMultiple, mNDel, mNKind, mNIntVal, mNFloatVal, + mNSymbol, mNIdent, mNGetType, mNStrVal, mNSetIntVal, mNSetFloatVal, + mNSetSymbol, mNSetIdent, mNSetType, mNSetStrVal, mNNewNimNode, mNCopyNimNode, + mNCopyNimTree, mStrToIdent, mIdentToStr, mEqIdent, mNHint, mNWarning, + mNError //[[[end]]] ); @@ -418,7 +419,6 @@ type loc: TLoc; end; - // these are not part of the syntax tree, but nevertherless inherit from TNode TPair = record key, val: PObject; end; @@ -512,19 +512,24 @@ const // "MagicToStr" array: 'NewString', 'Array', 'OpenArray', 'Range', 'Set', 'Seq', 'Ordinal', 'Int', 'Int8', 'Int16', 'Int32', 'Int64', 'Float', 'Float32', 'Float64', 'Bool', 'Char', 'String', - 'Cstring', 'Pointer', 'EmptySet', 'IntSetBaseType', 'Nil', 'IsMainModule', - 'CompileDate', 'CompileTime', 'NimrodVersion', 'NimrodMajor', 'NimrodMinor', 'NimrodPatch', - 'CpuEndian', 'HostOS', 'HostCPU', 'NaN', 'Inf', 'NegInf', - 'NLen', 'NChild', 'NSetChild', 'NAdd', 'NAddMultiple', 'NDel', - 'NKind', 'NIntVal', 'NFloatVal', 'NSymbol', 'NIdent', 'NGetType', - 'NStrVal', 'NSetIntVal', 'NSetFloatVal', 'NSetSymbol', 'NSetIdent', 'NSetType', - 'NSetStrVal', 'NNewNimNode', 'NCopyNimNode', 'NCopyNimTree', 'StrToIdent', 'IdentToStr', - 'EqIdent', 'NHint', 'NWarning', 'NError' + 'Cstring', 'Pointer', 'EmptySet', 'IntSetBaseType', 'Nil', 'Expr', + 'Stmt', 'TypeDesc', 'IsMainModule', 'CompileDate', 'CompileTime', 'NimrodVersion', + 'NimrodMajor', 'NimrodMinor', 'NimrodPatch', 'CpuEndian', 'HostOS', 'HostCPU', + 'NaN', 'Inf', 'NegInf', 'NLen', 'NChild', 'NSetChild', + 'NAdd', 'NAddMultiple', 'NDel', 'NKind', 'NIntVal', 'NFloatVal', + 'NSymbol', 'NIdent', 'NGetType', 'NStrVal', 'NSetIntVal', 'NSetFloatVal', + 'NSetSymbol', 'NSetIdent', 'NSetType', 'NSetStrVal', 'NNewNimNode', 'NCopyNimNode', + 'NCopyNimTree', 'StrToIdent', 'IdentToStr', 'EqIdent', 'NHint', 'NWarning', + 'NError' //[[[end]]] ); const - GenericTypes: TTypeKinds = {@set}[tyGeneric, tyGenericParam]; + GenericTypes: TTypeKinds = {@set}[ + tyGenericInvokation, + tyGenericBody, + tyGenericParam + ]; StructuralEquivTypes: TTypeKinds = {@set}[ tyArrayConstr, tyNil, tyTuple, @@ -669,6 +674,7 @@ type function IntSetContains(const s: TIntSet; key: int): bool; procedure IntSetIncl(var s: TIntSet; key: int); +procedure IntSetExcl(var s: TIntSet; key: int); procedure IntSetInit(var s: TIntSet); function IntSetContainsOrIncl(var s: TIntSet; key: int): bool; @@ -1069,6 +1075,7 @@ begin {@emit if isNil(father.sons) then father.sons := @[]; } {@emit add(father.sons, son); } + assert((father.kind <> tyGenericInvokation) or (son.kind <> tyGenericInst)); end; function sonsLen(n: PNode): int; @@ -1371,6 +1378,19 @@ begin or shlu(1, u and IntMask); end; +procedure IntSetExcl(var s: TIntSet; key: int); +var + u: TBitScalar; + t: PTrunk; +begin + t := IntSetGet(s, shru(key, TrunkShift)); + if t <> nil then begin + u := key and TrunkMask; + t.bits[shru(u, IntShift)] := t.bits[shru(u, IntShift)] + and not shlu(1, u and IntMask); + end +end; + function IntSetContainsOrIncl(var s: TIntSet; key: int): bool; var u: TBitScalar; diff --git a/nim/astalgo.pas b/nim/astalgo.pas index e5475ddd1..7c1f3ec0b 100644..100755 --- a/nim/astalgo.pas +++ b/nim/astalgo.pas @@ -419,6 +419,8 @@ end; function typeToYamlAux(n: PType; var marker: TIntSet; indent: int; maxRecDepth: int): PRope; +var + i: int; begin if n = nil then result := toRope('null') @@ -427,6 +429,18 @@ begin toRope(typeKindToStr[n.kind]), toRope(strutils.toHex({@cast}TAddress(n), sizeof(n)*2))]) else begin + if sonsLen(n) > 0 then begin + result := toRope('['+''); + for i := 0 to sonsLen(n)-1 do begin + if i > 0 then app(result, ','+''); + appf(result, '$n$1$2', + [spaces(indent+4), + typeToYamlAux(n.sons[i], marker, indent + 4, maxRecDepth-1)]); + end; + appf(result, '$n$1]', [spaces(indent+2)]); + end + else + result := toRope('null'); result := ropeConstr(indent, [ toRope('kind'), makeYamlString(typeKindToStr[n.kind]), toRope('sym'), symToYamlAux(n.sym, marker, indent+2, maxRecDepth-1), @@ -434,7 +448,8 @@ begin toRope('flags'), typeFlagsToStr(n.flags), toRope('callconv'), makeYamlString(CallingConvToStr[n.callConv]), toRope('size'), toRope(n.size), - toRope('align'), toRope(n.align) + toRope('align'), toRope(n.align), + toRope('sons'), result ]); end end; @@ -525,14 +540,20 @@ begin result := toRope('null') else begin result := toRope(typeKindToStr[n.kind]); - app(result, '('+''); - for i := 0 to sonsLen(n)-1 do begin - if i > 0 then app(result, ', '); - if n.sons[i] = nil then app(result, 'null') - else app(result, debugType(n.sons[i])); - // app(result, typeKindToStr[n.sons[i].kind]); + if n.sym <> nil then begin + app(result, ' '+''); + app(result, n.sym.name.s); end; - app(result, ')'+''); + if (n.kind <> tyString) and (sonsLen(n) > 0) then begin + app(result, '('+''); + for i := 0 to sonsLen(n)-1 do begin + if i > 0 then app(result, ', '); + if n.sons[i] = nil then app(result, 'null') + else app(result, debugType(n.sons[i])); + // app(result, typeKindToStr[n.sons[i].kind]); + end; + app(result, ')'+''); + end end end; diff --git a/nim/bitsets.pas b/nim/bitsets.pas index 78c6d1f36..78c6d1f36 100644..100755 --- a/nim/bitsets.pas +++ b/nim/bitsets.pas diff --git a/nim/ccgexprs.pas b/nim/ccgexprs.pas index 212017d14..97a24caeb 100644..100755 --- a/nim/ccgexprs.pas +++ b/nim/ccgexprs.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. @@ -213,8 +213,7 @@ end; function rdLoc(const a: TLoc): PRope; // 'read' location (deref if indirect) begin result := a.r; - if lfIndirect in a.flags then - result := ropef('(*$1 /*rdLoc*/)', [result]) + if lfIndirect in a.flags then result := ropef('(*$1)', [result]) end; function addrLoc(const a: TLoc): PRope; @@ -760,7 +759,8 @@ begin f := e.sons[1].sym; field := nil; while ty <> nil do begin - assert(ty.kind in [tyTuple, tyObject]); + if not (ty.kind in [tyTuple, tyObject]) then + InternalError(e.info, 'genRecordField'); field := lookupInRecord(ty.n, f.name); if field <> nil then break; if gCmd <> cmdCompileToCpp then app(r, '.Sup'); @@ -1643,8 +1643,8 @@ begin case op of mIncl: binaryStmtInExcl(p, e, d, '$1[$2/8] |=(1<<($2%8));$n'); mExcl: binaryStmtInExcl(p, e, d, '$1[$2/8] &= ~(1<<($2%8));$n'); - mCard: unaryExprChar(p, e, d, 'countBitsVar', - 'countBitsVar($1, ' + ToString(size) + ')'); + mCard: unaryExprChar(p, e, d, 'cardSet', + 'cardSet($1, ' + ToString(size) + ')'); mLtSet, mLeSet: begin getTemp(p, getSysType(tyInt), i); // our counter initLocExpr(p, e.sons[1], a); @@ -1847,7 +1847,6 @@ end; procedure genMagicExpr(p: BProc; e: PNode; var d: TLoc; op: TMagic); var - a: TLoc; line, filen: PRope; begin case op of @@ -1870,6 +1869,22 @@ begin else binaryExpr(p, e, d, 'addInt', 'addInt($1, $2)') end; + mInc: begin + if not (optOverflowCheck in p.Options) then + binaryStmt(p, e, d, '', '$1 += $2;$n') + else if skipTypes(e.sons[1].typ, abstractVar).kind = tyInt64 then + binaryStmt(p, e, d, 'addInt64', '$1 = addInt64($1, $2);$n') + else + binaryStmt(p, e, d, 'addInt', '$1 = addInt($1, $2);$n') + end; + ast.mDec: begin + if not (optOverflowCheck in p.Options) then + binaryStmt(p, e, d, '', '$1 -= $2;$n') + else if skipTypes(e.sons[1].typ, abstractVar).kind = tyInt64 then + binaryStmt(p, e, d, 'subInt64', '$1 = subInt64($1, $2);$n') + else + binaryStmt(p, e, d, 'subInt', '$1 = subInt($1, $2);$n') + end; mConStrStr: genStrConcat(p, e, d); mAppendStrCh: binaryStmt(p, e, d, 'addChar', '$1 = addChar($1, $2);$n'); mAppendStrStr: genStrAppend(p, e, d); @@ -1907,22 +1922,6 @@ begin mOrd: genOrd(p, e, d); mLengthArray, mHigh, mLengthStr, mLengthSeq, mLengthOpenArray: genArrayLen(p, e, d, op); - mInc: begin - if not (optOverflowCheck in p.Options) then - binaryStmt(p, e, d, '', '$1 += $2;$n') - else if skipTypes(e.sons[1].typ, abstractVar).kind = tyInt64 then - binaryStmt(p, e, d, 'addInt64', '$1 = addInt64($1, $2);$n') - else - binaryStmt(p, e, d, 'addInt', '$1 = addInt($1, $2);$n') - end; - ast.mDec: begin - if not (optOverflowCheck in p.Options) then - binaryStmt(p, e, d, '', '$1 -= $2;$n') - else if skipTypes(e.sons[1].typ, abstractVar).kind = tyInt64 then - binaryStmt(p, e, d, 'subInt64', '$1 = subInt64($1, $2);$n') - else - binaryStmt(p, e, d, 'subInt', '$1 = subInt($1, $2);$n') - end; mGCref: unaryStmt(p, e, d, 'nimGCref', 'nimGCref($1);$n'); mGCunref: unaryStmt(p, e, d, 'nimGCunref', 'nimGCunref($1);$n'); mSetLengthStr: genSetLengthStr(p, e, d); @@ -2203,7 +2202,8 @@ begin nkFloatLit..nkFloat64Lit, nkNilLit, nkCharLit: begin putIntoDest(p, d, e.typ, genLiteral(p, e)); end; - nkCall, nkHiddenCallConv, nkInfix, nkPrefix, nkPostfix, nkCommand: begin + nkCall, nkHiddenCallConv, nkInfix, nkPrefix, nkPostfix, nkCommand, + nkCallStrLit: begin if (e.sons[0].kind = nkSym) and (e.sons[0].sym.magic <> mNone) then genMagicExpr(p, e, d, e.sons[0].sym.magic) @@ -2279,7 +2279,6 @@ end; function genConstExpr(p: BProc; n: PNode): PRope; var - trans: PNode; cs: TBitSet; d: TLoc; begin diff --git a/nim/ccgstmts.pas b/nim/ccgstmts.pas index 90e5c1c77..03d6edb01 100644..100755 --- a/nim/ccgstmts.pas +++ b/nim/ccgstmts.pas @@ -94,31 +94,70 @@ begin end end; -procedure genVarStmt(p: BProc; n: PNode); +procedure genVarTuple(p: BProc; n: PNode); var - i: int; + i, L: int; v: PSym; - a: PNode; + tup, field: TLoc; + t: PType; begin - for i := 0 to sonsLen(n)-1 do begin - a := n.sons[i]; - if a.kind = nkCommentStmt then continue; - assert(a.kind = nkIdentDefs); - assert(a.sons[0].kind = nkSym); - v := a.sons[0].sym; + if n.kind <> nkVarTuple then InternalError(n.info, 'genVarTuple'); + L := sonsLen(n); + genLineDir(p, n); + initLocExpr(p, n.sons[L-1], tup); + t := tup.t; + for i := 0 to L-3 do begin + v := n.sons[i].sym; if sfGlobal in v.flags then assignGlobalVar(p, v) else begin assignLocalVar(p, v); - initVariable(p, v) // XXX: this is not required if a.sons[2] != nil, - // unless it is a GC'ed pointer + initVariable(p, v) end; // generate assignment: - if a.sons[2] <> nil then begin - genLineDir(p, a); - expr(p, a.sons[2], v.loc); + initLoc(field, locExpr, t.sons[i], tup.s); + if t.n = nil then begin + field.r := ropef('$1.Field$2', [rdLoc(tup), toRope(i)]); + end + else begin + if (t.n.sons[i].kind <> nkSym) then + InternalError(n.info, 'genVarTuple'); + field.r := ropef('$1.$2', [rdLoc(tup), + mangleRecFieldName(t.n.sons[i].sym, t)]); end; - genObjectInit(p, v.typ, v.loc, true); // correct position + putLocIntoDest(p, v.loc, field); + genObjectInit(p, v.typ, v.loc, true); + end +end; + +procedure genVarStmt(p: BProc; n: PNode); +var + i: int; + v: PSym; + a: PNode; +begin + for i := 0 to sonsLen(n)-1 do begin + a := n.sons[i]; + if a.kind = nkCommentStmt then continue; + if a.kind = nkIdentDefs then begin + assert(a.sons[0].kind = nkSym); + v := a.sons[0].sym; + if sfGlobal in v.flags then + assignGlobalVar(p, v) + else begin + assignLocalVar(p, v); + initVariable(p, v) // XXX: this is not required if a.sons[2] != nil, + // unless it is a GC'ed pointer + end; + // generate assignment: + if a.sons[2] <> nil then begin + genLineDir(p, a); + expr(p, a.sons[2], v.loc); + end; + genObjectInit(p, v.typ, v.loc, true); // correct position + end + else + genVarTuple(p, a); end end; @@ -294,7 +333,7 @@ begin else begin r := sym.loc.r; if r = nil then begin // if no name has already been given, - // it doesn't matter much: + // it doesn't matter much: r := mangleName(sym); sym.loc.r := r; // but be consequent! end; @@ -561,7 +600,7 @@ procedure genOrdinalCase(p: BProc; t: PNode); // we generate an ordinary if statement and rely on the C compiler // to produce good code. var - canGenerateSwitch: bool; + canGenerateSwitch, hasDefault: bool; i, j, len: int; a: TLoc; v: PNode; @@ -578,6 +617,7 @@ begin if canGenerateSwitch then begin initLocExpr(p, t.sons[0], a); appf(p.s[cpsStmts], 'switch ($1) {$n', [rdCharLoc(a)]); + hasDefault := false; for i := 1 to sonsLen(t)-1 do begin if t.sons[i].kind = nkOfBranch then begin len := sonsLen(t.sons[i]); @@ -604,9 +644,12 @@ begin else begin // else part of case statement: app(p.s[cpsStmts], 'default:' + tnl); genStmts(p, t.sons[i].sons[0]); + hasDefault := true; end; app(p.s[cpsStmts], 'break;' + tnl); end; + if (hasAssume in CC[ccompiler].props) and not hasDefault then + app(p.s[cpsStmts], 'default: __assume(0);' + tnl); app(p.s[cpsStmts], '}' + tnl); end else @@ -902,7 +945,8 @@ begin nkCaseStmt: genCaseStmt(p, t); nkReturnStmt: genReturnStmt(p, t); nkBreakStmt: genBreakStmt(p, t); - nkCall, nkHiddenCallConv, nkInfix, nkPrefix, nkPostfix, nkCommand: begin + nkCall, nkHiddenCallConv, nkInfix, nkPrefix, nkPostfix, nkCommand, + nkCallStrLit: begin genLineDir(p, t); initLocExpr(p, t, a); end; diff --git a/nim/ccgtypes.pas b/nim/ccgtypes.pas index f9b3a36c1..8c17514ff 100644..100755 --- a/nim/ccgtypes.pas +++ b/nim/ccgtypes.pas @@ -116,7 +116,7 @@ begin end; tyOpenArray, tyArrayConstr, tyArray: result := ctArray; tyObject, tyTuple: result := ctStruct; - tyGeneric, tyGenericInst, tyGenericParam, tyAbstract, tyOrdinal: + tyGenericBody, tyGenericInst, tyGenericParam, tyDistinct, tyOrdinal: result := mapType(lastSon(typ)); tyEnum: begin if firstOrd(typ) < 0 then @@ -664,7 +664,7 @@ begin end end end; - tyGenericInst, tyAbstract, tyOrdinal: + tyGenericInst, tyDistinct, tyOrdinal: result := getTypeDescAux(m, lastSon(t), check); else begin InternalError('getTypeDescAux(' + typeKindToStr[t.kind] + ')'); diff --git a/nim/ccgutils.pas b/nim/ccgutils.pas index de5cac13c..da6b8774f 100644..100755 --- a/nim/ccgutils.pas +++ b/nim/ccgutils.pas @@ -56,7 +56,7 @@ begin result := key; end end; - tyGenericInst, tyAbstract, tyOrdinal: + tyGenericInst, tyDistinct, tyOrdinal: result := GetUniqueType(lastSon(key)); tyProc: begin end; else begin diff --git a/nim/cgen.pas b/nim/cgen.pas index fdae6feb6..04c19d444 100644..100755 --- a/nim/cgen.pas +++ b/nim/cgen.pas @@ -463,7 +463,7 @@ begin if (le >= strStart) and (ri > le) then begin prefix := ncopy(s, strStart, le-1); suffix := ncopy(s, ri+1); - temp := splitSeq(ncopy(s, le+1, ri-1), {@set}['|']); + temp := split(ncopy(s, le+1, ri-1), {@set}['|']); for i := 0 to high(temp) do libCandidates(prefix +{&} temp[i] +{&} suffix, dest); end @@ -850,7 +850,7 @@ begin '; Generated by the Nimrod Compiler v$1$n' + '; (c) 2009 Andreas Rumpf$n' + '; Compiled for: $2, $3, $4$n' + - '; Command for C compiler:$n $5$n', + '; Command for LLVM compiler:$n $5$n', [toRope(versionAsString), toRope(platform.OS[targetOS].name), toRope(platform.CPU[targetCPU].name), toRope(extccomp.CC[extccomp.ccompiler].name), @@ -884,84 +884,119 @@ const ' call void systemInit()$n' + '$1' + '$2'; - PosixMain = + PosixNimMain = 'int cmdCount;$n' + 'char** cmdLine;$n' + 'char** gEnv;$n' + + 'N_CDECL(void, NimMain)(void) {$n' + + ' int dummy[8];$n' +{&} + CommonMainBody +{&} + '}$n'; + PosixCMain = 'int main(int argc, char** args, char** env) {$n' + - ' int dummy[8];$n' + ' cmdLine = args;$n' + ' cmdCount = argc;$n' + - ' gEnv = env;$n' +{&} - CommonMainBody +{&} + ' gEnv = env;$n' + + ' NimMain();$n' + ' return 0;$n' + '}$n'; - PosixMainLLVM = + PosixNimMainLLVM = '@cmdCount = linkonce i32$n' + '@cmdLine = linkonce i8**$n' + '@gEnv = linkonce i8**$n' + + 'define void @NimMain(void) {$n' + + ' %dummy = alloca [8 x %NI]$n' +{&} + CommonMainBodyLLVM +{&} + '}$n'; + PosixCMainLLVM = 'define i32 @main(i32 %argc, i8** %args, i8** %env) {$n' + - ' %dummy = alloca [8 x %NI]$n' + ' store i8** %args, i8*** @cmdLine$n' + ' store i32 %argc, i32* @cmdCount$n' + - ' store i8** %env, i8*** @gEnv$n' +{&} - CommonMainBodyLLVM +{&} + ' store i8** %env, i8*** @gEnv$n' + + ' call void @NimMain()$n' + ' ret i32 0$n' + + '}$n'; + WinNimMain = + 'N_CDECL(void, NimMain)(void) {$n' + + ' int dummy[8];$n' +{&} + CommonMainBody +{&} '}$n'; - WinMain = + WinCMain = 'N_STDCALL(int, WinMain)(HINSTANCE hCurInstance, $n' + ' HINSTANCE hPrevInstance, $n' + ' LPSTR lpCmdLine, int nCmdShow) {$n' + - ' int dummy[8];$n' +{&} - CommonMainBody +{&} + ' NimMain();$n' + ' return 0;$n' + '}$n'; - WinMainLLVM = + WinNimMainLLVM = + 'define void @NimMain(void) {$n' + + ' %dummy = alloca [8 x %NI]$n' +{&} + CommonMainBodyLLVM +{&} + '}$n'; + WinCMainLLVM = 'define stdcall i32 @WinMain(i32 %hCurInstance, $n' + ' i32 %hPrevInstance, $n' + ' i8* %lpCmdLine, i32 %nCmdShow) {$n' + - ' %dummy = alloca [8 x %NI]$n' +{&} - CommonMainBodyLLVM +{&} + ' call void @NimMain()$n' + ' ret i32 0$n' + '}$n'; - WinDllMain = + WinNimDllMain = WinNimMain; + WinCDllMain = 'BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fwdreason, $n' + ' LPVOID lpvReserved) {$n' + - ' int dummy[8];$n' +{&} - CommonMainBody +{&} + ' NimMain();$n' + ' return 1;$n' + '}$n'; - WinDllMainLLVM = + WinNimDllMainLLVM = WinNimMainLLVM; + WinCDllMainLLVM = 'define stdcall i32 @DllMain(i32 %hinstDLL, i32 %fwdreason, $n' + ' i8* %lpvReserved) {$n' + - ' %dummy = alloca [8 x %NI]$n' +{&} - CommonMainBodyLLVM +{&} + ' call void @NimMain()$n' + ' ret i32 1$n' + '}$n'; var - frmt: TFormatStr; + nimMain, otherMain: TFormatStr; begin useMagic(m, 'setStackBottom'); if (platform.targetOS = osWindows) and (gGlobalOptions * [optGenGuiApp, optGenDynLib] <> []) then begin - if optGenGuiApp in gGlobalOptions then - if gCmd = cmdCompileToLLVM then frmt := WinMainLLVM else frmt := WinMain - else - if gCmd = cmdCompileToLLVM then - frmt := WinDllMainLLVM - else - frmt := WinDllMain; + if optGenGuiApp in gGlobalOptions then begin + if gCmd = cmdCompileToLLVM then begin + nimMain := WinNimMainLLVM; + otherMain := WinCMainLLVM + end + else begin + nimMain := WinNimMain; + otherMain := WinCMain; + end + end + else begin + if gCmd = cmdCompileToLLVM then begin + nimMain := WinNimDllMainLLVM; + otherMain := WinCDllMainLLVM; + end + else begin + nimMain := WinNimDllMain; + otherMain := WinCDllMain; + end + end; {@discard} lists.IncludeStr(m.headerFiles, '<windows.h>') end - else - if gCmd = cmdCompileToLLVM then - frmt := PosixMainLLVM - else - frmt := PosixMain; - if gBreakpoints <> nil then - useMagic(m, 'dbgRegisterBreakpoint'); + else begin + if gCmd = cmdCompileToLLVM then begin + nimMain := PosixNimMainLLVM; + otherMain := PosixCMainLLVM; + end + else begin + nimMain := PosixNimMain; + otherMain := PosixCMain; + end + end; + if gBreakpoints <> nil then useMagic(m, 'dbgRegisterBreakpoint'); inc(m.labels); - appf(m.s[cfsProcs], frmt, [gBreakpoints, mainModInit, toRope(m.labels)]) + appf(m.s[cfsProcs], nimMain, [gBreakpoints, mainModInit, toRope(m.labels)]); + if not (optNoMain in gGlobalOptions) then + appf(m.s[cfsProcs], otherMain, []); end; function getInitName(m: PSym): PRope; @@ -1101,13 +1136,6 @@ begin //MessageOut('cgen.myOpenCached has been called ' + filename); cfile := changeFileExt(completeCFilePath(filename), cExt); cfilenoext := changeFileExt(cfile, ''); - (* - objFile := toObjFile(cfilenoext); - if ExistsFile(objFile) and nos.FileNewer(objFile, cfile) then begin - end - else begin - addFileToCompile(cfilenoext); // is to compile - end; *) addFileToLink(cfilenoext); registerModuleToMain(module); // XXX: this cannot be right here, initalization has to be appended during @@ -1208,11 +1236,12 @@ begin finishModule(gPendingModules[i]); for i := 0 to high(gPendingModules) do writeModule(gPendingModules[i]); setLength(gPendingModules, 0); - writeMapping(gMapping); end; if not (optDeadCodeElim in gGlobalOptions) and not (sfDeadCodeElim in m.module.flags) then writeModule(m); + if sfMainModule in m.module.flags then + writeMapping(gMapping); end; function cgenPass(): TPass; diff --git a/nim/charsets.pas b/nim/charsets.pas index a5f14450f..a5f14450f 100644..100755 --- a/nim/charsets.pas +++ b/nim/charsets.pas diff --git a/nim/commands.pas b/nim/commands.pas index df6ab9da7..b281552c9 100644..100755 --- a/nim/commands.pas +++ b/nim/commands.pas @@ -63,6 +63,7 @@ const +{&} ' compile_to_c, cc compile project with C code generator' +{&} nl +{&} ' doc generate the documentation for inputfile' +{&} nl +{&} ' rst2html converts a reStructuredText file to HTML' +{&} nl ++{&} ' rst2tex converts a reStructuredText file to TeX' +{&} nl +{&} 'Arguments:' +{&} nl +{&} ' arguments are passed to the program being run (if --run option is selected)' +{&} nl +{&} 'Options:' +{&} nl @@ -112,6 +113,7 @@ const +{&} ' --lib:PATH set the system library path' +{&} nl +{&} ' -c, --compile_only compile only; do not assemble or link' +{&} nl +{&} ' --no_linking compile but do not link' +{&} nl ++{&} ' --no_main do not generate a main procedure' +{&} nl +{&} ' --gen_script generate a compile script (in the ''nimcache''' +{&} nl +{&} ' subdirectory named ''compile_$project$scriptext'')' +{&} nl +{&} ' --os:SYMBOL set the target operating system (cross-compilation)' +{&} nl @@ -360,6 +362,10 @@ begin wNoLinking: begin expectNoArg(switch, arg, pass, info); include(gGlobalOptions, optNoLinking); + end; + wNoMain: begin + expectNoArg(switch, arg, pass, info); + include(gGlobalOptions, optNoMain); end; wForceBuild, wF: begin expectNoArg(switch, arg, pass, info); @@ -555,10 +561,6 @@ begin expectArg(switch, arg, pass, info); setCC(arg) end; - wMaxErr: begin - expectArg(switch, arg, pass, info); - gErrorMax := parseInt(arg); - end; else if strutils.find(switch, '.') >= strStart then options.setConfigVar(switch, arg) else diff --git a/nim/condsyms.pas b/nim/condsyms.pas index 465bc045e..465bc045e 100644..100755 --- a/nim/condsyms.pas +++ b/nim/condsyms.pas diff --git a/nim/config.inc b/nim/config.inc index f73444a71..f73444a71 100644..100755 --- a/nim/config.inc +++ b/nim/config.inc diff --git a/nim/crc.pas b/nim/crc.pas index e14716605..e14716605 100644..100755 --- a/nim/crc.pas +++ b/nim/crc.pas diff --git a/nim/depends.pas b/nim/depends.pas index d8b978142..d8b978142 100644..100755 --- a/nim/depends.pas +++ b/nim/depends.pas diff --git a/nim/docgen.pas b/nim/docgen.pas index a72f64908..39a9069c7 100644..100755 --- a/nim/docgen.pas +++ b/nim/docgen.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. @@ -24,6 +24,7 @@ uses procedure CommandDoc(const filename: string); procedure CommandRst2Html(const filename: string); +procedure CommandRst2TeX(const filename: string); implementation @@ -33,7 +34,7 @@ type refname, header: PRope; end; TSections = array [TSymKind] of PRope; - TMetaEnum = (metaNone, metaTitle, metaSubtitle); + TMetaEnum = (metaNone, metaTitle, metaSubtitle, metaAuthor, metaVersion); TDocumentor = record // contains a module's documentation filename: string; // filename of the source file; without extension basedir: string; // base directory (where to put the documentation) @@ -51,6 +52,9 @@ type end; PDoc = ^TDocumentor; +var + splitter: string = '<wbr />'; + function findIndexNode(n: PRstNode): PRstNode; var i: int; @@ -213,6 +217,8 @@ begin end end; +// -------------------- dispatcher ------------------------------------------- + procedure addXmlChar(var dest: string; c: Char); begin case c of @@ -224,6 +230,43 @@ begin end end; +procedure addRtfChar(var dest: string; c: Char); +begin + case c of + '{': add(dest, '\{'); + '}': add(dest, '\}'); + '\': add(dest, '\\'); + else addChar(dest, c) + end +end; + +procedure addTexChar(var dest: string; c: Char); +begin + case c of + '_': add(dest, '\_'); + '{': add(dest, '\symbol{123}'); + '}': add(dest, '\symbol{125}'); + '[': add(dest, '\symbol{91}'); + ']': add(dest, '\symbol{93}'); + '\': add(dest, '\symbol{92}'); + '$': add(dest, '\$'); + '&': add(dest, '\&'); + '#': add(dest, '\#'); + '%': add(dest, '\%'); + '~': add(dest, '\symbol{126}'); + '@': add(dest, '\symbol{64}'); + '^': add(dest, '\symbol{94}'); + '`': add(dest, '\symbol{96}'); + else addChar(dest, c) + end +end; + +procedure escChar(var dest: string; c: Char); +begin + if gCmd <> cmdRst2Tex then addXmlChar(dest, c) + else addTexChar(dest, c); +end; + function nextSplitPoint(const s: string; start: int): int; begin result := start; @@ -241,9 +284,7 @@ begin dec(result); // last valid index end; -function toXml(const s: string; splitAfter: int = -1): string; -const - splitter = '<wbr />'; +function esc(const s: string; splitAfter: int = -1): string; var i, j, k, partLen: int; begin @@ -257,26 +298,52 @@ begin partLen := 0; add(result, splitter); end; - for i := j to k do addXmlChar(result, s[i]); + for i := j to k do escChar(result, s[i]); inc(partLen, k - j + 1); j := k+1; end; end else begin - for i := strStart to length(s)+strStart-1 do addXmlChar(result, s[i]) + for i := strStart to length(s)+strStart-1 do escChar(result, s[i]) end end; -function renderRstToHtml(d: PDoc; n: PRstNode): PRope; forward; +function disp(const xml, tex: string): string; +begin + if gCmd <> cmdRst2Tex then + result := xml + else + result := tex +end; + +function dispF(const xml, tex: string; const args: array of PRope): PRope; +begin + if gCmd <> cmdRst2Tex then + result := ropef(xml, args) + else + result := ropef(tex, args) +end; + +procedure dispA(var dest: PRope; const xml, tex: string; + const args: array of PRope); +begin + if gCmd <> cmdRst2Tex then + appf(dest, xml, args) + else + appf(dest, tex, args) +end; + +// --------------------------------------------------------------------------- + +function renderRstToOut(d: PDoc; n: PRstNode): PRope; forward; -function renderAux(d: PDoc; n: PRstNode; const outer: string = '$1'; - const inner: string = '$1'): PRope; +function renderAux(d: PDoc; n: PRstNode; const outer: string = '$1'): PRope; var i: int; begin result := nil; for i := 0 to rsonsLen(n)-1 do - appf(result, inner, [renderRstToHtml(d, n.sons[i])]); + app(result, renderRstToOut(d, n.sons[i])); result := ropef(outer, [result]); end; @@ -286,7 +353,8 @@ var begin if d.theIndex = nil then exit; h := newRstNode(rnHyperlink); - a := newRstNode(rnLeaf, d.indexValFilename +{&} '#' +{&} toString(id)); + a := newRstNode(rnLeaf, d.indexValFilename +{&} disp('#'+'', '') + +{&} toString(id)); addSon(h, a); addSon(h, a); a := newRstNode(rnIdx); @@ -299,9 +367,11 @@ var a, h: PRstNode; begin inc(d.id); - result := ropef('<em id="$1">$2</em>', [toRope(d.id), renderAux(d, n)]); + result := dispF('<em id="$1">$2</em>', + '$2\label{$1}', [toRope(d.id), renderAux(d, n)]); h := newRstNode(rnHyperlink); - a := newRstNode(rnLeaf, d.indexValFilename +{&} '#' +{&} toString(d.id)); + a := newRstNode(rnLeaf, d.indexValFilename +{&} disp('#'+'', '') + +{&} toString(d.id)); addSon(h, a); addSon(h, a); setIndexPair(d.theIndex, n, h); @@ -312,10 +382,9 @@ var dummyHasToc: bool; begin if (n.comment <> snil) and startsWith(n.comment, '##') then - result := renderRstToHtml(d, rstParse(n.comment, true, - toFilename(n.info), - toLineNumber(n.info), toColumn(n.info), - dummyHasToc)) + result := renderRstToOut(d, rstParse(n.comment, true, toFilename(n.info), + toLineNumber(n.info), + toColumn(n.info), dummyHasToc)) else result := nil; end; @@ -359,9 +428,11 @@ begin case n.kind of nkPostfix: result := getName(n.sons[1], splitAfter); nkPragmaExpr: result := getName(n.sons[0], splitAfter); - nkSym: result := toXML(n.sym.name.s, splitAfter); - nkIdent: result := toXML(n.ident.s, splitAfter); - nkAccQuoted: result := '`' +{&} getName(n.sons[0], splitAfter) +{&} '`'; + nkSym: result := esc(n.sym.name.s, splitAfter); + nkIdent: result := esc(n.ident.s, splitAfter); + nkAccQuoted: + result := esc('`'+'') +{&} getName(n.sons[0], splitAfter) +{&} + esc('`'+''); else begin internalError(n.info, 'getName()'); result := '' @@ -407,39 +478,47 @@ begin case kind of tkEof: break; tkComment: - appf(result, '<span class="Comment">$1</span>', - [toRope(toXml(literal))]); + dispA(result, '<span class="Comment">$1</span>', + '\spanComment{$1}', + [toRope(esc(literal))]); tokKeywordLow..tokKeywordHigh: - appf(result, '<span class="Keyword">$1</span>', + dispA(result, '<span class="Keyword">$1</span>', + '\spanKeyword{$1}', [toRope(literal)]); tkOpr, tkHat: - appf(result, '<span class="Operator">$1</span>', - [toRope(toXml(literal))]); + dispA(result, '<span class="Operator">$1</span>', + '\spanOperator{$1}', + [toRope(esc(literal))]); tkStrLit..tkTripleStrLit: - appf(result, '<span class="StringLit">$1</span>', - [toRope(toXml(literal))]); + dispA(result, '<span class="StringLit">$1</span>', + '\spanStringLit{$1}', + [toRope(esc(literal))]); tkCharLit: - appf(result, '<span class="CharLit">$1</span>', - [toRope(toXml(literal))]); + dispA(result, '<span class="CharLit">$1</span>', + '\spanCharLit{$1}', + [toRope(esc(literal))]); tkIntLit..tkInt64Lit: - appf(result, '<span class="DecNumber">$1</span>', - [toRope(literal)]); + dispA(result, '<span class="DecNumber">$1</span>', + '\spanDecNumber{$1}', + [toRope(esc(literal))]); tkFloatLit..tkFloat64Lit: - appf(result, '<span class="FloatNumber">$1</span>', - [toRope(literal)]); + dispA(result, '<span class="FloatNumber">$1</span>', + '\spanFloatNumber{$1}', + [toRope(esc(literal))]); tkSymbol: - appf(result, '<span class="Identifier">$1</span>', - [toRope(literal)]); - tkInd, tkSad, tkDed, tkSpaces: - app(result, literal); - //appf(result, '<span class="Whitespace">$1</span>', - // [toRope(literal)]); + dispA(result, '<span class="Identifier">$1</span>', + '\spanIdentifier{$1}', + [toRope(esc(literal))]); + tkInd, tkSad, tkDed, tkSpaces: begin + app(result, literal) + end; tkParLe, tkParRi, tkBracketLe, tkBracketRi, tkCurlyLe, tkCurlyRi, tkBracketDotLe, tkBracketDotRi, tkCurlyDotLe, tkCurlyDotRi, tkParDotLe, tkParDotRi, tkComma, tkSemiColon, tkColon, tkEquals, tkDot, tkDotDot, tkAccent: - appf(result, '<span class="Other">$1</span>', - [toRope(literal)]); + dispA(result, '<span class="Other">$1</span>', + '\spanOther{$1}', + [toRope(esc(literal))]); else InternalError(n.info, 'docgen.genThing(' + toktypeToStr[kind] + ')'); end end; @@ -460,7 +539,7 @@ var begin result := nil; for i := 0 to rsonsLen(n)-1 do - app(result, renderRstToHtml(d, n.sons[i])); + app(result, renderRstToOut(d, n.sons[i])); refname := toRope(rstnodeToRefname(n)); if d.hasToc then begin len := length(d.tocPart); @@ -468,13 +547,17 @@ begin d.tocPart[len].refname := refname; d.tocPart[len].n := n; d.tocPart[len].header := result; - result := ropef('<h$1><a class="toc-backref" id="$2" href="#$2_toc">$3'+ - '</a></h$1>', - [toRope(n.level), d.tocPart[len].refname, result]); + result := dispF( + '<h$1><a class="toc-backref" id="$2" href="#$2_toc">$3</a></h$1>', + '\rsth$4{$3}\label{$2}$n', + [toRope(n.level), d.tocPart[len].refname, result, + toRope(chr(n.level-1+ord('A'))+'')]); end else - result := ropef('<h$1 id="$2">$3</h$1>', - [toRope(n.level), refname, result]); + result := dispF('<h$1 id="$2">$3</h$1>', + '\rsth$4{$3}\label{$2}$n', + [toRope(n.level), refname, result, + toRope(chr(n.level-1+ord('A'))+'')]); end; function renderOverline(d: PDoc; n: PRstNode): PRope; @@ -484,13 +567,15 @@ var begin t := nil; for i := 0 to rsonsLen(n)-1 do - app(t, renderRstToHtml(d, n.sons[i])); + app(t, renderRstToOut(d, n.sons[i])); result := nil; if d.meta[metaTitle] = nil then d.meta[metaTitle] := t else if d.meta[metaSubtitle] = nil then d.meta[metaSubtitle] := t else - result := ropef('<h$1 id="$2"><center>$3</center></h$1>', - [toRope(n.level), toRope(rstnodeToRefname(n)), t]); + result := dispF('<h$1 id="$2"><center>$3</center></h$1>', + '\rstov$4{$3}\label{$2}$n', + [toRope(n.level), toRope(rstnodeToRefname(n)), t, + toRope(chr(n.level-1+ord('A'))+'')]); end; function renderRstToRst(d: PDoc; n: PRstNode): PRope; forward; @@ -645,8 +730,10 @@ end; function renderTocEntry(d: PDoc; const e: TTocEntry): PRope; begin - result := ropef('<li><a class="reference" id="$1_toc" href="#$1">$2' + - '</a></li>$n', [e.refname, e.header]); + result := dispF( + '<li><a class="reference" id="$1_toc" href="#$1">$2</a></li>$n', + '\item\label{$1_toc} $2\ref{$1}$n', + [e.refname, e.header]); end; function renderTocEntries(d: PDoc; var j: int; lvl: int): PRope; @@ -666,7 +753,8 @@ begin break end; if lvl > 1 then - result := ropef('<ul class="simple">$1</ul>', [result]); + result := dispF('<ul class="simple">$1</ul>', + '\begin{enumerate}$1\end{enumerate}', [result]); end; function fieldAux(const s: string): PRope; @@ -676,21 +764,28 @@ end; function renderImage(d: PDoc; n: PRstNode): PRope; var - s: string; + s, scale: string; + options: PRope; begin - result := ropef('<img src="$1"', [toRope(getArgument(n))]); + options := nil; + s := getFieldValue(n, 'scale'); + if s <> '' then dispA(options, ' scale="$1"', ' scale=$1', [fieldAux(scale)]); + s := getFieldValue(n, 'height'); - if s <> '' then appf(result, ' height="$1"', [fieldAux(s)]); + if s <> '' then dispA(options, ' height="$1"', ' height=$1', [fieldAux(s)]); + s := getFieldValue(n, 'width'); - if s <> '' then appf(result, ' width="$1"', [fieldAux(s)]); - s := getFieldValue(n, 'scale'); - if s <> '' then appf(result, ' scale="$1"', [fieldAux(s)]); + if s <> '' then dispA(options, ' width="$1"', ' width=$1', [fieldAux(s)]); + s := getFieldValue(n, 'alt'); - if s <> '' then appf(result, ' alt="$1"', [fieldAux(s)]); + if s <> '' then dispA(options, ' alt="$1"', '', [fieldAux(s)]); s := getFieldValue(n, 'align'); - if s <> '' then appf(result, ' align="$1"', [fieldAux(s)]); - app(result, ' />'); - if rsonsLen(n) >= 3 then app(result, renderRstToHtml(d, n.sons[2])) + if s <> '' then dispA(options, ' align="$1"', '', [fieldAux(s)]); + + if options <> nil then options := dispF('$1', '[$1]', [options]); + result := dispF('<img src="$1"$2 />', + '\includegraphics$2{$1}', [toRope(getArgument(n)), options]); + if rsonsLen(n) >= 3 then app(result, renderRstToOut(d, n.sons[2])) end; function renderCodeBlock(d: PDoc; n: PRstNode): PRope; @@ -709,7 +804,7 @@ begin else lang := getSourceLanguage(langstr); if lang = langNone then begin rawMessage(warnLanguageXNotSupported, langstr); - result := ropef('<pre>$1</pre>', [toRope(m.text)]) + result := toRope(m.text) end else begin initGeneralTokenizer(g, m.text); @@ -717,164 +812,220 @@ begin getNextToken(g, lang); case g.kind of gtEof: break; - gtNone, gtWhitespace: + gtNone, gtWhitespace: begin app(result, ncopy(m.text, g.start+strStart, - g.len+g.start-1+strStart)); + g.len+g.start-1+strStart)) + end else - appf(result, '<span class="$2">$1</span>', - [toRope(toXml(ncopy(m.text, g.start+strStart, - g.len+g.start-1+strStart))), - toRope(tokenClassToStr[g.kind])]); + dispA(result, + '<span class="$2">$1</span>', + '\span$2{$1}', + [toRope(esc(ncopy(m.text, g.start+strStart, + g.len+g.start-1+strStart))), + toRope(tokenClassToStr[g.kind])]); end; end; deinitGeneralTokenizer(g); - if result <> nil then result := ropef('<pre>$1</pre>', [result]); - end + end; + if result <> nil then + result := dispF('<pre>$1</pre>', '\begin{rstpre}$n$1$n\end{rstpre}$n', + [result]) end; function renderContainer(d: PDoc; n: PRstNode): PRope; var arg: PRope; begin - result := renderRstToHtml(d, n.sons[2]); + result := renderRstToOut(d, n.sons[2]); arg := toRope(strip(getArgument(n))); - if arg = nil then result := ropef('<div>$1</div>', [result]) - else result := ropef('<div class="$1">$2</div>', [arg, result]) + if arg = nil then result := dispF('<div>$1</div>', '$1', [result]) + else result := dispF('<div class="$1">$2</div>', '$2', [arg, result]) +end; + +function texColumns(n: PRstNode): string; +var + i: int; +begin + result := ''; + for i := 1 to rsonsLen(n) do add(result, '|X'); +end; + +function renderField(d: PDoc; n: PRstNode): PRope; +var + fieldname: string; + fieldval: PRope; + b: bool; +begin + b := false; + if gCmd = cmdRst2Tex then begin + fieldname := addNodes(n.sons[0]); + fieldval := toRope(esc(strip(addNodes(n.sons[1])))); + if cmpIgnoreStyle(fieldname, 'author') = 0 then begin + if d.meta[metaAuthor] = nil then begin + d.meta[metaAuthor] := fieldval; + b := true + end + end + else if cmpIgnoreStyle(fieldName, 'version') = 0 then begin + if d.meta[metaVersion] = nil then begin + d.meta[metaVersion] := fieldval; + b := true + end + end + end; + if b then result := nil + else result := renderAux(d, n, disp('<tr>$1</tr>$n', '$1')); end; -function renderRstToHtml(d: PDoc; n: PRstNode): PRope; +function renderRstToOut(d: PDoc; n: PRstNode): PRope; var - outer, inner: string; + i: int; begin if n = nil then begin result := nil; exit end; - outer := '$1'; - inner := '$1'; case n.kind of - rnInner: begin end; - rnHeadline: begin - result := renderHeadline(d, n); exit; - end; - rnOverline: begin - result := renderOverline(d, n); - exit; - end; - rnTransition: outer := '<hr />'+nl; - rnParagraph: outer := '<p>$1</p>'+nl; - rnBulletList: outer := '<ul class="simple">$1</ul>'+nl; - rnBulletItem, rnEnumItem: outer := '<li>$1</li>'+nl; - rnEnumList: outer := '<ol class="simple">$1</ol>'+nl; - rnDefList: outer := '<dl class="docutils">$1</dl>'+nl; - rnDefItem: begin end; - rnDefName: outer := '<dt>$1</dt>'+nl; - rnDefBody: outer := '<dd>$1</dd>'+nl; - rnFieldList: - outer := '<table class="docinfo" frame="void" rules="none">' + - '<col class="docinfo-name" />' + - '<col class="docinfo-content" />' + - '<tbody valign="top">$1' + - '</tbody></table>'; - rnField: outer := '<tr>$1</tr>$n'; - rnFieldName: outer := '<th class="docinfo-name">$1:</th>'; - rnFieldBody: outer := '<td>$1</td>'; - rnIndex: begin - result := renderRstToHtml(d, n.sons[2]); - exit + rnInner: result := renderAux(d, n); + rnHeadline: result := renderHeadline(d, n); + rnOverline: result := renderOverline(d, n); + rnTransition: + result := renderAux(d, n, disp('<hr />'+nl, '\hrule'+nl)); + rnParagraph: + result := renderAux(d, n, disp('<p>$1</p>'+nl, '$1$n$n')); + rnBulletList: + result := renderAux(d, n, disp('<ul class="simple">$1</ul>'+nl, + '\begin{itemize}$1\end{itemize}'+nl)); + rnBulletItem, rnEnumItem: + result := renderAux(d, n, disp('<li>$1</li>'+nl, '\item $1'+nl)); + rnEnumList: + result := renderAux(d, n, disp('<ol class="simple">$1</ol>'+nl, + '\begin{enumerate}$1\end{enumerate}'+nl)); + rnDefList: + result := renderAux(d, n, disp('<dl class="docutils">$1</dl>'+nl, + '\begin{description}$1\end{description}'+nl)); + rnDefItem: + result := renderAux(d, n); + rnDefName: + result := renderAux(d, n, disp('<dt>$1</dt>'+nl, '\item[$1] ')); + rnDefBody: + result := renderAux(d, n, disp('<dd>$1</dd>'+nl, '$1'+nl)); + rnFieldList: begin + result := nil; + for i := 0 to rsonsLen(n)-1 do app(result, renderRstToOut(d, n.sons[i])); + if result <> nil then + result := dispf('<table class="docinfo" frame="void" rules="none">' + + '<col class="docinfo-name" />' + + '<col class="docinfo-content" />' + + '<tbody valign="top">$1' + + '</tbody></table>', + '\begin{description}$1\end{description}'+nl, [result]); end; + rnField: result := renderField(d, n); + rnFieldName: + result := renderAux(d, n, disp( + '<th class="docinfo-name">$1:</th>', '\item[$1:]')); + rnFieldBody: + result := renderAux(d, n, disp('<td>$1</td>', ' $1$n')); + rnIndex: + result := renderRstToOut(d, n.sons[2]); rnOptionList: - outer := '<table frame="void">$1</table>'; + result := renderAux(d, n, disp('<table frame="void">$1</table>', + '\begin{description}$n$1\end{description}'+nl)); rnOptionListItem: - outer := '<tr>$1</tr>$n'; - rnOptionGroup: outer := '<th align="left">$1</th>'; - rnDescription: outer := '<td align="left">$1</td>$n'; + result := renderAux(d, n, disp('<tr>$1</tr>$n', '$1')); + rnOptionGroup: + result := renderAux(d, n, disp('<th align="left">$1</th>', '\item[$1]')); + rnDescription: + result := renderAux(d, n, disp('<td align="left">$1</td>$n', ' $1$n')); rnOption, rnOptionString, - rnOptionArgument: InternalError('renderRstToHtml'); + rnOptionArgument: InternalError('renderRstToOut'); - rnLiteralBlock: outer := '<pre>$1</pre>'+nl; - rnQuotedLiteralBlock: InternalError('renderRstToHtml'); + rnLiteralBlock: + result := renderAux(d, n, disp('<pre>$1</pre>$n', + '\begin{rstpre}$n$1$n\end{rstpre}$n')); + rnQuotedLiteralBlock: InternalError('renderRstToOut'); - rnLineBlock: outer := '<p>$1</p>'; - rnLineBlockItem: outer := '$1<br />'; + rnLineBlock: result := renderAux(d, n, disp('<p>$1</p>', '$1$n$n')); + rnLineBlockItem: result := renderAux(d, n, disp('$1<br />', '$1\\$n')); - rnBlockQuote: outer := '<blockquote><p>$1</p></blockquote>$n'; + rnBlockQuote: + result := renderAux(d, n, disp('<blockquote><p>$1</p></blockquote>$n', + '\begin{quote}$1\end{quote}$n')); - rnTable, rnGridTable: - outer := '<table border="1" class="docutils">$1</table>'; - rnTableRow: outer := '<tr>$1</tr>$n'; - rnTableDataCell: outer := '<td>$1</td>'; - rnTableHeaderCell: outer := '<th>$1</th>'; + rnTable, rnGridTable: begin + result := renderAux(d, n, + disp('<table border="1" class="docutils">$1</table>', + '\begin{table}\begin{rsttab}{' +{&} + texColumns(n) +{&} + '|}$n\hline$n$1\end{rsttab}\end{table}')); + end; + rnTableRow: begin + if rsonsLen(n) >= 1 then begin + result := renderRstToOut(d, n.sons[0]); + for i := 1 to rsonsLen(n)-1 do + dispa(result, '$1', ' & $1', [renderRstToOut(d, n.sons[i])]); + result := dispf('<tr>$1</tr>$n', '$1\\$n\hline$n', [result]); + end + else + result := nil; + end; + rnTableDataCell: result := renderAux(d, n, disp('<td>$1</td>', '$1')); + rnTableHeaderCell: + result := renderAux(d, n, disp('<th>$1</th>', '\textbf{$1}')); - rnLabel: InternalError('renderRstToHtml'); // used for footnotes and other - rnFootnote: InternalError('renderRstToHtml'); // a footnote + rnLabel: InternalError('renderRstToOut'); // used for footnotes and other + rnFootnote: InternalError('renderRstToOut'); // a footnote - rnCitation: InternalError('renderRstToHtml'); // similar to footnote - rnRef: begin - result := ropef('<a class="reference external" href="#$2">$1</a>', - [renderAux(d, n), toRope(rstnodeToRefname(n))]); - exit - end; + rnCitation: InternalError('renderRstToOut'); // similar to footnote + rnRef: + result := dispF('<a class="reference external" href="#$2">$1</a>', + '$1\ref{$2}', + [renderAux(d, n), toRope(rstnodeToRefname(n))]); rnStandaloneHyperlink: - outer := '<a class="reference external" href="$1">$1</a>'; - rnHyperlink: begin - result := ropef('<a class="reference external" href="$2">$1</a>', - [renderRstToHtml(d, n.sons[0]), - renderRstToHtml(d, n.sons[1])]); - exit - end; - rnDirArg, rnRaw: begin end; - rnImage, rnFigure: begin - result := renderImage(d, n); - exit - end; - rnCodeBlock: begin - result := renderCodeBlock(d, n); - exit - end; - rnContainer: begin - result := renderContainer(d, n); - exit - end; - rnSubstitutionReferences, rnSubstitutionDef: outer := '|$1|'; - rnDirective: outer := ''; + result := renderAux(d, n, disp( + '<a class="reference external" href="$1">$1</a>', + '\href{$1}{$1}')); + rnHyperlink: + result := dispF('<a class="reference external" href="$2">$1</a>', + '\href{$2}{$1}', + [renderRstToOut(d, n.sons[0]), + renderRstToOut(d, n.sons[1])]); + rnDirArg, rnRaw: result := renderAux(d, n); + rnImage, rnFigure: result := renderImage(d, n); + rnCodeBlock: result := renderCodeBlock(d, n); + rnContainer: result := renderContainer(d, n); + rnSubstitutionReferences, rnSubstitutionDef: + result := renderAux(d, n, disp('|$1|', '|$1|')); + rnDirective: result := renderAux(d, n, ''); // Inline markup: - rnGeneralRole: begin - result := ropef('<span class="$2">$1</span>', - [renderRstToHtml(d, n.sons[0]), - renderRstToHtml(d, n.sons[1])]); - exit - end; - rnSub: outer := '<sub>$1</sub>'; - rnSup: outer := '<sup>$1</sup>'; - rnEmphasis: outer := '<em>$1</em>'; - rnStrongEmphasis: outer := '<strong>$1</strong>'; - rnInterpretedText: outer := '<cite>$1</cite>'; + rnGeneralRole: + result := dispF('<span class="$2">$1</span>', + '\span$2{$1}', + [renderRstToOut(d, n.sons[0]), + renderRstToOut(d, n.sons[1])]); + rnSub: result := renderAux(d, n, disp('<sub>$1</sub>', '\rstsub{$1}')); + rnSup: result := renderAux(d, n, disp('<sup>$1</sup>', '\rstsup{$1}')); + rnEmphasis: result := renderAux(d, n, disp('<em>$1</em>', '\emph{$1}')); + rnStrongEmphasis: + result := renderAux(d, n, disp('<strong>$1</strong>', '\textbf{$1}')); + rnInterpretedText: + result := renderAux(d, n, disp('<cite>$1</cite>', '\emph{$1}')); rnIdx: begin if d.theIndex = nil then - outer := '<em>$1</em>' - else begin - result := renderIndexTerm(d, n); exit - end + result := renderAux(d, n, disp('<em>$1</em>', '\emph{$1}')) + else + result := renderIndexTerm(d, n); end; rnInlineLiteral: - outer := '<tt class="docutils literal"><span class="pre">' - +{&} '$1</span></tt>'; - rnLeaf: begin - result := toRope(toXml(n.text)); - exit - end; - rnContents: begin - d.hasToc := true; - exit; - end; - rnTitle: begin - d.meta[metaTitle] := renderRstToHtml(d, n.sons[0]); - exit - end; - else InternalError('renderRstToHtml'); - end; - result := renderAux(d, n, outer, inner); + result := renderAux(d, n, disp( + '<tt class="docutils literal"><span class="pre">$1</span></tt>', + '\texttt{$1}')); + rnLeaf: result := toRope(esc(n.text)); + rnContents: d.hasToc := true; + rnTitle: d.meta[metaTitle] := renderRstToOut(d, n.sons[0]); + else InternalError('renderRstToOut'); + end end; procedure generateDoc(d: PDoc; n: PNode); @@ -929,7 +1080,7 @@ begin [toRope(ord(kind)), title, toRope(ord(kind)+50), d.toc[kind]]); end; -function genHtmlFile(d: PDoc): PRope; +function genOutFile(d: PDoc): PRope; var code, toc, title, content: PRope; bodyname: string; @@ -947,8 +1098,7 @@ begin end; if toc <> nil then toc := ropeFormatNamedVars(getConfigVar('doc.toc'), ['content'], [toc]); - for i := low(TSymKind) to high(TSymKind) do - app(code, d.section[i]); + for i := low(TSymKind) to high(TSymKind) do app(code, d.section[i]); if d.meta[metaTitle] <> nil then title := d.meta[metaTitle] else @@ -962,9 +1112,10 @@ begin [title, toc, d.modDesc, toRope(getDateStr()), toRope(getClockStr()), code]); if not (optCompileOnly in gGlobalOptions) then code := ropeFormatNamedVars(getConfigVar('doc.file'), - ['title', 'tableofcontents', 'moduledesc', 'date', 'time', 'content'], - [title, toc, d.modDesc, - toRope(getDateStr()), toRope(getClockStr()), content]) + ['title', 'tableofcontents', 'moduledesc', 'date', 'time', + 'content', 'author', 'version'], + [title, toc, d.modDesc, toRope(getDateStr()), toRope(getClockStr()), + content, d.meta[metaAuthor], d.meta[metaVersion]]) else code := content; result := code; @@ -989,11 +1140,11 @@ begin initIndexFile(d); d.hasToc := true; generateDoc(d, ast); - writeRope(genHtmlFile(d), getOutFile(filename, HtmlExt)); + writeRope(genOutFile(d), getOutFile(filename, HtmlExt)); generateIndex(d); end; -procedure CommandRst2Html(const filename: string); +procedure CommandRstAux(const filename, outExt: string); var filen: string; d: PDoc; @@ -1004,10 +1155,21 @@ begin d := newDocumentor(filen); initIndexFile(d); rst := rstParse(readFile(filen), false, filen, 0, 1, d.hasToc); - d.modDesc := renderRstToHtml(d, rst); - code := genHtmlFile(d); - writeRope(code, getOutFile(filename, HtmlExt)); + d.modDesc := renderRstToOut(d, rst); + code := genOutFile(d); + writeRope(code, getOutFile(filename, outExt)); generateIndex(d); end; +procedure CommandRst2Html(const filename: string); +begin + CommandRstAux(filename, HtmlExt); +end; + +procedure CommandRst2TeX(const filename: string); +begin + splitter := '\-'; + CommandRstAux(filename, TexExt); +end; + end. diff --git a/nim/ecmasgen.pas b/nim/ecmasgen.pas index 9ffa550ae..73faa4ddb 100644..100755 --- a/nim/ecmasgen.pas +++ b/nim/ecmasgen.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. @@ -108,10 +108,13 @@ const tyOpenArray, tySet, tyVar, tyRef, tyPtr]; function mapType(typ: PType): TEcmasTypeKind; +var + t: PType; begin - case skipTypes(typ, abstractInst).kind of + t := skipTypes(typ, abstractInst); + case t.kind of tyVar, tyRef, tyPtr: begin - if typ.sons[0].kind in mappedToObject then + if skipTypes(t.sons[0], abstractInst).kind in mappedToObject then result := etyObject else result := etyBaseIndex @@ -120,7 +123,7 @@ begin // treat a tyPointer like a typed pointer to an array of bytes result := etyInt; end; - tyRange, tyAbstract, tyOrdinal: result := mapType(typ.sons[0]); + tyRange, tyDistinct, tyOrdinal: result := mapType(t.sons[0]); tyInt..tyInt64, tyEnum, tyChar: result := etyInt; tyBool: result := etyBool; @@ -133,7 +136,8 @@ begin tyObject, tyArray, tyArrayConstr, tyTuple, tyOpenArray: result := etyObject; tyNil: result := etyNull; - tyGenericInst, tyGenericParam, tyGeneric, tyNone, tyForward, tyEmpty: + tyGenericInst, tyGenericParam, tyGenericBody, tyGenericInvokation, + tyNone, tyForward, tyEmpty, tyExpr, tyStmt, tyTypeDesc: result := etyNone; tyProc: result := etyProc; tyCString: result := etyString; @@ -299,7 +303,7 @@ begin result := ropef('NTI$1', [toRope(t.id)]); if IntSetContainsOrIncl(p.globals.TypeInfoGenerated, t.id) then exit; case t.kind of - tyAbstract: result := genTypeInfo(p, typ.sons[0]); + tyDistinct: result := genTypeInfo(p, typ.sons[0]); tyPointer, tyProc, tyBool, tyChar, tyCString, tyString, tyInt..tyFloat128: begin s := ropef( @@ -889,7 +893,8 @@ const nkFloatLit..nkFloat64Lit, nkCurly, nkPar, nkStringToCString, nkCStringToString, - nkCall, nkCommand, nkHiddenCallConv]; + nkCall, nkCommand, nkHiddenCallConv, + nkCallStrLit]; function needsNoCopy(y: PNode): bool; begin @@ -1772,7 +1777,7 @@ begin end; nkBlockExpr: genBlock(p, n, r); nkIfExpr: genIfExpr(p, n, r); - nkCall, nkHiddenCallConv, nkCommand: begin + nkCall, nkHiddenCallConv, nkCommand, nkCallStrLit: begin if (n.sons[0].kind = nkSym) and (n.sons[0].sym.magic <> mNone) then genMagic(p, n, r) else diff --git a/nim/evals.pas b/nim/evals.pas index d522dfaf0..b88fa3304 100644..100755 --- a/nim/evals.pas +++ b/nim/evals.pas @@ -278,11 +278,13 @@ begin case t.kind of tyBool, tyChar, tyInt..tyInt64: result := newNodeIT(nkIntLit, info, t); tyFloat..tyFloat128: result := newNodeIt(nkFloatLit, info, t); - tyVar, tyPointer, tyPtr, tyRef, tyCString, tySequence, tyString: + tyVar, tyPointer, tyPtr, tyRef, tyCString, tySequence, tyString, tyExpr, + tyStmt, tyTypeDesc: result := newNodeIT(nkNilLit, info, t); tyObject: begin result := newNodeIT(nkPar, info, t); internalError(info, 'init to implement'); + // XXX end; tyArray, tyArrayConstr: begin result := newNodeIT(nkBracket, info, t); @@ -1283,7 +1285,7 @@ begin nkType..pred(nkNilLit): result := copyNode(n); nkNilLit: result := n; // end of atoms - nkCall, nkHiddenCallConv, nkMacroStmt, nkCommand: + nkCall, nkHiddenCallConv, nkMacroStmt, nkCommand, nkCallStrLit: result := evalMagicOrCall(c, n); nkCurly, nkBracket, nkRange: begin a := copyNode(n); diff --git a/nim/extccomp.pas b/nim/extccomp.pas index a3e4ff367..9e7c7e4cc 100644..100755 --- a/nim/extccomp.pas +++ b/nim/extccomp.pas @@ -27,7 +27,8 @@ type TInfoCCProp = ( // properties of the C compiler: hasSwitchRange, // CC allows ranges in switch statements (GNU C extension) hasComputedGoto, // CC has computed goto (GNU C extension) - hasCpp // CC is/contains a C++ compiler + hasCpp, // CC is/contains a C++ compiler + hasAssume // CC has __assume (Visual C extension) ); TInfoCCProps = set of TInfoCCProp; TInfoCC = record{@tuple} @@ -167,7 +168,7 @@ const debug: ' /GZ /Zi '; pic: ''; asmStmtFrmt: '__asm{$n$1$n}$n'; - props: {@set}[hasCpp]; + props: {@set}[hasCpp, hasAssume]; ), ( name: 'tcc'; diff --git a/nim/hashtest.pas b/nim/hashtest.pas index 7e93ca5bf..7e93ca5bf 100644..100755 --- a/nim/hashtest.pas +++ b/nim/hashtest.pas diff --git a/nim/highlite.pas b/nim/highlite.pas index 1867268d3..ec5374663 100644..100755 --- a/nim/highlite.pas +++ b/nim/highlite.pas @@ -134,14 +134,19 @@ end; procedure initGeneralTokenizer(var g: TGeneralTokenizer; const buf: string); +var + pos: int; begin {@ignore} fillChar(g, sizeof(g), 0); {@emit} g.buf := PChar(buf); g.kind := low(TTokenClass); g.start := 0; g.len := 0; - g.pos := 0; g.state := low(TTokenClass); + pos := 0; + // skip initial whitespace: + while g.buf[pos] in [' ', #9..#13] do inc(pos); + g.pos := pos; end; procedure deinitGeneralTokenizer(var g: TGeneralTokenizer); diff --git a/nim/idents.pas b/nim/idents.pas index c1c1755e9..c1c1755e9 100644..100755 --- a/nim/idents.pas +++ b/nim/idents.pas diff --git a/nim/importer.pas b/nim/importer.pas index fdb72fd4b..fdb72fd4b 100644..100755 --- a/nim/importer.pas +++ b/nim/importer.pas diff --git a/nim/interact.pas b/nim/interact.pas index aab3c7fc2..aab3c7fc2 100644..100755 --- a/nim/interact.pas +++ b/nim/interact.pas diff --git a/nim/lexbase.pas b/nim/lexbase.pas index 2b056c04f..2b056c04f 100644..100755 --- a/nim/lexbase.pas +++ b/nim/lexbase.pas diff --git a/nim/lists.pas b/nim/lists.pas index e3442eb29..e3442eb29 100644..100755 --- a/nim/lists.pas +++ b/nim/lists.pas diff --git a/nim/llstream.pas b/nim/llstream.pas index df4c823a6..df4c823a6 100644..100755 --- a/nim/llstream.pas +++ b/nim/llstream.pas diff --git a/nim/llvmdyn.pas b/nim/llvmdyn.pas index 34839a1c8..e039939e5 100644..100755 --- a/nim/llvmdyn.pas +++ b/nim/llvmdyn.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. diff --git a/nim/llvmstat.pas b/nim/llvmstat.pas index e7d06a284..e7d06a284 100644..100755 --- a/nim/llvmstat.pas +++ b/nim/llvmstat.pas diff --git a/nim/lookups.pas b/nim/lookups.pas index d106ef302..5caceaf46 100644..100755 --- a/nim/lookups.pas +++ b/nim/lookups.pas @@ -72,7 +72,7 @@ begin liMessage(s.info, errImplOfXexpected, getSymRepr(s)) else if ([sfUsed, sfInInterface] * s.flags = []) and (optHints in s.options) then // BUGFIX: check options in s! - if not (s.kind in [skForVar, skParam]) then + if not (s.kind in [skForVar, skParam, skUnknown]) then liMessage(s.info, hintXDeclaredButNotUsed, getSymRepr(s)); s := NextIter(it, tab.stack[tab.tos-1]); end; @@ -103,7 +103,7 @@ begin if not (fn.kind in OverloadableSyms) then InternalError(fn.info, 'addOverloadableSymAt'); check := StrTableGet(c.tab.stack[at], fn.name); - if (check <> nil) and (check.Kind <> fn.kind) then + if (check <> nil) and not (check.Kind in OverloadableSyms) then liMessage(fn.info, errAttemptToRedefine, fn.Name.s); SymTabAddAt(c.tab, fn, at); end; @@ -136,17 +136,16 @@ function lookUp(c: PContext; n: PNode): PSym; begin case n.kind of nkAccQuoted: result := lookup(c, n.sons[0]); - nkSym: begin + nkSym: begin (* result := SymtabGet(c.Tab, n.sym.name); if result = nil then - liMessage(n.info, errUndeclaredIdentifier, n.sym.name.s); - //include(result.flags, sfUsed); + liMessage(n.info, errUndeclaredIdentifier, n.sym.name.s); *) + result := n.sym; end; nkIdent: begin result := SymtabGet(c.Tab, n.ident); if result = nil then liMessage(n.info, errUndeclaredIdentifier, n.ident.s); - //include(result.flags, sfUsed); end else InternalError(n.info, 'lookUp'); end; @@ -169,12 +168,13 @@ begin and IntSetContains(c.AmbiguousSymbols, result.id) then liMessage(n.info, errUseQualifier, n.ident.s) end; - nkSym: begin + nkSym: begin (* result := SymtabGet(c.Tab, n.sym.name); if result = nil then liMessage(n.info, errUndeclaredIdentifier, n.sym.name.s) - else if ambiguousCheck - and IntSetContains(c.AmbiguousSymbols, result.id) then + else *) + result := n.sym; + if ambiguousCheck and IntSetContains(c.AmbiguousSymbols, result.id) then liMessage(n.info, errUseQualifier, n.sym.name.s) end; nkDotExpr, nkQualified: begin diff --git a/nim/magicsys.pas b/nim/magicsys.pas index db801d5f2..d9dde8871 100644..100755 --- a/nim/magicsys.pas +++ b/nim/magicsys.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. diff --git a/nim/main.pas b/nim/main.pas index b1c58c2b9..1bb2ce586 100644..100755 --- a/nim/main.pas +++ b/nim/main.pas @@ -375,6 +375,12 @@ begin wantFile(filename); CommandRst2Html(filename); end; + wRst2tex: begin + gCmd := cmdRst2tex; + LoadSpecialConfig(DocTexConfig); + wantFile(filename); + CommandRst2TeX(filename); + end; wPas: begin gCmd := cmdPas; wantFile(filename); diff --git a/nim/msgs.pas b/nim/msgs.pas index 0f47695af..9d421a5bf 100644..100755 --- a/nim/msgs.pas +++ b/nim/msgs.pas @@ -1,54 +1,54 @@ -// -// -// The Nimrod Compiler -// (c) Copyright 2009 Andreas Rumpf -// -// See the file "copying.txt", included in this -// distribution, for details about the copyright. -// -unit msgs; - -interface - -{$include 'config.inc'} - -uses - nsystem, options, strutils, nos; - -//[[[cog -//from string import replace -//enum = "type\n TMsgKind = (\n" -//msgs = "const\n MsgKindToStr: array [TMsgKind] of string = (\n" -//warns = "const\n WarningsToStr: array [0..%d] of string = (\n" -//hints = "const\n HintsToStr: array [0..%d] of string = (\n" -//w = 0 # counts the warnings -//h = 0 # counts the hints -// -//for elem in eval(open('data/messages.yml').read()): -// for key, val in elem.items(): -// enum = enum + ' %s,\n' % key -// v = replace(val, "'", "''") -// if key[0:4] == 'warn': -// msgs = msgs + " '%s [%s]',\n" % (v, key[4:]) -// warns = warns + " '%s',\n" % key[4:] -// w = w + 1 -// elif key[0:4] == 'hint': -// msgs = msgs + " '%s [%s]',\n" % (v, key[4:]) -// hints = hints + " '%s',\n" % key[4:] -// h = h + 1 -// else: -// msgs = msgs + " '%s',\n" % v -// -//enum = enum[:-2] + ');\n\n' -//msgs = msgs[:-2] + '\n );\n' -//warns = (warns[:-2] + '\n );\n') % (w-1) -//hints = (hints[:-2] + '\n );\n') % (h-1) -// -//cog.out(enum) -//cog.out(msgs) -//cog.out(warns) -//cog.out(hints) -//]]] +// +// +// The Nimrod Compiler +// (c) Copyright 2009 Andreas Rumpf +// +// See the file "copying.txt", included in this +// distribution, for details about the copyright. +// +unit msgs; + +interface + +{$include 'config.inc'} + +uses + nsystem, options, strutils, nos; + +//[[[cog +//from string import replace +//enum = "type\n TMsgKind = (\n" +//msgs = "const\n MsgKindToStr: array [TMsgKind] of string = (\n" +//warns = "const\n WarningsToStr: array [0..%d] of string = (\n" +//hints = "const\n HintsToStr: array [0..%d] of string = (\n" +//w = 0 # counts the warnings +//h = 0 # counts the hints +// +//for elem in eval(open('data/messages.yml').read()): +// for key, val in elem.items(): +// enum = enum + ' %s,\n' % key +// v = replace(val, "'", "''") +// if key[0:4] == 'warn': +// msgs = msgs + " '%s [%s]',\n" % (v, key[4:]) +// warns = warns + " '%s',\n" % key[4:] +// w = w + 1 +// elif key[0:4] == 'hint': +// msgs = msgs + " '%s [%s]',\n" % (v, key[4:]) +// hints = hints + " '%s',\n" % key[4:] +// h = h + 1 +// else: +// msgs = msgs + " '%s',\n" % v +// +//enum = enum[:-2] + ');\n\n' +//msgs = msgs[:-2] + '\n );\n' +//warns = (warns[:-2] + '\n );\n') % (w-1) +//hints = (hints[:-2] + '\n );\n') % (h-1) +// +//cog.out(enum) +//cog.out(msgs) +//cog.out(warns) +//cog.out(hints) +//]]] type TMsgKind = ( errUnknown, @@ -74,13 +74,12 @@ type errOperatorExpected, errTokenExpected, errStringAfterIncludeExpected, - errRecursiveInclude, + errRecursiveDependencyX, errOnOrOffExpected, errNoneSpeedOrSizeExpected, errInvalidPragma, errUnknownPragma, - errUnknownDirective, - errInvalidDirective, + errInvalidDirectiveX, errAtPopWithoutPush, errEmptyAsm, errInvalidIndentation, @@ -128,8 +127,6 @@ type errOverOrUnderflow, errCannotEvalXBecauseIncompletelyDefined, errChrExpectsRange0_255, - errStaticAssertFailed, - errStaticAssertCannotBeEval, errDotRequiresRecordOrObjectType, errUndeclaredFieldX, errNilAccess, @@ -184,7 +181,7 @@ type errButExpected, errButExpectedX, errAmbiguousCallXYZ, - errWrongNumberOfTypeParams, + errWrongNumberOfArguments, errInlineProcHasNoAddress, errXCannotBeInParamDecl, errPragmaOnlyInHeaderOfProc, @@ -230,11 +227,9 @@ type errInitHereNotAllowed, errXCannotBeAssignedTo, errIteratorNotAllowed, - errIteratorNeedsImplementation, - errIteratorNeedsReturnType, + errXNeedsReturnType, errInvalidCommandX, errXOnlyAtModuleScope, - errTypeXNeedsImplementation, errTemplateInstantiationTooNested, errInstantiationFrom, errInvalidIndexValueForTuple, @@ -257,12 +252,12 @@ type errInvalidConversionFromTypeX, errAssertionFailed, errCannotGenerateCodeForX, - errXNeedsReturnType, errXRequiresOneArgument, errUnhandledExceptionX, errCyclicTree, errXisNoMacroOrTemplate, errXhasSideEffects, + errIteratorExpected, errUser, warnCannotOpenFile, warnOctalEscape, @@ -317,15 +312,14 @@ const 'operator expected, but found ''$1''', '''$1'' expected', 'string after ''include'' expected', - 'recursive include file: ''$1''', + 'recursive dependency: ''$1''', '''on'' or ''off'' expected', '''none'', ''speed'' or ''size'' expected', 'invalid pragma', 'unknown pragma: ''$1''', - 'unknown directive: ''$1''', - 'invalid directive', + 'invalid directive: ''$1''', '''pop'' without a ''push'' pragma', - 'empty asm statement makes no sense', + 'empty asm statement', 'invalid indentation', 'exception expected', 'exception already handled', @@ -371,8 +365,6 @@ const 'over- or underflow', 'cannot evalutate ''$1'' because type is not defined completely', '''chr'' expects an int in the range 0..255', - '''staticAssert'' failed: condition is false', - 'argument to ''staticAssert'' cannot be evaluated at compile time', '''.'' requires a record or object type', 'undeclared field: ''$1''', 'attempt to access a nil address', @@ -427,7 +419,7 @@ const 'but expected one of: ', 'but expected ''$1''', 'ambiguous call; both $1 and $2 match for: $3', - 'wrong number of type parameters', + 'wrong number of arguments', 'an inline proc has no address', '$1 cannot be declared in parameter declaration', 'pragmas are only in the header of a proc allowed', @@ -469,15 +461,13 @@ const 'named expression not allowed here', '''$1'' expects one type parameter', 'array expects two type parameters', - 'invalid invisibility: ''$1''', + 'invalid visibility: ''$1''', 'initialization not allowed here', '''$1'' cannot be assigned to', 'iterators can only be defined at the module''s top level', - 'iterator needs an implementation', - 'iterator needs a return type', + '$1 needs a return type', 'invalid command: ''$1''', '''$1'' is only allowed at top level', - 'type ''$1'' needs an implementation', 'template instantiation too nested', 'instantiation from here', 'invalid index value for tuple subscript', @@ -500,12 +490,12 @@ const 'invalid conversion from type ''$1''', 'assertion failed', 'cannot generate code for ''$1''', - 'converter needs return type', - 'converter requires one parameter', + '$1 requires one parameter', 'unhandled exception: $1', 'macro returned a cyclic abstract syntax tree', '''$1'' is no macro or template', '''$1'' can have side effects', + 'iterator within for loop context expected', '$1', 'cannot open ''$1'' [CannotOpenFile]', 'octal escape sequences do not exist; leading zero is ignored [OctalEscape]', @@ -568,322 +558,335 @@ const 'Conf', 'User' ); -//[[[end]]] - -const - fatalMin = errUnknown; - fatalMax = errInternal; - errMin = errUnknown; - errMax = errUser; - warnMin = warnCannotOpenFile; - warnMax = pred(hintSuccess); - hintMin = hintSuccess; - hintMax = high(TMsgKind); - -type - TNoteKind = warnMin..hintMax; - // "notes" are warnings or hints - TNoteKinds = set of TNoteKind; - - TLineInfo = record - // This is designed to be as small as possible, because it is used - // in syntax nodes. We safe space here by using two int16 and an int32 - // on 64 bit and on 32 bit systems this is only 8 bytes. - line, col: int16; - fileIndex: int32; - end; - -function UnknownLineInfo(): TLineInfo; - -var - gNotes: TNoteKinds = [low(TNoteKind)..high(TNoteKind)]; - gErrorCounter: int = 0; // counts the number of errors - gHintCounter: int = 0; - gWarnCounter: int = 0; - gErrorMax: int = 1; // stop after gErrorMax errors - -const // this format is understood by many text editors: it is the same that - // Borland and Freepascal use - PosErrorFormat = '$1($2, $3) Error: $4'; - PosWarningFormat = '$1($2, $3) Warning: $4'; - PosHintFormat = '$1($2, $3) Hint: $4'; - - RawErrorFormat = 'Error: $1'; - RawWarningFormat = 'Warning: $1'; - RawHintFormat = 'Hint: $1'; - -procedure MessageOut(const s: string); - -procedure rawMessage(const msg: TMsgKind; const arg: string = ''); overload; -procedure rawMessage(const msg: TMsgKind; const args: array of string); overload; - -procedure liMessage(const info: TLineInfo; const msg: TMsgKind; - const arg: string = ''); - -procedure InternalError(const info: TLineInfo; const errMsg: string); - overload; -procedure InternalError(const errMsg: string); overload; - -function newLineInfo(const filename: string; line, col: int): TLineInfo; - -function ToFilename(const info: TLineInfo): string; -function toColumn(const info: TLineInfo): int; -function ToLinenumber(const info: TLineInfo): int; - -function MsgKindToString(kind: TMsgKind): string; - -// checkpoints are used for debugging: -function checkpoint(const info: TLineInfo; const filename: string; - line: int): boolean; - -procedure addCheckpoint(const info: TLineInfo); overload; -procedure addCheckpoint(const filename: string; line: int); overload; -function inCheckpoint(const current: TLineInfo): boolean; -// prints the line information if in checkpoint - -procedure pushInfoContext(const info: TLineInfo); -procedure popInfoContext; - -implementation - -function UnknownLineInfo(): TLineInfo; -begin - result.line := int16(-1); - result.col := int16(-1); - result.fileIndex := -1; -end; - -{@ignore} -var - filenames: array of string; - msgContext: array of TLineInfo; -{@emit -var - filenames: array of string = @[]; - msgContext: array of TLineInfo = @[]; -} - -procedure pushInfoContext(const info: TLineInfo); -var - len: int; -begin - len := length(msgContext); - setLength(msgContext, len+1); - msgContext[len] := info; -end; - -procedure popInfoContext; -begin - setLength(msgContext, length(msgContext)-1); -end; - -function includeFilename(const f: string): int; -var - i: int; -begin - for i := high(filenames) downto low(filenames) do - if filenames[i] = f then begin - result := i; exit - end; - // not found, so add it: - result := length(filenames); - setLength(filenames, result+1); - filenames[result] := f; -end; - -function checkpoint(const info: TLineInfo; const filename: string; - line: int): boolean; -begin - result := (int(info.line) = line) and ( - ChangeFileExt(extractFilename(filenames[info.fileIndex]), '') = filename); -end; - - -{@ignore} -var - checkPoints: array of TLineInfo; -{@emit -var - checkPoints: array of TLineInfo = @[]; -} - -procedure addCheckpoint(const info: TLineInfo); overload; -var - len: int; -begin - len := length(checkPoints); - setLength(checkPoints, len+1); - checkPoints[len] := info; -end; - -procedure addCheckpoint(const filename: string; line: int); overload; -begin - addCheckpoint(newLineInfo(filename, line, -1)); -end; - -function newLineInfo(const filename: string; line, col: int): TLineInfo; -begin - result.fileIndex := includeFilename(filename); - result.line := int16(line); - result.col := int16(col); -end; - -function ToFilename(const info: TLineInfo): string; -begin - if info.fileIndex = -1 then result := '???' - else result := filenames[info.fileIndex] -end; - -function ToLinenumber(const info: TLineInfo): int; -begin - result := info.line -end; - -function toColumn(const info: TLineInfo): int; -begin - result := info.col -end; - -procedure MessageOut(const s: string); -begin // change only this proc to put it elsewhere - Writeln(output, s); -end; - -function coordToStr(const coord: int): string; -begin - if coord = -1 then result := '???' - else result := toString(coord) -end; - -function MsgKindToString(kind: TMsgKind): string; -begin // later versions may provide translated error messages - result := msgKindToStr[kind]; -end; - -function getMessageStr(msg: TMsgKind; const arg: string): string; -begin - result := format(msgKindToString(msg), [arg]); -end; - -function inCheckpoint(const current: TLineInfo): boolean; -var - i: int; -begin - result := false; - if not (optCheckpoints in gOptions) then exit; // ignore all checkpoints - for i := 0 to high(checkPoints) do begin - if (current.line = checkPoints[i].line) and - (current.fileIndex = (checkPoints[i].fileIndex)) then begin - MessageOut(Format('$1($2, $3) Checkpoint: ', [toFilename(current), - coordToStr(current.line), - coordToStr(current.col)])); - result := true; - exit - end - end -end; - -procedure handleError(const msg: TMsgKind); -begin - if msg = errInternal then assert(false); // we want a stack trace here - if (msg >= fatalMin) and (msg <= fatalMax) then begin - if gVerbosity >= 3 then assert(false); - halt(1) - end; - if (msg >= errMin) and (msg <= errMax) then begin - inc(gErrorCounter); - if gErrorCounter >= gErrorMax then begin - if gVerbosity >= 3 then assert(false); - halt(1) // one error stops the compiler - end - end -end; - -procedure writeContext; -var - i: int; -begin - for i := 0 to length(msgContext)-1 do begin - MessageOut(Format(posErrorFormat, [toFilename(msgContext[i]), - coordToStr(msgContext[i].line), - coordToStr(msgContext[i].col), - getMessageStr(errInstantiationFrom, '')])); - end; -end; - -procedure rawMessage(const msg: TMsgKind; const args: array of string); -var - frmt: string; -begin - case msg of - errMin..errMax: begin - writeContext(); - frmt := rawErrorFormat; - end; - warnMin..warnMax: begin - if not (optWarns in gOptions) then exit; - if not (msg in gNotes) then exit; - frmt := rawWarningFormat; - inc(gWarnCounter); - end; - hintMin..hintMax: begin - if not (optHints in gOptions) then exit; - if not (msg in gNotes) then exit; - frmt := rawHintFormat; - inc(gHintCounter); - end; - else assert(false) // cannot happen - end; - MessageOut(Format(frmt, format(msgKindToString(msg), args))); - handleError(msg); -end; - -procedure rawMessage(const msg: TMsgKind; const arg: string = ''); -begin - rawMessage(msg, [arg]); -end; - -procedure liMessage(const info: TLineInfo; const msg: TMsgKind; - const arg: string = ''); -var - frmt: string; -begin - case msg of - errMin..errMax: begin - writeContext(); - frmt := posErrorFormat; - end; - warnMin..warnMax: begin - if not (optWarns in gOptions) then exit; - if not (msg in gNotes) then exit; - frmt := posWarningFormat; - inc(gWarnCounter); - end; - hintMin..hintMax: begin - if not (optHints in gOptions) then exit; - if not (msg in gNotes) then exit; - frmt := posHintFormat; - inc(gHintCounter); - end; - else assert(false) // cannot happen - end; - MessageOut(Format(frmt, [toFilename(info), - coordToStr(info.line), - coordToStr(info.col), - getMessageStr(msg, arg)])); - handleError(msg); -end; - -procedure InternalError(const info: TLineInfo; const errMsg: string); -begin - writeContext(); - liMessage(info, errInternal, errMsg); -end; - -procedure InternalError(const errMsg: string); overload; -begin - writeContext(); - rawMessage(errInternal, errMsg); -end; - -end. +//[[[end]]] + +const + fatalMin = errUnknown; + fatalMax = errInternal; + errMin = errUnknown; + errMax = errUser; + warnMin = warnCannotOpenFile; + warnMax = pred(hintSuccess); + hintMin = hintSuccess; + hintMax = high(TMsgKind); + +type + TNoteKind = warnMin..hintMax; + // "notes" are warnings or hints + TNoteKinds = set of TNoteKind; + + TLineInfo = record + // This is designed to be as small as possible, because it is used + // in syntax nodes. We safe space here by using two int16 and an int32 + // on 64 bit and on 32 bit systems this is only 8 bytes. + line, col: int16; + fileIndex: int32; + end; + +function UnknownLineInfo(): TLineInfo; + +var + gNotes: TNoteKinds = [low(TNoteKind)..high(TNoteKind)]; + gErrorCounter: int = 0; // counts the number of errors + gHintCounter: int = 0; + gWarnCounter: int = 0; + gErrorMax: int = 1; // stop after gErrorMax errors + +const // this format is understood by many text editors: it is the same that + // Borland and Freepascal use + PosErrorFormat = '$1($2, $3) Error: $4'; + PosWarningFormat = '$1($2, $3) Warning: $4'; + PosHintFormat = '$1($2, $3) Hint: $4'; + + RawErrorFormat = 'Error: $1'; + RawWarningFormat = 'Warning: $1'; + RawHintFormat = 'Hint: $1'; + +procedure MessageOut(const s: string); + +procedure rawMessage(const msg: TMsgKind; const arg: string = ''); overload; +procedure rawMessage(const msg: TMsgKind; const args: array of string); overload; + +procedure liMessage(const info: TLineInfo; const msg: TMsgKind; + const arg: string = ''); + +procedure InternalError(const info: TLineInfo; const errMsg: string); + overload; +procedure InternalError(const errMsg: string); overload; + +function newLineInfo(const filename: string; line, col: int): TLineInfo; + +function ToFilename(const info: TLineInfo): string; +function toColumn(const info: TLineInfo): int; +function ToLinenumber(const info: TLineInfo): int; + +function MsgKindToString(kind: TMsgKind): string; + +// checkpoints are used for debugging: +function checkpoint(const info: TLineInfo; const filename: string; + line: int): boolean; + +procedure addCheckpoint(const info: TLineInfo); overload; +procedure addCheckpoint(const filename: string; line: int); overload; +function inCheckpoint(const current: TLineInfo): boolean; +// prints the line information if in checkpoint + +procedure pushInfoContext(const info: TLineInfo); +procedure popInfoContext; + +function includeFilename(const f: string): int; + + +implementation + +function UnknownLineInfo(): TLineInfo; +begin + result.line := int16(-1); + result.col := int16(-1); + result.fileIndex := -1; +end; + +{@ignore} +var + filenames: array of string; + msgContext: array of TLineInfo; +{@emit +var + filenames: array of string = @[]; + msgContext: array of TLineInfo = @[]; +} + +procedure pushInfoContext(const info: TLineInfo); +var + len: int; +begin + len := length(msgContext); + setLength(msgContext, len+1); + msgContext[len] := info; +end; + +procedure popInfoContext; +begin + setLength(msgContext, length(msgContext)-1); +end; + +function includeFilename(const f: string): int; +var + i: int; +begin + for i := high(filenames) downto low(filenames) do + if filenames[i] = f then begin + result := i; exit + end; + // not found, so add it: + result := length(filenames); + setLength(filenames, result+1); + filenames[result] := f; +end; + +function checkpoint(const info: TLineInfo; const filename: string; + line: int): boolean; +begin + result := (int(info.line) = line) and ( + ChangeFileExt(extractFilename(filenames[info.fileIndex]), '') = filename); +end; + + +{@ignore} +var + checkPoints: array of TLineInfo; +{@emit +var + checkPoints: array of TLineInfo = @[]; +} + +procedure addCheckpoint(const info: TLineInfo); overload; +var + len: int; +begin + len := length(checkPoints); + setLength(checkPoints, len+1); + checkPoints[len] := info; +end; + +procedure addCheckpoint(const filename: string; line: int); overload; +begin + addCheckpoint(newLineInfo(filename, line, -1)); +end; + +function newLineInfo(const filename: string; line, col: int): TLineInfo; +begin + result.fileIndex := includeFilename(filename); + result.line := int16(line); + result.col := int16(col); +end; + +function ToFilename(const info: TLineInfo): string; +begin + if info.fileIndex = -1 then result := '???' + else result := filenames[info.fileIndex] +end; + +function ToLinenumber(const info: TLineInfo): int; +begin + result := info.line +end; + +function toColumn(const info: TLineInfo): int; +begin + result := info.col +end; + +procedure MessageOut(const s: string); +begin // change only this proc to put it elsewhere + Writeln(output, s); +end; + +function coordToStr(const coord: int): string; +begin + if coord = -1 then result := '???' + else result := toString(coord) +end; + +function MsgKindToString(kind: TMsgKind): string; +begin // later versions may provide translated error messages + result := msgKindToStr[kind]; +end; + +function getMessageStr(msg: TMsgKind; const arg: string): string; +begin + result := format(msgKindToString(msg), [arg]); +end; + +function inCheckpoint(const current: TLineInfo): boolean; +var + i: int; +begin + result := false; + if not (optCheckpoints in gOptions) then exit; // ignore all checkpoints + for i := 0 to high(checkPoints) do begin + if (current.line = checkPoints[i].line) and + (current.fileIndex = (checkPoints[i].fileIndex)) then begin + MessageOut(Format('$1($2, $3) Checkpoint: ', [toFilename(current), + coordToStr(current.line), + coordToStr(current.col)])); + result := true; + exit + end + end +end; + +procedure handleError(const msg: TMsgKind); +begin + if msg = errInternal then assert(false); // we want a stack trace here + if (msg >= fatalMin) and (msg <= fatalMax) then begin + if gVerbosity >= 3 then assert(false); + halt(1) + end; + if (msg >= errMin) and (msg <= errMax) then begin + inc(gErrorCounter); + if gErrorCounter >= gErrorMax then begin + if gVerbosity >= 3 then assert(false); + halt(1) // one error stops the compiler + end + end +end; + +function sameLineInfo(const a, b: TLineInfo): bool; +begin + result := (a.line = b.line) and (a.fileIndex = b.fileIndex); +end; + +procedure writeContext(const lastinfo: TLineInfo); +var + i: int; + info: TLineInfo; +begin + info := lastInfo; + for i := 0 to length(msgContext)-1 do begin + if not sameLineInfo(msgContext[i], lastInfo) + and not sameLineInfo(msgContext[i], info) then + MessageOut(Format(posErrorFormat, [toFilename(msgContext[i]), + coordToStr(msgContext[i].line), + coordToStr(msgContext[i].col), + getMessageStr(errInstantiationFrom, '')])); + info := msgContext[i]; + end; +end; + +procedure rawMessage(const msg: TMsgKind; const args: array of string); +var + frmt: string; +begin + case msg of + errMin..errMax: begin + writeContext(unknownLineInfo()); + frmt := rawErrorFormat; + end; + warnMin..warnMax: begin + if not (optWarns in gOptions) then exit; + if not (msg in gNotes) then exit; + frmt := rawWarningFormat; + inc(gWarnCounter); + end; + hintMin..hintMax: begin + if not (optHints in gOptions) then exit; + if not (msg in gNotes) then exit; + frmt := rawHintFormat; + inc(gHintCounter); + end; + else assert(false) // cannot happen + end; + MessageOut(Format(frmt, format(msgKindToString(msg), args))); + handleError(msg); +end; + +procedure rawMessage(const msg: TMsgKind; const arg: string = ''); +begin + rawMessage(msg, [arg]); +end; + +procedure liMessage(const info: TLineInfo; const msg: TMsgKind; + const arg: string = ''); +var + frmt: string; +begin + case msg of + errMin..errMax: begin + writeContext(info); + frmt := posErrorFormat; + end; + warnMin..warnMax: begin + if not (optWarns in gOptions) then exit; + if not (msg in gNotes) then exit; + frmt := posWarningFormat; + inc(gWarnCounter); + end; + hintMin..hintMax: begin + if not (optHints in gOptions) then exit; + if not (msg in gNotes) then exit; + frmt := posHintFormat; + inc(gHintCounter); + end; + else assert(false) // cannot happen + end; + MessageOut(Format(frmt, [toFilename(info), + coordToStr(info.line), + coordToStr(info.col), + getMessageStr(msg, arg)])); + handleError(msg); +end; + +procedure InternalError(const info: TLineInfo; const errMsg: string); +begin + writeContext(info); + liMessage(info, errInternal, errMsg); +end; + +procedure InternalError(const errMsg: string); overload; +begin + writeContext(UnknownLineInfo()); + rawMessage(errInternal, errMsg); +end; + +end. diff --git a/nim/nhashes.pas b/nim/nhashes.pas index 0564f6f47..0564f6f47 100644..100755 --- a/nim/nhashes.pas +++ b/nim/nhashes.pas diff --git a/nim/nimconf.pas b/nim/nimconf.pas index 842446ae9..69c6f7618 100644..100755 --- a/nim/nimconf.pas +++ b/nim/nimconf.pas @@ -218,7 +218,7 @@ begin ppGetTok(L, tok) end else - lexMessage(L, errUnknownDirective, tokToStr(tok)) + lexMessage(L, errInvalidDirectiveX, tokToStr(tok)) end end; diff --git a/nim/nimrod.pas b/nim/nimrod.pas index 728325ccc..728325ccc 100644..100755 --- a/nim/nimrod.pas +++ b/nim/nimrod.pas diff --git a/nim/nimsets.pas b/nim/nimsets.pas index 9795817b8..9795817b8 100644..100755 --- a/nim/nimsets.pas +++ b/nim/nimsets.pas diff --git a/nim/nmath.pas b/nim/nmath.pas index 8b638eb42..8b638eb42 100644..100755 --- a/nim/nmath.pas +++ b/nim/nmath.pas diff --git a/nim/nos.pas b/nim/nos.pas index 4926c99b0..2edb0864e 100644..100755 --- a/nim/nos.pas +++ b/nim/nos.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. @@ -220,7 +220,7 @@ begin if (length(result) > 0) and (result[1] <> '/') then begin // not an absolute path? // iterate over any path in the $PATH environment variable - paths := splitSeq(getEnv('PATH'), [':']); + paths := split(getEnv('PATH'), [':']); for p := 0 to high(paths) do begin tail := joinPath(paths[p], result); if ExistsFile(tail) then begin result := tail; exit end diff --git a/nim/nstrtabs.pas b/nim/nstrtabs.pas index bcb10f2ed..bcb10f2ed 100644..100755 --- a/nim/nstrtabs.pas +++ b/nim/nstrtabs.pas diff --git a/nim/nsystem.pas b/nim/nsystem.pas index 51ca05605..49d17b172 100644..100755 --- a/nim/nsystem.pas +++ b/nim/nsystem.pas @@ -217,8 +217,15 @@ procedure nimWrite(var f: tBinaryFile; const str: string); overload; procedure add(var x: string; const y: string); // Pascal version of string appending. Terminating zero is ignored. +function isNil(s: string): bool; + implementation +function isNil(s: string): bool; +begin + result := s = ''; +end; + {@ignore} procedure add(var x: string; const y: string); // Pascal version of string appending. Terminating zero is ignored. diff --git a/nim/ntime.pas b/nim/ntime.pas index 9135c26c3..9135c26c3 100644..100755 --- a/nim/ntime.pas +++ b/nim/ntime.pas diff --git a/nim/nversion.pas b/nim/nversion.pas index e15f88068..add85acd1 100644..100755 --- a/nim/nversion.pas +++ b/nim/nversion.pas @@ -31,10 +31,10 @@ const //cog.outl('VersionMinor = %s;' % ver[1]) //cog.outl('VersionPatch = %s;' % ver[2]) //]]] - VersionAsString = '0.7.10'; + VersionAsString = '0.8.0'; VersionMajor = 0; - VersionMinor = 7; - VersionPatch = 10; + VersionMinor = 8; + VersionPatch = 0; //[[[[end]]]] implementation diff --git a/nim/options.pas b/nim/options.pas index f84d8458c..d210f3b44 100644..100755 --- a/nim/options.pas +++ b/nim/options.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. @@ -46,7 +46,8 @@ type optRun, // run the compiled project optSymbolFiles, // use symbol files for speeding up compilation optSkipConfigFile, // skip the general config file - optSkipProjConfigFile // skip the project's config file + optSkipProjConfigFile, // skip the project's config file + optNoMain // do not generate a "main" proc ); TGlobalOptions = set of TGlobalOption; @@ -68,6 +69,7 @@ type cmdScan, // scan a single file (for debugging) cmdDebugTrans, // debug a transformation pass cmdRst2html, // convert a reStructuredText file to HTML + cmdRst2tex, // convert a reStructuredText file to TeX cmdInteractive // start interactive session ); TStringSeq = array of string; @@ -107,9 +109,11 @@ const NimExt = 'nim'; RodExt = 'rod'; HtmlExt = 'html'; + TexExt = 'tex'; IniExt = 'ini'; TmplExt = 'tmpl'; DocConfig = 'nimdoc.cfg'; + DocTexConfig = 'nimdoc.tex.cfg'; function completeGeneratedFilePath(const f: string; createSubDir: bool = true): string; diff --git a/nim/osproc.pas b/nim/osproc.pas index dd6bd10f0..dd6bd10f0 100644..100755 --- a/nim/osproc.pas +++ b/nim/osproc.pas diff --git a/nim/parsecfg.pas b/nim/parsecfg.pas index ba6a98679..ba6a98679 100644..100755 --- a/nim/parsecfg.pas +++ b/nim/parsecfg.pas diff --git a/nim/parseopt.pas b/nim/parseopt.pas index 0ca87bd37..0ca87bd37 100644..100755 --- a/nim/parseopt.pas +++ b/nim/parseopt.pas diff --git a/nim/paslex.pas b/nim/paslex.pas index f3d8daaeb..f3d8daaeb 100644..100755 --- a/nim/paslex.pas +++ b/nim/paslex.pas diff --git a/nim/pasparse.pas b/nim/pasparse.pas index 73280aeca..8a73feca5 100644..100755 --- a/nim/pasparse.pas +++ b/nim/pasparse.pas @@ -293,7 +293,7 @@ begin addSon(result, a.sons[1]); end else begin - parMessage(p, errInvalidDirective); + parMessage(p, errInvalidDirectiveX, pasTokToStr(p.tok)); result := a end end @@ -334,7 +334,7 @@ begin getTok(p); eat(p, pxCurlyDirRi); end else begin - parMessage(p, errUnknownDirective, pasTokToStr(p.tok)); + parMessage(p, errInvalidDirectiveX, pasTokToStr(p.tok)); while true do begin getTok(p); if (p.tok.xkind = pxCurlyDirRi) or (p.tok.xkind = pxEof) then break; diff --git a/nim/passaux.pas b/nim/passaux.pas index 8b052257f..8b052257f 100644..100755 --- a/nim/passaux.pas +++ b/nim/passaux.pas diff --git a/nim/passes.pas b/nim/passes.pas index f5dff3559..f5dff3559 100644..100755 --- a/nim/passes.pas +++ b/nim/passes.pas diff --git a/nim/platform.pas b/nim/platform.pas index 9f8d30f60..9f8d30f60 100644..100755 --- a/nim/platform.pas +++ b/nim/platform.pas diff --git a/nim/pnimsyn.pas b/nim/pnimsyn.pas index 2ca411770..dae7de539 100644..100755 --- a/nim/pnimsyn.pas +++ b/nim/pnimsyn.pas @@ -612,6 +612,18 @@ begin result := newStrNodeP(nkTripleStrLit, p.tok.literal, p); getTok(p); end; + tkCallRStrLit: begin + result := newNodeP(nkCallStrLit, p); + addSon(result, newIdentNodeP(p.tok.ident, p)); + addSon(result, newStrNodeP(nkRStrLit, p.tok.literal, p)); + getTok(p); + end; + tkCallTripleStrLit: begin + result := newNodeP(nkCallStrLit, p); + addSon(result, newIdentNodeP(p.tok.ident, p)); + addSon(result, newStrNodeP(nkTripleStrLit, p.tok.literal, p)); + getTok(p); + end; tkCharLit: begin result := newIntNodeP(nkCharLit, ord(p.tok.literal[strStart]), p); getTok(p); @@ -885,8 +897,8 @@ begin while true do begin case p.tok.tokType of tkEof, tkSad, tkDed: break; - tkSymbol, tkAccent: a := parseSymbol(p); - tkRStrLit: begin + tkSymbol, tkAccent: a := parseSymbol(p); + tkRStrLit: begin a := newStrNodeP(nkRStrLit, p.tok.literal, p); getTok(p) end; @@ -901,16 +913,7 @@ begin else begin parMessage(p, errIdentifierExpected, tokToStr(p.tok)); break - end; - end; - //optInd(p, a); - if p.tok.tokType = tkAs then begin - getTok(p); - optInd(p, a); - b := a; - a := newNodeP(nkImportAs, p); - addSon(a, b); - addSon(a, parseSymbol(p)); + end end; addSon(result, a); if p.tok.tokType <> tkComma then break; @@ -1227,24 +1230,31 @@ begin result := a end; -function parseIdentColonEquals(var p: TParser; withPragma: bool): PNode; +type + TDeclaredIdentFlag = ( + withPragma, // identifier may have pragma + withBothOptional // both ':' and '=' parts are optional + ); + TDeclaredIdentFlags = set of TDeclaredIdentFlag; + +function parseIdentColonEquals(var p: TParser; + flags: TDeclaredIdentFlags): PNode; var a: PNode; begin result := newNodeP(nkIdentDefs, p); while true do begin case p.tok.tokType of - tkColon, tkEof, tkSad, tkDed, tkParRi, tkEquals: break; - else begin - if withPragma then + tkSymbol, tkAccent: begin + if withPragma in flags then a := identWithPragma(p) else a := parseSymbol(p); if a = nil then exit; - end + end; + else break; end; addSon(result, a); - //optInd(p, a); if p.tok.tokType <> tkComma then break; getTok(p); optInd(p, a) @@ -1255,7 +1265,7 @@ begin end else begin addSon(result, nil); - if p.tok.tokType <> tkEquals then + if (p.tok.tokType <> tkEquals) and not (withBothOptional in flags) then parMessage(p, errColonOrEqualsExpected, tokToStr(p.tok)) end; if p.tok.tokType = tkEquals then begin @@ -1277,7 +1287,7 @@ begin optInd(p, result); while true do begin case p.tok.tokType of - tkSymbol, tkAccent: a := parseIdentColonEquals(p, false); + tkSymbol, tkAccent: a := parseIdentColonEquals(p, {@set}[]); tkParRi: break; else begin parMessage(p, errTokenExpected, ')'+''); break; end; end; @@ -1335,7 +1345,7 @@ begin eat(p, tkBracketLe); optInd(p, result); while (p.tok.tokType = tkSymbol) or (p.tok.tokType = tkAccent) do begin - a := parseIdentColonEquals(p, false); + a := parseIdentColonEquals(p, {@set}[]); addSon(result, a); if p.tok.tokType <> tkComma then break; getTok(p); @@ -1360,23 +1370,6 @@ begin end end; -function parseGenericParam(var p: TParser): PNode; -var - a: PNode; -begin - a := parseSymbol(p); - optInd(p, a); - if p.tok.tokType = tkEquals then begin - result := newNodeP(nkDefaultTypeParam, p); - getTok(p); - optInd(p, a); - addSon(result, a); - addSon(result, parseTypeDesc(p)); - end - else - result := a -end; - function parseGenericParamList(var p: TParser): PNode; var a: PNode; @@ -1385,7 +1378,7 @@ begin getTok(p); optInd(p, result); while (p.tok.tokType = tkSymbol) or (p.tok.tokType = tkAccent) do begin - a := parseGenericParam(p); + a := parseIdentColonEquals(p, {@set}[withBothOptional]); addSon(result, a); if p.tok.tokType <> tkComma then break; getTok(p); @@ -1479,7 +1472,10 @@ begin end; popInd(p.lex^); end; - tkSymbol, tkAccent: addSon(result, defparser(p)); + tkSymbol, tkAccent, tkParLe: begin + // tkParLe is allowed for ``var (x, y) = ...`` tuple parsing + addSon(result, defparser(p)); + end else parMessage(p, errIdentifierExpected, tokToStr(p.tok)); end end; @@ -1627,7 +1623,7 @@ begin tkWhen: result := parseRecordWhen(p); tkCase: result := parseRecordCase(p); tkSymbol, tkAccent: begin - result := parseIdentColonEquals(p, true); + result := parseIdentColonEquals(p, {@set}[withPragma]); skipComment(p, result); end; tkNil: begin @@ -1660,9 +1656,9 @@ begin addSon(result, parseRecordPart(p)); end; -function parseAbstract(var p: TParser): PNode; +function parseDistinct(var p: TParser): PNode; begin - result := newNodeP(nkAbstractTy, p); + result := newNodeP(nkDistinctTy, p); getTok(p); optInd(p, result); addSon(result, parseTypeDesc(p)); @@ -1681,7 +1677,7 @@ begin case p.tok.tokType of tkObject: a := parseRecordOrObject(p, nkObjectTy); tkEnum: a := parseEnum(p); - tkAbstract: a := parseAbstract(p); + tkDistinct: a := parseDistinct(p); else a := parseTypeDesc(p); end; addSon(result, a); @@ -1718,7 +1714,7 @@ begin if p.tok.tokType = tkParLe then result := parseVarTuple(p) else - result := parseIdentColonEquals(p, true); + result := parseIdentColonEquals(p, {@set}[withPragma]); indAndComment(p, result); // special extension! end; diff --git a/nim/pragmas.pas b/nim/pragmas.pas index f81cdd6e2..5ec706f19 100644..100755 --- a/nim/pragmas.pas +++ b/nim/pragmas.pas @@ -19,16 +19,45 @@ uses rnimsyn, wordrecg, ropes, options, strutils, lists, extccomp, nmath, magicsys; -procedure pragmaProc(c: PContext; s: PSym; n: PNode); -procedure pragmaMacro(c: PContext; s: PSym; n: PNode); -procedure pragmaIterator(c: PContext; s: PSym; n: PNode); -procedure pragmaStmt(c: PContext; s: PSym; n: PNode); -procedure pragmaLambda(c: PContext; s: PSym; n: PNode); -procedure pragmaType(c: PContext; s: PSym; n: PNode); -procedure pragmaField(c: PContext; s: PSym; n: PNode); -procedure pragmaVar(c: PContext; s: PSym; n: PNode); -procedure pragmaConst(c: PContext; s: PSym; n: PNode); -procedure pragmaProcType(c: PContext; s: PSym; n: PNode); +const + FirstCallConv = wNimcall; + LastCallConv = wNoconv; + +const + procPragmas = {@set}[FirstCallConv..LastCallConv, + wImportc, wExportc, wNodecl, wMagic, wNosideEffect, wSideEffect, + wNoreturn, wDynLib, wHeader, wCompilerProc, wPure, + wCppMethod, wDeprecated, wVarargs, wCompileTime, wMerge, + wBorrow]; + converterPragmas = procPragmas; + macroPragmas = {@set}[FirstCallConv..LastCallConv, + wImportc, wExportc, wNodecl, wMagic, wNosideEffect, + wCompilerProc, wDeprecated, wTypeCheck]; + iteratorPragmas = {@set}[FirstCallConv..LastCallConv, + wNosideEffect, wSideEffect, + wImportc, wExportc, wNodecl, wMagic, wDeprecated, wBorrow]; + stmtPragmas = {@set}[wChecks, wObjChecks, wFieldChecks, wRangechecks, + wBoundchecks, wOverflowchecks, wNilchecks, wAssertions, wWarnings, + wHints, wLinedir, wStacktrace, wLinetrace, wOptimization, + wHint, wWarning, wError, wFatal, wDefine, wUndef, + wCompile, wLink, wLinkSys, wPure, + wPush, wPop, wBreakpoint, wCheckpoint, + wPassL, wPassC, wDeadCodeElim]; + lambdaPragmas = {@set}[FirstCallConv..LastCallConv, + wImportc, wExportc, wNodecl, wNosideEffect, wSideEffect, + wNoreturn, wDynLib, wHeader, wPure, wDeprecated]; + typePragmas = {@set}[wImportc, wExportc, wDeprecated, wMagic, wAcyclic, + wNodecl, wPure, wHeader, wCompilerProc, wFinal]; + fieldPragmas = {@set}[wImportc, wExportc, wDeprecated]; + varPragmas = {@set}[wImportc, wExportc, wVolatile, wRegister, wThreadVar, + wNodecl, wMagic, wHeader, wDeprecated, wCompilerProc, + wDynLib]; + constPragmas = {@set}[wImportc, wExportc, wHeader, wDeprecated, + wMagic, wNodecl]; + procTypePragmas = [FirstCallConv..LastCallConv, wVarargs, wNosideEffect]; + +procedure pragma(c: PContext; sym: PSym; n: PNode; + const validPragmas: TSpecialWords); function pragmaAsm(c: PContext; n: PNode): char; @@ -66,9 +95,6 @@ begin end; const - FirstCallConv = wNimcall; - LastCallConv = wNoconv; - FirstPragmaWord = wMagic; LastPragmaWord = wNoconv; @@ -598,74 +624,4 @@ begin end end; -procedure pragmaProc(c: PContext; s: PSym; n: PNode); -begin - pragma(c, s, n, {@set}[FirstCallConv..LastCallConv, - wImportc, wExportc, wNodecl, wMagic, wNosideEffect, wSideEffect, - wNoreturn, wDynLib, wHeader, wCompilerProc, wPure, - wCppMethod, wDeprecated, wVarargs, wCompileTime, wMerge, - wBorrow]); -end; - -procedure pragmaMacro(c: PContext; s: PSym; n: PNode); -begin - pragma(c, s, n, {@set}[FirstCallConv..LastCallConv, - wImportc, wExportc, wNodecl, wMagic, wNosideEffect, - wCompilerProc, wDeprecated, wTypeCheck]); -end; - -procedure pragmaIterator(c: PContext; s: PSym; n: PNode); -begin - pragma(c, s, n, {@set}[FirstCallConv..LastCallConv, - wNosideEffect, wSideEffect, - wImportc, wExportc, wNodecl, wMagic, wDeprecated, wBorrow]); -end; - -procedure pragmaStmt(c: PContext; s: PSym; n: PNode); -begin - pragma(c, s, n, {@set}[wChecks, wObjChecks, wFieldChecks, wRangechecks, - wBoundchecks, wOverflowchecks, wNilchecks, wAssertions, wWarnings, - wHints, wLinedir, wStacktrace, wLinetrace, wOptimization, - wHint, wWarning, wError, wFatal, wDefine, wUndef, - wCompile, wLink, wLinkSys, wPure, - wPush, wPop, wBreakpoint, wCheckpoint, - wPassL, wPassC, wDeadCodeElim]); -end; - -procedure pragmaLambda(c: PContext; s: PSym; n: PNode); -begin - pragma(c, s, n, {@set}[FirstCallConv..LastCallConv, - wImportc, wExportc, wNodecl, wNosideEffect, wSideEffect, - wNoreturn, wDynLib, wHeader, wPure, wDeprecated]); -end; - -procedure pragmaType(c: PContext; s: PSym; n: PNode); -begin - pragma(c, s, n, {@set}[wImportc, wExportc, wDeprecated, wMagic, wAcyclic, - wNodecl, wPure, wHeader, wCompilerProc, wFinal]); -end; - -procedure pragmaField(c: PContext; s: PSym; n: PNode); -begin - pragma(c, s, n, {@set}[wImportc, wExportc, wDeprecated]); -end; - -procedure pragmaVar(c: PContext; s: PSym; n: PNode); -begin - pragma(c, s, n, {@set}[wImportc, wExportc, wVolatile, wRegister, wThreadVar, - wNodecl, wMagic, wHeader, wDeprecated, wCompilerProc, - wDynLib]); -end; - -procedure pragmaConst(c: PContext; s: PSym; n: PNode); -begin - pragma(c, s, n, {@set}[wImportc, wExportc, wHeader, wDeprecated, - wMagic, wNodecl]); -end; - -procedure pragmaProcType(c: PContext; s: PSym; n: PNode); -begin - pragma(c, s, n, [FirstCallConv..LastCallConv, wVarargs]); -end; - end. diff --git a/nim/procfind.pas b/nim/procfind.pas index c8792586a..e93820ab3 100644..100755 --- a/nim/procfind.pas +++ b/nim/procfind.pas @@ -16,7 +16,7 @@ interface {$include 'config.inc'} uses - nsystem, ast, astalgo, msgs, semdata, types; + nsystem, ast, astalgo, msgs, semdata, types, trees; function SearchForProc(c: PContext; fn: PSym; tos: int): PSym; // Searchs for the fn in the symbol table. If the parameter lists are exactly @@ -45,7 +45,9 @@ begin InternalError(procB.info, 'equalGenericParams'); a := procA.sons[i].sym; b := procB.sons[i].sym; - if (a.name.id <> b.name.id) or not sameType(a.typ, b.typ) then exit; + if (a.name.id <> b.name.id) or not sameTypeOrNil(a.typ, b.typ) then exit; + if (a.ast <> nil) and (b.ast <> nil) then + if not ExprStructuralEquivalent(a.ast, b.ast) then exit; end; result := true end; @@ -85,10 +87,10 @@ begin m := a.sons[i].sym; n := b.sons[i].sym; assert((m.kind = skParam) and (n.kind = skParam)); - if not equalOrAbstractOf(m.typ, n.typ) then exit; + if not equalOrDistinctOf(m.typ, n.typ) then exit; end; // return type: - if not equalOrAbstractOf(a.sons[0].typ, b.sons[0].typ) then exit; + if not equalOrDistinctOf(a.sons[0].typ, b.sons[0].typ) then exit; result := true end end; diff --git a/nim/ptmplsyn.pas b/nim/ptmplsyn.pas index 2368b22c7..2368b22c7 100644..100755 --- a/nim/ptmplsyn.pas +++ b/nim/ptmplsyn.pas diff --git a/nim/readme.txt b/nim/readme.txt index 99d574bac..99d574bac 100644..100755 --- a/nim/readme.txt +++ b/nim/readme.txt diff --git a/nim/rnimsyn.pas b/nim/rnimsyn.pas index 0ed3cfcd7..b3271a3bb 100644..100755 --- a/nim/rnimsyn.pas +++ b/nim/rnimsyn.pas @@ -188,10 +188,8 @@ var i: int; begin result := '"' + ''; - for i := strStart to length(s)+strStart-1 do begin - result := result +{&} toNimChar(s[i]); - end; - result := result + '"'; + for i := strStart to length(s)+strStart-1 do add(result, toNimChar(s[i])); + addChar(result, '"'); end; procedure putComment(var g: TSrcGen; s: string); @@ -496,7 +494,7 @@ begin nkAddr: result := lsub(n.sons[0])+length('addr()'); nkHiddenAddr, nkHiddenDeref: result := lsub(n.sons[0]); nkCommand: result := lsub(n.sons[0])+lcomma(n, 1)+1; - nkExprEqExpr, nkDefaultTypeParam, nkAsgn, nkFastAsgn: result := lsons(n)+3; + nkExprEqExpr, 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[]'); @@ -528,10 +526,10 @@ begin nkInfix: result := lsons(n) + 2; nkPrefix: result := lsons(n) + 1; nkPostfix: result := lsons(n); + nkCallStrLit: result := lsons(n); nkPragmaExpr: result := lsub(n.sons[0])+lcomma(n, 1); nkRange: result := lsons(n) + 2; nkDerefExpr: result := lsub(n.sons[0])+2; - nkImportAs: result := lsons(n) + length('_as_'); nkAccQuoted: result := lsub(n.sons[0]) + 2; nkIfExpr: result := lsub(n.sons[0].sons[0])+lsub(n.sons[0].sons[1]) @@ -544,7 +542,7 @@ begin nkRefTy: result := lsub(n.sons[0])+length('ref_'); nkPtrTy: result := lsub(n.sons[0])+length('ptr_'); nkVarTy: result := lsub(n.sons[0])+length('var_'); - nkAbstractTy: result := lsub(n.sons[0])+length('abstract_'); + nkDistinctTy: result := lsub(n.sons[0])+length('Distinct_'); nkTypeDef: result := lsons(n)+3; nkOfInherit: result := lsub(n.sons[0])+length('of_'); nkProcTy: result := lsons(n)+length('proc_'); @@ -612,11 +610,6 @@ begin gsub(g, n, c); end; -function one(b: bool): int; -begin - if b then result := 1 else result := 0 -end; - function hasCom(n: PNode): bool; var i: int; @@ -649,7 +642,7 @@ var begin for i := start to sonsLen(n)+theEnd do begin c := i < sonsLen(n)+theEnd; - sublen := lsub(n.sons[i])+one(c); + sublen := lsub(n.sons[i])+ord(c); if not fits(g, sublen) and (ind+sublen < maxLineLen) then optNL(g, ind); gsub(g, n.sons[i]); if c then begin @@ -959,6 +952,13 @@ begin gcomma(g, n, 1); put(g, tkParRi, ')'+''); end; + nkCallStrLit: begin + gsub(g, n.sons[0]); + if n.sons[1].kind = nkRStrLit then + put(g, tkRStrLit, '"' + n.sons[1].strVal + '"') + else + gsub(g, n.sons[0]); + end; nkHiddenStdConv, nkHiddenSubConv, nkHiddenCallConv: begin gsub(g, n.sons[0]); end; @@ -992,7 +992,7 @@ begin put(g, tkSpaces, space); gcomma(g, n, 1); end; - nkExprEqExpr, nkDefaultTypeParam, nkAsgn, nkFastAsgn: begin + nkExprEqExpr, nkAsgn, nkFastAsgn: begin gsub(g, n.sons[0]); put(g, tkSpaces, Space); putWithSpace(g, tkEquals, '='+''); @@ -1121,12 +1121,6 @@ begin // unfortunately this requires a space, because ^. would be // only one operator end; - nkImportAs: begin - gsub(g, n.sons[0]); - put(g, tkSpaces, Space); - putWithSpace(g, tkAs, 'as'); - gsub(g, n.sons[1]); - end; nkAccQuoted: begin put(g, tkAccent, '`'+''); gsub(g, n.sons[0]); @@ -1167,8 +1161,8 @@ begin putWithSpace(g, tkVar, 'var'); gsub(g, n.sons[0]); end; - nkAbstractTy: begin - putWithSpace(g, tkAbstract, 'abstract'); + nkDistinctTy: begin + putWithSpace(g, tkDistinct, 'distinct'); gsub(g, n.sons[0]); end; nkTypeDef: begin diff --git a/nim/rodread.pas b/nim/rodread.pas index a34153ccf..dc3630a45 100644..100755 --- a/nim/rodread.pas +++ b/nim/rodread.pas @@ -172,7 +172,7 @@ begin res := ''; for i := strStart to length(s)+strStart-1 do begin case s[i] of - '0'..'9', 'a'..'z', 'A'..'Z', '_': + 'a'..'z', 'A'..'Z', '0'..'9', '_': addChar(res, s[i]); else res := res +{&} '\' +{&} toHex(ord(s[i]), 2) @@ -535,7 +535,7 @@ var begin i := r.pos; sign := -1; - assert(r.s[i] in ['0'..'9', 'a'..'z', 'A'..'Z', '-', #128..#255]); + assert(r.s[i] in ['a'..'z', 'A'..'Z', '0'..'9', '-', #128..#255]); if r.s[i] = '-' then begin inc(i); sign := 1 @@ -562,7 +562,7 @@ var begin i := r.pos; sign := -1; - assert(r.s[i] in ['0'..'9', 'a'..'z', 'A'..'Z', '-', #128..#255]); + assert(r.s[i] in ['a'..'z', 'A'..'Z', '0'..'9', '-', #128..#255]); if r.s[i] = '-' then begin inc(i); sign := 1 @@ -606,7 +606,7 @@ begin hexChar(r.s[i-1], xi); addChar(result, chr(xi)); end; - 'a'..'z', '0'..'9', 'A'..'Z', '_': begin + 'a'..'z', 'A'..'Z', '0'..'9', '_': begin addChar(result, r.s[i]); inc(i); end diff --git a/nim/rodwrite.pas b/nim/rodwrite.pas index 72d5c893d..72d5c893d 100644..100755 --- a/nim/rodwrite.pas +++ b/nim/rodwrite.pas diff --git a/nim/ropes.pas b/nim/ropes.pas index 286f1b9e6..286f1b9e6 100644..100755 --- a/nim/ropes.pas +++ b/nim/ropes.pas diff --git a/nim/rst.pas b/nim/rst.pas index d2afc7e33..d5cde5c7e 100644..100755 --- a/nim/rst.pas +++ b/nim/rst.pas @@ -142,6 +142,8 @@ procedure addSon(father, son: PRstNode); function rstnodeToRefname(n: PRstNode): string; +function addNodes(n: PRstNode): string; + function getFieldValue(n: PRstNode; const fieldname: string): string; function getArgument(n: PRstNode): string; @@ -1834,7 +1836,6 @@ begin rnDirective: a := parseDotDot(p); rnEnumList: a := parseEnumList(p); rnLeaf: begin - //writeln(ord(p.tok[p.idx].kind), ' ', p.tok[p.idx].symbol); rstMessage(p, errNewSectionExpected); end; rnParagraph: begin end; @@ -1856,14 +1857,9 @@ begin end; addSonIfNotNil(result, a); end; - //if (result.kind in [rnBulletItem]) and if (sonKind(result, 0) = rnParagraph) and (sonKind(result, 1) <> rnParagraph) then result.sons[0].kind := rnInner; - (* - if (result.kind <> rnInner) and (rsonsLen(result) = 1) - and (result.sons[0].kind = rnParagraph) then - result.sons[0].kind := rnInner; *) end; function parseSectionWrapper(var p: TRstParser): PRstNode; @@ -1921,7 +1917,6 @@ begin if (assigned(contentParser)) and (p.tok[p.idx].kind = tkIndent) and (p.tok[p.idx].ival > currInd(p)) then begin pushInd(p, p.tok[p.idx].ival); - //while p.tok[p.idx].kind = tkIndent do inc(p.idx); content := contentParser(p); popInd(p); addSon(result, content) @@ -2085,7 +2080,7 @@ begin dkRaw: result := dirRaw(p); dkCodeblock: result := dirCodeBlock(p); dkIndex: result := dirIndex(p); - else rstMessage(p, errUnknownDirective, d); + else rstMessage(p, errInvalidDirectiveX, d); end; popInd(p); end @@ -2112,7 +2107,7 @@ begin b := dirImage(p); end else - rstMessage(p, errUnknownDirective, p.tok[p.idx].symbol); + rstMessage(p, errInvalidDirectiveX, p.tok[p.idx].symbol); setSub(p, addNodes(a), b); end else if match(p, p.idx, ' [') then begin @@ -2172,6 +2167,8 @@ function rstParse(const text: string; // the text to be parsed var p: TRstParser; begin + if isNil(text) then + rawMessage(errCannotOpenFile, filename); initParser(p, newSharedState()); p.filename := filename; p.line := line; diff --git a/nim/scanner.pas b/nim/scanner.pas index edc9ca24a..ffe1741f5 100644..100755 --- a/nim/scanner.pas +++ b/nim/scanner.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. @@ -52,10 +52,10 @@ type // i = i + 1 //cog.out(idents) //]]] - tkAbstract, tkAddr, tkAnd, tkAs, - tkAsm, tkBind, tkBlock, tkBreak, - tkCase, tkCast, tkConst, tkContinue, - tkConverter, tkDiscard, tkDiv, tkElif, + tkAddr, tkAnd, tkAs, tkAsm, + tkBind, tkBlock, tkBreak, tkCase, + tkCast, tkConst, tkContinue, tkConverter, + tkDiscard, tkDistinct, tkDiv, tkElif, tkElse, tkEnd, tkEnum, tkExcept, tkFinally, tkFor, tkFrom, tkGeneric, tkIf, tkImplies, tkImport, tkIn, @@ -71,8 +71,8 @@ type //[[[end]]] tkIntLit, tkInt8Lit, tkInt16Lit, tkInt32Lit, tkInt64Lit, tkFloatLit, tkFloat32Lit, tkFloat64Lit, - tkStrLit, tkRStrLit, tkTripleStrLit, tkCharLit, - tkParLe, tkParRi, tkBracketLe, tkBracketRi, tkCurlyLe, tkCurlyRi, + tkStrLit, tkRStrLit, tkTripleStrLit, tkCallRStrLit, tkCallTripleStrLit, + tkCharLit, tkParLe, tkParRi, tkBracketLe, tkBracketRi, tkCurlyLe, tkCurlyRi, tkBracketDotLe, tkBracketDotRi, // [. and .] tkCurlyDotLe, tkCurlyDotRi, // {. and .} tkParDotLe, tkParDotRi, // (. and .) @@ -96,10 +96,10 @@ const //[[[cog //cog.out(strings) //]]] - 'abstract', 'addr', 'and', 'as', - 'asm', 'bind', 'block', 'break', - 'case', 'cast', 'const', 'continue', - 'converter', 'discard', 'div', 'elif', + 'addr', 'and', 'as', 'asm', + 'bind', 'block', 'break', 'case', + 'cast', 'const', 'continue', 'converter', + 'discard', 'distinct', 'div', 'elif', 'else', 'end', 'enum', 'except', 'finally', 'for', 'from', 'generic', 'if', 'implies', 'import', 'in', @@ -115,7 +115,9 @@ const //[[[end]]] 'tkIntLit', 'tkInt8Lit', 'tkInt16Lit', 'tkInt32Lit', 'tkInt64Lit', 'tkFloatLit', 'tkFloat32Lit', 'tkFloat64Lit', - 'tkStrLit', 'tkRStrLit', 'tkTripleStrLit', 'tkCharLit', + 'tkStrLit', 'tkRStrLit', 'tkTripleStrLit', + 'tkCallRStrLit', 'tkCallTripleStrLit', + 'tkCharLit', '('+'', ')'+'', '['+'', ']'+'', '{'+'', '}'+'', '[.', '.]', '{.', '.}', '(.', '.)', ','+'', ';'+'', ':'+'', '='+'', '.'+'', '..', '^'+'', 'tkOpr', @@ -764,7 +766,12 @@ begin (tok.ident.id > ord(tokKeywordHigh)-ord(tkSymbol)) then tok.tokType := tkSymbol else - tok.tokType := TTokType(tok.ident.id+ord(tkSymbol)) + tok.tokType := TTokType(tok.ident.id+ord(tkSymbol)); + if buf[pos] = '"' then begin + getString(L, tok, true); + if tok.tokType = tkRStrLit then tok.tokType := tkCallRStrLit + else tok.tokType := tkCallTripleStrLit + end end; procedure getOperator(var L: TLexer; var tok: TToken); diff --git a/nim/sem.pas b/nim/sem.pas index 1fd141f5a..029ba869f 100644..100755 --- a/nim/sem.pas +++ b/nim/sem.pas @@ -15,7 +15,7 @@ interface {$include 'config.inc'} uses - sysutils, nsystem, charsets, strutils, + sysutils, nsystem, charsets, strutils, nhashes, lists, options, scanner, ast, astalgo, trees, treetab, wordrecg, ropes, msgs, nos, condsyms, idents, rnimsyn, types, platform, nmath, magicsys, pnimsyn, nversion, nimsets, @@ -29,8 +29,6 @@ function semPass(): TPass; implementation -function semp(c: PContext; n: PNode): PNode; forward; - function considerAcc(n: PNode): PIdent; var x: PNode; @@ -47,6 +45,11 @@ begin end end; +function isTopLevel(c: PContext): bool; +begin + result := c.tab.tos <= 2 +end; + function newSymS(const kind: TSymKind; n: PNode; c: PContext): PSym; begin result := newSym(kind, considerAcc(n), getCurrOwner()); @@ -62,27 +65,32 @@ function semIdentWithPragma(c: PContext; kind: TSymKind; function semStmtScope(c: PContext; n: PNode): PNode; forward; type - TExprFlag = (efAllowType, efLValue); + TExprFlag = (efAllowType, efLValue, efWantIterator); TExprFlags = set of TExprFlag; function semExpr(c: PContext; n: PNode; flags: TExprFlags = {@set}[]): PNode; forward; function semExprWithType(c: PContext; n: PNode; flags: TExprFlags = {@set}[]): PNode; forward; +function fitNode(c: PContext; formal: PType; arg: PNode): PNode; forward; function semLambda(c: PContext; n: PNode): PNode; forward; function semTypeNode(c: PContext; n: PNode; prev: PType): PType; forward; function semStmt(c: PContext; n: PNode): PNode; forward; +procedure semParamList(c: PContext; n, genericParams: PNode; s: PSym); forward; +procedure addParams(c: PContext; n: PNode); forward; +procedure addResult(c: PContext; t: PType; const info: TLineInfo); forward; +procedure addResultNode(c: PContext; n: PNode); forward; + +function instGenericContainer(c: PContext; n: PNode; header: PType): PType; forward; function semConstExpr(c: PContext; n: PNode): PNode; -var - e: PNode; begin - e := semExprWithType(c, n); - if e = nil then begin + result := semExprWithType(c, n); + if result = nil then begin liMessage(n.info, errConstExprExpected); - result := nil; exit + exit end; - result := getConstExpr(c.module, e); + result := getConstExpr(c.module, result); if result = nil then liMessage(n.info, errConstExprExpected); end; @@ -105,24 +113,19 @@ begin end end; -function semAfterMacroCall(c: PContext; n, p: PNode): PNode; +function semAfterMacroCall(c: PContext; n: PNode; s: PSym): PNode; begin result := n; - if (p = nil) or (p.kind <> nkIdent) then - liMessage(n.info, errInvalidParamKindX, renderTree(p)) - else begin - case p.ident.id of - ord(wExpr): result := semExprWithType(c, result); - ord(wStmt): result := semStmt(c, result); - ord(wTypeDesc): - result.typ := semTypeNode(c, result, nil); - else - liMessage(p.info, errInvalidParamKindX, p.ident.s) - end + case s.typ.sons[0].kind of + tyExpr: result := semExprWithType(c, result); + tyStmt: result := semStmt(c, result); + tyTypeDesc: result.typ := semTypeNode(c, result, nil); + else liMessage(s.info, errInvalidParamKindX, typeToString(s.typ.sons[0])) end end; -function semMacroExpr(c: PContext; n: PNode; sym: PSym): PNode; +function semMacroExpr(c: PContext; n: PNode; sym: PSym; + semCheck: bool = true): PNode; var p: PEvalContext; s: PStackFrame; @@ -139,9 +142,8 @@ begin result := s.params[0]; popStackFrame(p); if cyclicTree(result) then liMessage(n.info, errCyclicTree); - result := semAfterMacroCall(c, result, sym.ast.sons[paramsPos].sons[0]); - // now, that was easy ... - // and we get more flexibility than in any other programming language + if semCheck then + result := semAfterMacroCall(c, result, sym); end; {$include 'semtempl.pas'} @@ -164,13 +166,9 @@ end; {$include 'semtypes.pas'} {$include 'semexprs.pas'} +{$include 'semgnrc.pas'} {$include 'semstmts.pas'} -function semp(c: PContext; n: PNode): PNode; -begin - result := semStmt(c, n); -end; - procedure addCodeForGenerics(c: PContext; n: PNode); var i: int; diff --git a/nim/semdata.pas b/nim/semdata.pas index acaffd3bf..37934f3d6 100644..100755 --- a/nim/semdata.pas +++ b/nim/semdata.pas @@ -42,24 +42,29 @@ type PContext = ^TContext; TContext = object(TPassContext) // a context represents a module - module: PSym; // the module sym belonging to the context - filename: string; // the module's filename - tab: TSymTab; // each module has its own symbol table - 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 - // symbol and the instantiated symbol - converters: TSymSeq; // sequence of converters + module: PSym; // the module sym belonging to the context + p: PProcCon; // procedure context + InstCounter: int; // to prevent endless instantiations + generics: PNode; // a list of the things to compile; list of + // nkExprEqExpr nodes which contain the + // generic symbol and the instantiated symbol + lastGenericIdx: int; // used for the generics stack + tab: TSymTab; // each module has its own symbol table + AmbiguousSymbols: TIntSet; // ids of all ambiguous symbols (cannot + // store this info in the syms themselves!) + converters: TSymSeq; // sequence of converters optionStack: TLinkedList; - libs: TLinkedList; // all libs used by this module - p: PProcCon; // procedure context - fromCache: bool; // is the module read from a cache? - lastGenericIdx: int; // used for the generics stack + libs: TLinkedList; // all libs used by this module + fromCache: bool; // is the module read from a cache? semConstExpr: function (c: PContext; n: PNode): PNode; // for the pragmas module + includedFiles: TIntSet; // used to detect recursive include files + filename: string; // the module's filename end; +var + gInstTypes: TIdTable; // map PType to PType + function newContext(module: PSym; const nimfile: string): PContext; function newProcCon(owner: PSym): PProcCon; @@ -164,6 +169,7 @@ begin result.generics := newNode(nkStmtList); {@emit result.converters := @[];} result.filename := nimfile; + IntSetInit(result.includedFiles); end; procedure addConverter(c: PContext; conv: PSym); @@ -255,4 +261,6 @@ begin if (n = nil) or (sonsLen(n) < len) then illFormedAst(n); end; +initialization + initIdTable(gInstTypes); end. diff --git a/nim/semexprs.pas b/nim/semexprs.pas index de37295b7..2fd0d6843 100644..100755 --- a/nim/semexprs.pas +++ b/nim/semexprs.pas @@ -10,6 +10,17 @@ // this module does the semantic checking for expressions +function semTemplateExpr(c: PContext; n: PNode; s: PSym; + semCheck: bool = true): PNode; +begin + include(s.flags, sfUsed); + pushInfoContext(n.info); + result := evalTemplate(c, n, s); + if semCheck then + result := semAfterMacroCall(c, result, s); + popInfoContext(); +end; + function semDotExpr(c: PContext; n: PNode; flags: TExprFlags = {@set}[]): PNode; forward; @@ -79,8 +90,8 @@ begin // we use d, s here to speed up that operation a bit: case cmpTypes(d, s) of isNone, isGeneric: begin - if not equalOrAbstractOf(castDest, src) and - not equalOrAbstractOf(src, castDest) then + if not equalOrDistinctOf(castDest, src) and + not equalOrDistinctOf(src, castDest) then liMessage(info, errGenerated, format(MsgKindToString(errIllegalConvFromXtoY), [typeToString(src), typeToString(castDest)])); @@ -457,15 +468,21 @@ begin n.sons[i] := analyseIfAddressTaken(c, n.sons[i]); end; -function semDirectCallAnalyseEffects(c: PContext; n: PNode): PNode; +function semDirectCallAnalyseEffects(c: PContext; n: PNode; + flags: TExprFlags): PNode; var callee: PSym; begin - result := semDirectCall(c, n); + if not (efWantIterator in flags) then + result := semDirectCall(c, n, {@set}[skProc, skConverter]) + else + result := semDirectCall(c, n, {@set}[skIterator]); if result <> nil then begin if result.sons[0].kind <> nkSym then InternalError('semDirectCallAnalyseEffects'); callee := result.sons[0].sym; + if (callee.kind = skIterator) and (callee.id = c.p.owner.id) then + liMessage(n.info, errRecursiveDependencyX, callee.name.s); if not (sfNoSideEffect in callee.flags) then if (sfForward in callee.flags) or ([sfImportc, sfSideEffect] * callee.flags <> []) then @@ -473,12 +490,13 @@ begin end end; -function semIndirectOp(c: PContext; n: PNode): PNode; +function semIndirectOp(c: PContext; n: PNode; flags: TExprFlags): PNode; var m: TCandidate; msg: string; i: int; prc: PNode; + t: PType; begin result := nil; prc := n.sons[0]; @@ -496,13 +514,12 @@ begin end end; else n.sons[0] := semExpr(c, n.sons[0]); - end; - if n.sons[0].typ = nil then - liMessage(n.sons[0].info, errExprXHasNoType, - renderTree(n.sons[0], {@set}[renderNoComments])); + end; semOpAux(c, n); - if (n.sons[0].typ <> nil) and (n.sons[0].typ.kind = tyProc) then begin - initCandidate(m, n.sons[0].typ); + if (n.sons[0].typ <> nil) then t := skipTypes(n.sons[0].typ, abstractInst) + else t := nil; + if (t <> nil) and (t.kind = tyProc) then begin + initCandidate(m, t); matches(c, n, m); if m.state <> csMatch then begin msg := msgKindToString(errTypeMismatch); @@ -519,7 +536,8 @@ begin result := m.call; // we assume that a procedure that calls something indirectly // has side-effects: - include(c.p.owner.flags, sfSideEffect); + if not (tfNoSideEffect in t.flags) then + include(c.p.owner.flags, sfSideEffect); end else begin result := overloadedCallOpr(c, n); @@ -527,7 +545,7 @@ begin // 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); + result := semDirectCallAnalyseEffects(c, n, flags); end; if result = nil then liMessage(n.info, errExprXCannotBeCalled, @@ -537,11 +555,11 @@ begin analyseIfAddressTakenInCall(c, result); end; -function semDirectOp(c: PContext; n: PNode): PNode; +function semDirectOp(c: PContext; n: PNode; flags: TExprFlags): PNode; begin // this seems to be a hotspot in the compiler! semOpAux(c, n); - result := semDirectCallAnalyseEffects(c, n); + result := semDirectCallAnalyseEffects(c, n, flags); if result = nil then begin result := overloadedCallOpr(c, n); if result = nil then @@ -624,18 +642,19 @@ begin n.sons[0].info := n.info; end; -function semMagic(c: PContext; n: PNode; s: PSym): PNode; +function semMagic(c: PContext; n: PNode; s: PSym; flags: TExprFlags): PNode; // this is a hotspot in the compiler! begin result := n; case s.magic of // magics that need special treatment mDefined: result := semDefined(c, setMs(n, s)); + mDefinedInScope: result := semDefinedInScope(c, setMs(n, s)); mLow: result := semLowHigh(c, setMs(n, s), mLow); mHigh: result := semLowHigh(c, setMs(n, s), mHigh); mSizeOf: result := semSizeof(c, setMs(n, s)); mIs: result := semIs(c, setMs(n, s)); mEcho: result := semEcho(c, setMs(n, s)); - else result := semDirectOp(c, n); + else result := semDirectOp(c, n, flags); end; end; @@ -644,67 +663,6 @@ begin if sfDeprecated in s.flags then liMessage(n.info, warnDeprecated, s.name.s); end; -function semSym(c: PContext; n: PNode; s: PSym; flags: TExprFlags): PNode; -begin - if (s.kind = skType) and not (efAllowType in flags) then - liMessage(n.info, errATypeHasNoValue); - case s.kind of - 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:: - const x = [] - proc p(a: openarray[int], i: int) - proc q(a: openarray[char], c: char) - p(x, 0) - q(x, '\0') - - It is clear that ``[]`` means two totally different things. Thus, we - 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; - skTemplate: begin - include(s.flags, sfUsed); - // Templates and macros can be invoked without ``()`` - pushInfoContext(n.info); - result := evalTemplate(c, n, s); - popInfoContext(); - 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; - function isTypeExpr(n: PNode): bool; begin case n.kind of @@ -797,12 +755,12 @@ var t: PType; a: PNode; begin - t := n.typ; + t := skipTypes(n.typ, {@set}[tyGenericInst]); result := n; if t.kind = tyVar then begin result := newNodeIT(nkHiddenDeref, n.info, t.sons[0]); addSon(result, n); - t := t.sons[0]; + t := skipTypes(t.sons[0], {@set}[tyGenericInst]); end; if t.kind in [tyPtr, tyRef] then begin a := result; @@ -830,7 +788,7 @@ begin // look up if the identifier belongs to the enum: while (ty <> nil) do begin f := getSymFromList(ty.n, i); - if f <> nil then breaK; + if f <> nil then break; ty := ty.sons[0]; // enum inheritance end; if f <> nil then begin @@ -891,7 +849,7 @@ begin // --> replace("", ...) f := SymTabGet(c.tab, i); //if (f <> nil) and (f.kind = skStub) then loadStub(f); - // XXX ``loadStub`` is not correct here as we don't care for ``f`` really + // ``loadStub`` is not correct here as we don't care for ``f`` really if (f <> nil) then begin // BUGFIX: do not check for (f.kind in [skProc, skIterator]) here result := newNodeI(nkDotCall, n.info); @@ -1168,24 +1126,13 @@ begin Dec(c.p.nestedBlockCounter); end; -function semDotExpr(c: PContext; n: PNode; flags: TExprFlags): PNode; -var - s: PSym; -begin - s := qualifiedLookup(c, n, true); // check for ambiguity - if s <> nil then - result := semSym(c, n, s, flags) - else - // this is a test comment; please don't touch it - result := semFieldAccess(c, n, flags); -end; - function isCallExpr(n: PNode): bool; begin - result := n.kind in [nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand]; + result := n.kind in [nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, + nkCallStrLit]; end; -function semMacroStmt(c: PContext; n: PNode): PNode; +function semMacroStmt(c: PContext; n: PNode; semCheck: bool = true): PNode; var s: PSym; a: PNode; @@ -1200,9 +1147,8 @@ begin if (s <> nil) then begin checkDeprecated(n, s); case s.kind of - skMacro: result := semMacroExpr(c, n, s); + skMacro: result := semMacroExpr(c, n, s, semCheck); skTemplate: begin - include(s.flags, sfUsed); // transform // nkMacroStmt(nkCall(a...), stmt, b...) // to @@ -1213,11 +1159,8 @@ begin for i := 1 to sonsLen(n.sons[0])-1 do addSon(result, n.sons[0].sons[i]); end; - for i := 1 to sonsLen(n)-1 do - addSon(result, n.sons[i]); - pushInfoContext(n.info); - result := evalTemplate(c, result, s); - popInfoContext(); + for i := 1 to sonsLen(n)-1 do addSon(result, n.sons[i]); + result := semTemplateExpr(c, result, s, semCheck); end; else liMessage(n.info, errXisNoMacroOrTemplate, s.name.s); @@ -1228,9 +1171,78 @@ begin renderTree(a, {@set}[renderNoComments])); end; +function semSym(c: PContext; n: PNode; s: PSym; flags: TExprFlags): PNode; +begin + if (s.kind = skType) and not (efAllowType in flags) then + liMessage(n.info, errATypeHasNoValue); + case s.kind of + 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:: + const x = [] + proc p(a: openarray[int]) + proc q(a: openarray[char]) + p(x) + q(x) + + It is clear that ``[]`` means two totally different things. Thus, we + 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: result := semMacroExpr(c, n, s); + skTemplate: result := semTemplateExpr(c, n, s); + 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; + skGenericParam: begin + if s.ast = nil then InternalError(n.info, 'no default for'); + result := semExpr(c, s.ast); + end + else begin + include(s.flags, sfUsed); + result := newSymNode(s); + result.info := n.info; + end + end; + checkDeprecated(n, s); +end; + +function semDotExpr(c: PContext; n: PNode; flags: TExprFlags): PNode; +var + s: PSym; +begin + s := qualifiedLookup(c, n, true); // check for ambiguity + if s <> nil then + result := semSym(c, n, s, flags) + else + // this is a test comment; please don't touch it + result := semFieldAccess(c, n, flags); +end; + function semExpr(c: PContext; n: PNode; flags: TExprFlags = {@set}[]): PNode; var s: PSym; + t: PType; begin result := n; if n = nil then exit; @@ -1242,13 +1254,16 @@ begin result := semSym(c, n, s, flags); end; nkSym: begin - s := n.sym; + (*s := n.sym; include(s.flags, sfUsed); if (s.kind = skType) and not (efAllowType in flags) then liMessage(n.info, errATypeHasNoValue); if (s.magic <> mNone) and (s.kind in [skProc, skIterator, skConverter]) then - liMessage(n.info, errInvalidContextForBuiltinX, s.name.s); + liMessage(n.info, errInvalidContextForBuiltinX, s.name.s); *) + // because of the changed symbol binding, this does not mean that we + // don't have to check the symbol for semantics here again! + result := semSym(c, n, n.sym, flags); end; nkEmpty, nkNone: begin end; nkNilLit: result.typ := getSysType(tyNil); @@ -1276,7 +1291,7 @@ begin end; end; nkBind: result := semExpr(c, n.sons[0], flags); - nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand: begin + nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, nkCallStrLit: begin // check if it is an expression macro: checkMinSonsLen(n, 1); s := qualifiedLookup(c, n.sons[0], false); @@ -1284,26 +1299,28 @@ begin checkDeprecated(n, s); case s.kind of skMacro: result := semMacroExpr(c, n, s); - skTemplate: begin - include(s.flags, sfUsed); - pushInfoContext(n.info); - result := evalTemplate(c, n, s); - popInfoContext(); - end; + skTemplate: result := semTemplateExpr(c, n, s); skType: begin include(s.flags, sfUsed); if n.kind <> nkCall then liMessage(n.info, errXisNotCallable, s.name.s); + // XXX does this check make any sense? result := semConv(c, n, s); end; skProc, skConverter, skIterator: begin - if s.magic = mNone then result := semDirectOp(c, n) - else result := semMagic(c, n, s); + if s.magic = mNone then result := semDirectOp(c, n, flags) + else result := semMagic(c, n, s, flags); end; - else result := semIndirectOp(c, n) + else begin + //liMessage(n.info, warnUser, renderTree(n)); + result := semIndirectOp(c, n, flags) + end end end - else result := semIndirectOp(c, n); + else if n.sons[0].kind = nkSymChoice then + result := semDirectOp(c, n, flags) + else + result := semIndirectOp(c, n, flags); end; nkMacroStmt: begin result := semMacroStmt(c, n); @@ -1341,8 +1358,9 @@ begin checkSonsLen(n, 1); n.sons[0] := semExprWithType(c, n.sons[0]); result := n; - case skipTypes(n.sons[0].typ, {@set}[tyGenericInst, tyVar]).kind of - tyRef, tyPtr: n.typ := n.sons[0].typ.sons[0]; + t := skipTypes(n.sons[0].typ, {@set}[tyGenericInst, tyVar]); + case t.kind of + tyRef, tyPtr: n.typ := t.sons[0]; else liMessage(n.sons[0].info, errCircumNeedsPointer); end; result := n; diff --git a/nim/semfold.pas b/nim/semfold.pas index 556dabe9b..acca84c71 100644..100755 --- a/nim/semfold.pas +++ b/nim/semfold.pas @@ -417,7 +417,7 @@ begin end; nkCharLit..nkNilLit: result := copyNode(n); nkIfExpr: result := getConstIfExpr(module, n); - nkCall, nkCommand: begin + nkCall, nkCommand, nkCallStrLit: begin if (n.sons[0].kind <> nkSym) then exit; s := n.sons[0].sym; if (s.kind <> skProc) then exit; diff --git a/nim/seminst.pas b/nim/seminst.pas index a49d8478e..6a6f272de 100644..100755 --- a/nim/seminst.pas +++ b/nim/seminst.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. @@ -10,102 +10,50 @@ // This module does the instantiation of generic procs and types. function generateInstance(c: PContext; fn: PSym; const pt: TIdTable; - const instantiator: TLineInfo): PSym; forward; + const info: TLineInfo): PSym; forward; // generates an instantiated proc -type - TInstantiateClosure = object(NObject) - typeMap: TIdTable; // map PType to PType - symMap: TIdTable; // map PSym to PSym - fn: PSym; - module: PSym; - //newOwner: PSym; - instantiator: TLineInfo; - end; - PInstantiateClosure = ^TInstantiateClosure; - PInstClosure = PInstantiateClosure; - -function instantiateTree(c: PInstantiateClosure; t: PNode): PNode; forward; -function instantiateSym(c: PInstantiateClosure; sym: PSym): PSym; forward; -function instantiateType(c: PInstantiateClosure; typ: PType): PType; forward; - -function containsGenericTypeIter(t: PType; closure: PObject): bool; -begin - result := t.kind in GenericTypes; -end; - -function containsGenericType(t: PType): bool; -begin - result := iterOverType(t, containsGenericTypeIter, nil); -end; -function instTypeNode(c: PInstantiateClosure; n: PNode): PNode; +function searchInstTypes(const tab: TIdTable; key: PType): PType; var - i: int; -begin - result := nil; - if n <> nil then begin - result := copyNode(n); - result.typ := instantiateType(c, n.typ); - case n.kind of - nkNone..nkNilLit: begin // a leaf - end; - else begin - for i := 0 to sonsLen(n)-1 do - addSon(result, instTypeNode(c, n.sons[i])); + t: PType; + h: THash; + j: int; + match: bool; +begin // returns nil if we need to declare this type + result := PType(IdTableGet(tab, key)); + if (result = nil) and (tab.counter > 0) then begin + // we have to do a slow linear search because types may need + // to be compared by their structure: + for h := 0 to high(tab.data) do begin + t := PType(tab.data[h].key); + if t <> nil then begin + if key.containerId = t.containerID then begin + match := true; + for j := 0 to sonsLen(t) - 1 do begin + // XXX sameType is not really correct for nested generics? + if not sameType(t.sons[j], key.sons[j]) then begin + match := false; break + end + end; + if match then begin result := PType(tab.data[h].val); exit end; + end end end end end; -procedure genericToConcreteTypeKind(t: PType); -var - body: PNode; +function containsGenericTypeIter(t: PType; closure: PObject): bool; begin - if (t.kind = tyGeneric) and (t.sym <> nil) then begin - body := t.sym.ast.sons[2]; - case body.kind of - nkObjectTy: t.kind := tyObject; - nkTupleTy: t.kind := tyTuple; - nkRefTy: t.kind := tyRef; - nkPtrTy: t.kind := tyPtr; - nkVarTy: t.kind := tyVar; - nkProcTy: t.kind := tyProc; - else InternalError('genericToConcreteTypeKind'); - end - end + result := t.kind in GenericTypes; end; -function instantiateType(c: PInstantiateClosure; typ: PType): PType; -var - i: int; +function containsGenericType(t: PType): bool; begin - if typ = nil then begin result := nil; exit end; - result := PType(idTableGet(c.typeMap, typ)); - if result <> nil then exit; - //if typ.kind = tyOpenArray then - // liMessage(c.instantiator, warnUser, 'instantiating type for: openarray'); - if containsGenericType(typ) then begin - result := copyType(typ, typ.owner, false); - idTablePut(c.typeMap, typ, result); // to avoid cycles - for i := 0 to sonsLen(result)-1 do - result.sons[i] := instantiateType(c, result.sons[i]); - if result.n <> nil then - result.n := instTypeNode(c, result.n); - genericToConcreteTypeKind(result); - end - else - result := typ; - if result.Kind in GenericTypes then begin - liMessage(c.instantiator, errCannotInstantiateX, - TypeToString(typ, preferName)); - end - else if result.kind = tyVar then begin - if result.sons[0].kind = tyVar then - liMessage(c.instantiator, errVarVarTypeNotAllowed); - end; + result := iterOverType(t, containsGenericTypeIter, nil); end; +(* function instantiateSym(c: PInstantiateClosure; sym: PSym): PSym; begin if sym = nil then begin result := nil; exit end; // BUGFIX @@ -128,56 +76,31 @@ begin result := sym // do not copy t! end end; +*) -function instantiateTree(c: PInstantiateClosure; t: PNode): PNode; -var - len, i: int; -begin - if t = nil then begin result := nil; exit end; - result := copyNode(t); - if result.typ <> nil then result.typ := instantiateType(c, result.typ); - case t.kind of - nkNone..pred(nkSym), succ(nkSym)..nkNilLit: begin end; - nkSym: begin - if result.sym <> nil then result.sym := instantiateSym(c, result.sym); - end - else begin - len := sonsLen(t); - if len > 0 then begin - newSons(result, len); - for i := 0 to len-1 do - result.sons[i] := instantiateTree(c, t.sons[i]); - end - end - end -end; - -procedure instantiateGenericParamList(c: PContext; n: PNode; - const pt: TIdTable); +procedure instantiateGenericParamList(c: PContext; n: PNode; const pt: TIdTable); var i: int; s, q: PSym; t: PType; + a: PNode; begin if (n.kind <> nkGenericParams) then - InternalError(n.info, 'instantiateGenericParamList'); + InternalError(n.info, 'instantiateGenericParamList; no generic params'); for i := 0 to sonsLen(n)-1 do begin - if n.sons[i].kind = nkDefaultTypeParam then begin - internalError(n.sons[i].info, - 'instantiateGenericParamList() to implement'); - // XXX - end; - if (n.sons[i].kind <> nkSym) then - InternalError(n.info, 'instantiateGenericParamList'); - q := n.sons[i].sym; + a := n.sons[i]; + if a.kind <> nkSym then + InternalError(a.info, 'instantiateGenericParamList; no symbol'); + q := a.sym; + if not (q.typ.kind in [tyTypeDesc, tyGenericParam]) then continue; s := newSym(skType, q.name, getCurrOwner()); t := PType(IdTableGet(pt, q.typ)); - if t = nil then - liMessage(n.sons[i].info, errCannotInstantiateX, s.name.s); - if (t.kind = tyGenericParam) then - InternalError(n.info, 'instantiateGenericParamList'); + if t = nil then liMessage(a.info, errCannotInstantiateX, s.name.s); + if (t.kind = tyGenericParam) then begin + InternalError(a.info, 'instantiateGenericParamList: ' + q.name.s); + end; s.typ := t; - addDecl(c, s); + addDecl(c, s) end end; @@ -212,25 +135,24 @@ begin addSon(c.generics, n); end; -procedure semParamList(c: PContext; n: PNode; s: PSym); forward; -procedure addParams(c: PContext; n: PNode); forward; -procedure addResult(c: PContext; t: PType; const info: TLineInfo); forward; -procedure addResultNode(c: PContext; n: PNode); forward; - function generateInstance(c: PContext; fn: PSym; const pt: TIdTable; - const instantiator: TLineInfo): PSym; + const info: TLineInfo): PSym; // generates an instantiated proc var - oldPrc: PSym; + oldPrc, oldMod: PSym; oldP: PProcCon; n: PNode; begin + if c.InstCounter > 1000 then InternalError(fn.ast.info, 'nesting too deep'); + inc(c.InstCounter); oldP := c.p; // restore later + // NOTE: for access of private fields within generics from a different module + // and other identifiers we fake the current module temporarily! + oldMod := c.module; + c.module := getModule(fn); result := copySym(fn, false); include(result.flags, sfFromGeneric); - //include(fn.flags, sfFromGeneric); result.owner := getCurrOwner().owner; - //idTablePut(c.mapping, fn, result); n := copyTree(fn.ast); result.ast := n; pushOwner(result); @@ -238,13 +160,13 @@ begin if (n.sons[genericParamsPos] = nil) then InternalError(n.info, 'generateInstance'); n.sons[namePos] := newSymNode(result); - pushInfoContext(instantiator); + pushInfoContext(info); instantiateGenericParamList(c, n.sons[genericParamsPos], pt); n.sons[genericParamsPos] := nil; // semantic checking for the parameters: if n.sons[paramsPos] <> nil then begin - semParamList(c, n.sons[ParamsPos], result); + semParamList(c, n.sons[ParamsPos], nil, result); addParams(c, result.typ.n); end else begin @@ -256,6 +178,7 @@ begin oldPrc := GenericCacheGet(c, fn, result); if oldPrc = nil then begin // add it here, so that recursive generic procs are possible: + GenericCacheAdd(c, fn, result); addDecl(c, result); if n.sons[codePos] <> nil then begin c.p := newProcCon(result); @@ -264,8 +187,7 @@ begin addResultNode(c, n); end; n.sons[codePos] := semStmtScope(c, n.sons[codePos]); - end; - GenericCacheAdd(c, fn, result); + end end else result := oldPrc; @@ -273,37 +195,168 @@ begin closeScope(c.tab); // close scope for parameters popOwner(); c.p := oldP; // restore + c.module := oldMod; + dec(c.InstCounter); end; -function generateTypeInstance(p: PContext; const pt: TIdTable; - const instantiator: TLineInfo; t: PType): PType; +procedure checkConstructedType(const info: TLineInfo; t: PType); +begin + if (tfAcyclic in t.flags) + and (skipTypes(t, abstractInst).kind <> tyObject) then + liMessage(info, errInvalidPragmaX, 'acyclic'); + if computeSize(t) < 0 then + liMessage(info, errIllegalRecursionInTypeX, typeToString(t)); + if (t.kind = tyVar) and (t.sons[0].kind = tyVar) then + liMessage(info, errVarVarTypeNotAllowed); +end; + +type + TReplTypeVars = record + c: PContext; + typeMap: TIdTable; // map PType to PType + symMap: TIdTable; // map PSym to PSym + info: TLineInfo; + end; + +function ReplaceTypeVarsT(var cl: TReplTypeVars; t: PType): PType; forward; +function ReplaceTypeVarsS(var cl: TReplTypeVars; s: PSym): PSym; forward; + +function ReplaceTypeVarsN(var cl: TReplTypeVars; n: PNode): PNode; var - c: PInstantiateClosure; + i, Len: int; begin - new(c); -{@ignore} - fillChar(c^, sizeof(c^), 0); -{@emit} - copyIdTable(c.typeMap, pt); - InitIdTable(c.symMap); - c.fn := nil; - c.instantiator := instantiator; - c.module := p.module; - result := instantiateType(c, t); + result := nil; + if n <> nil then begin + result := copyNode(n); + result.typ := ReplaceTypeVarsT(cl, n.typ); + case n.kind of + nkNone..pred(nkSym), succ(nkSym)..nkNilLit: begin end; + nkSym: begin + result.sym := ReplaceTypeVarsS(cl, n.sym); + end; + else begin + len := sonsLen(n); + if len > 0 then begin + newSons(result, len); + for i := 0 to len-1 do + result.sons[i] := ReplaceTypeVarsN(cl, n.sons[i]); + end + end + end + end end; -function newInstantiateClosure(p: PContext; - const instantiator: TLineInfo): PInstantiateClosure; +function ReplaceTypeVarsS(var cl: TReplTypeVars; s: PSym): PSym; begin - new(result); -{@ignore} - fillChar(result^, sizeof(result^), 0); -{@emit} - InitIdTable(result.typeMap); - InitIdTable(result.symMap); - result.fn := nil; - result.instantiator := instantiator; - result.module := p.module; + if s = nil then begin result := nil; exit end; + result := PSym(idTableGet(cl.symMap, s)); + if (result = nil) then begin + result := copySym(s, false); + include(result.flags, sfFromGeneric); + idTablePut(cl.symMap, s, result); + result.typ := ReplaceTypeVarsT(cl, s.typ); + result.owner := s.owner; + result.ast := ReplaceTypeVarsN(cl, s.ast); + end +end; + +function lookupTypeVar(cl: TReplTypeVars; t: PType): PType; +begin + result := PType(idTableGet(cl.typeMap, t)); + if result = nil then + liMessage(t.sym.info, errCannotInstantiateX, typeToString(t)) + else if result.kind = tyGenericParam then + InternalError(cl.info, 'substitution with generic parameter'); +end; + +function ReplaceTypeVarsT(var cl: TReplTypeVars; t: PType): PType; +var + i: int; + body, newbody, x, header: PType; +begin + result := t; + if t = nil then exit; + case t.kind of + tyGenericParam: begin + result := lookupTypeVar(cl, t); + end; + tyGenericInvokation: begin + body := t.sons[0]; + if body.kind <> tyGenericBody then + InternalError(cl.info, 'no generic body'); + header := nil; + for i := 1 to sonsLen(t)-1 do begin + if t.sons[i].kind = tyGenericParam then begin + x := lookupTypeVar(cl, t.sons[i]); + if header = nil then header := copyType(t, t.owner, false); + header.sons[i] := x; + end + else + x := t.sons[i]; + idTablePut(cl.typeMap, body.sons[i-1], x); + end; + // cycle detection: + if header = nil then header := t; + result := searchInstTypes(gInstTypes, header); + if result <> nil then exit; + + result := newType(tyGenericInst, t.sons[0].owner); + for i := 0 to sonsLen(t)-1 do begin + // if one of the params is not concrete, we cannot do anything + // but we already raised an error! + addSon(result, header.sons[i]); + end; + // add these before recursive calls: + idTablePut(gInstTypes, header, result); + + newbody := ReplaceTypeVarsT(cl, lastSon(body)); + newbody.n := ReplaceTypeVarsN(cl, lastSon(body).n); + addSon(result, newbody); + //writeln(output, ropeToStr(Typetoyaml(newbody))); + checkConstructedType(cl.info, newbody); + end; + tyGenericBody: begin + InternalError(cl.info, 'ReplaceTypeVarsT: tyGenericBody'); + result := ReplaceTypeVarsT(cl, lastSon(t)); + end + else begin + if containsGenericType(t) then begin + result := copyType(t, t.owner, false); + for i := 0 to sonsLen(result)-1 do + result.sons[i] := ReplaceTypeVarsT(cl, result.sons[i]); + result.n := ReplaceTypeVarsN(cl, result.n); + if result.Kind in GenericTypes then + liMessage(cl.info, errCannotInstantiateX, TypeToString(t, preferName)); + //writeln(output, ropeToStr(Typetoyaml(result))); + //checkConstructedType(cl.info, result); + end + end + end +end; + +function instGenericContainer(c: PContext; n: PNode; header: PType): PType; +var + cl: TReplTypeVars; +begin + InitIdTable(cl.symMap); + InitIdTable(cl.typeMap); + cl.info := n.info; + cl.c := c; + result := ReplaceTypeVarsT(cl, header); +end; + +function generateTypeInstance(p: PContext; const pt: TIdTable; + arg: PNode; t: PType): PType; +var + cl: TReplTypeVars; +begin + InitIdTable(cl.symMap); + copyIdTable(cl.typeMap, pt); + cl.info := arg.info; + cl.c := p; + pushInfoContext(arg.info); + result := ReplaceTypeVarsT(cl, t); + popInfoContext(); end; function partialSpecialization(c: PContext; n: PNode; s: PSym): PNode; diff --git a/nim/semstmts.pas b/nim/semstmts.pas index 686ff775d..efbee6da8 100644..100755 --- a/nim/semstmts.pas +++ b/nim/semstmts.pas @@ -9,11 +9,6 @@ // this module does the semantic checking of statements -function isTopLevel(c: PContext): bool; -begin - result := c.tab.tos <= 2 -end; - function semWhen(c: PContext; n: PNode): PNode; var i: int; @@ -71,7 +66,7 @@ begin end; else illFormedAst(n) end - end; + end end; function semDiscard(c: PContext; n: PNode): PNode; @@ -90,19 +85,19 @@ begin result := n; checkSonsLen(n, 1); if n.sons[0] <> nil then begin - if n.sons[0].kind = nkIdent then begin - // lookup the symbol: - s := lookUp(c, n.sons[0]); - if (s.kind = skLabel) and (s.owner.id = c.p.owner.id) then begin - x := newSymNode(s); - x.info := n.info; - include(s.flags, sfUsed); - n.sons[0] := x - end - else - liMessage(n.info, errInvalidControlFlowX, s.name.s) + case n.sons[0].kind of + nkIdent: s := lookUp(c, n.sons[0]); + nkSym: s := n.sons[0].sym; + else illFormedAst(n) + end; + if (s.kind = skLabel) and (s.owner.id = c.p.owner.id) then begin + x := newSymNode(s); + x.info := n.info; + include(s.flags, sfUsed); + n.sons[0] := x end - else illFormedAst(n) + else + liMessage(n.info, errInvalidControlFlowX, s.name.s) end else if (c.p.nestedLoopCounter <= 0) and (c.p.nestedBlockCounter <= 0) then liMessage(n.info, errInvalidControlFlowX, @@ -257,7 +252,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 := semDirectCallAnalyseEffects(c, result); + result := semDirectCallAnalyseEffects(c, result, {@set}[]); if result <> nil then begin fixAbstractType(c, result); analyseIfAddressTakenInCall(c, result); @@ -277,7 +272,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 := semDirectCallAnalyseEffects(c, result); + result := semDirectCallAnalyseEffects(c, result, {@set}[]); if result <> nil then begin fixAbstractType(c, result); analyseIfAddressTakenInCall(c, result); @@ -289,7 +284,7 @@ begin addSon(result, semExpr(c, a.sons[0])); addSon(result, semExpr(c, a.sons[1])); addSon(result, semExpr(c, n.sons[1])); - result := semDirectCallAnalyseEffects(c, result); + result := semDirectCallAnalyseEffects(c, result, {@set}[]); if result <> nil then begin fixAbstractType(c, result); analyseIfAddressTakenInCall(c, result); @@ -355,8 +350,7 @@ var begin result := n; checkSonsLen(n, 1); - if (c.p.owner = nil) or (c.p.owner.kind <> skIterator) - or (c.p.nestedLoopCounter <= 0) then + if (c.p.owner = nil) or (c.p.owner.kind <> skIterator) then liMessage(n.info, errYieldNotAllowedHere); if (n.sons[0] <> nil) then begin n.sons[0] := SemExprWithType(c, n.sons[0]); @@ -409,13 +403,20 @@ begin end else def := nil; - if not typeAllowed(typ, skVar) then + if not typeAllowed(typ, skVar) then begin + //debug(typ); liMessage(a.info, errXisNoType, typeToString(typ)); + end; tup := skipTypes(typ, {@set}[tyGenericInst]); if a.kind = nkVarTuple then begin if tup.kind <> tyTuple then liMessage(a.info, errXExpected, 'tuple'); if len-2 <> sonsLen(tup) then liMessage(a.info, errWrongNumberOfVariables); + b := newNodeI(nkVarTuple, a.info); + newSons(b, len); + b.sons[len-2] := nil; // no type desc + b.sons[len-1] := def; + addSon(result, b); end; for j := 0 to len-3 do begin if (c.p.owner.kind = skModule) then begin @@ -424,16 +425,21 @@ begin end else v := semIdentWithPragma(c, skVar, a.sons[j], {@set}[]); - if a.kind <> nkVarTuple then v.typ := typ - else v.typ := tup.sons[j]; if v.flags * [sfStar, sfMinus] <> {@set}[] then include(v.flags, sfInInterface); addInterfaceDecl(c, v); - b := newNodeI(nkIdentDefs, a.info); - addSon(b, newSymNode(v)); - addSon(b, nil); // no type description - addSon(b, copyTree(def)); - addSon(result, b); + if a.kind <> nkVarTuple then begin + v.typ := typ; + b := newNodeI(nkIdentDefs, a.info); + addSon(b, newSymNode(v)); + addSon(b, nil); // no type description + addSon(b, copyTree(def)); + addSon(result, b); + end + else begin + v.typ := tup.sons[j]; + b.sons[j] := newSymNode(v); + end end end end; @@ -485,9 +491,9 @@ end; function semFor(c: PContext; n: PNode): PNode; var i, len: int; - v: PSym; + v, countup: PSym; iter: PType; - countupNode, m: PNode; + countupNode, call: PNode; begin result := n; checkMinSonsLen(n, 3); @@ -496,22 +502,22 @@ begin if n.sons[len-2].kind = nkRange then begin checkSonsLen(n.sons[len-2], 2); // convert ``in 3..5`` to ``in countup(3, 5)`` - // YYY: if the programmer overrides system.countup in a local scope - // this leads to wrong code. This is extremely hard to fix! But it may - // not even be a bug, but a feature... - countupNode := newNodeI(nkCall, n.sons[len-2].info); + countupNode := newNodeI(nkCall, n.sons[len-2].info); + countUp := StrTableGet(magicsys.systemModule.Tab, getIdent('countup')); + if (countUp = nil) then + liMessage(countupNode.info, errSystemNeeds, 'countup'); newSons(countupNode, 3); - countupNode.sons[0] := newNodeI(nkQualified, n.sons[len-2].info); - newSons(countupNode.sons[0], 2); - m := newIdentNode(getIdent('system'), n.sons[len-2].info); - countupNode.sons[0].sons[0] := m; - m := newIdentNode(getIdent('countup'), n.sons[len-2].info); - countupNode.sons[0].sons[1] := m; + countupnode.sons[0] := newSymNode(countup); countupNode.sons[1] := n.sons[len-2].sons[0]; countupNode.sons[2] := n.sons[len-2].sons[1]; + n.sons[len-2] := countupNode; end; - n.sons[len-2] := semExprWithType(c, n.sons[len-2]); + n.sons[len-2] := semExprWithType(c, n.sons[len-2], {@set}[efWantIterator]); + call := n.sons[len-2]; + if (call.kind <> nkCall) or (call.sons[0].kind <> nkSym) + or (call.sons[0].sym.kind <> skIterator) then + liMessage(n.sons[len-2].info, errIteratorExpected); iter := skipTypes(n.sons[len-2].typ, {@set}[tyGenericInst]); if iter.kind <> tyTuple then begin if len <> 3 then liMessage(n.info, errWrongNumberOfVariables); @@ -521,8 +527,7 @@ begin addDecl(c, v); end else begin - if len-2 <> sonsLen(iter) then - liMessage(n.info, errWrongNumberOfVariables); + if len-2 <> sonsLen(iter) then liMessage(n.info, errWrongNumberOfVariables); for i := 0 to len-3 do begin v := newSymS(skForVar, n.sons[i], c); v.typ := iter.sons[i]; @@ -585,66 +590,57 @@ begin end; end; -procedure semGenericParamList(c: PContext; n: PNode; father: PType = nil); +function semGenericParamList(c: PContext; n: PNode; father: PType = nil): PNode; var - i: int; + i, j, L: int; s: PSym; + a, def: PNode; + typ: PType; begin + result := copyNode(n); if n.kind <> nkGenericParams then InternalError(n.info, 'semGenericParamList'); for i := 0 to sonsLen(n)-1 do begin - if n.sons[i].kind = nkDefaultTypeParam then begin - internalError(n.sons[i].info, 'semGenericParamList() to implement'); - // XXX - end - else begin - s := newSymS(skTypeParam, n.sons[i], c); - s.typ := newTypeS(tyGenericParam, c); + a := n.sons[i]; + if a.kind <> nkIdentDefs then illFormedAst(n); + L := sonsLen(a); + def := a.sons[L-1]; + if a.sons[L-2] <> nil then + typ := semTypeNode(c, a.sons[L-2], nil) + else if def <> nil then + typ := newTypeS(tyExpr, c) + else + typ := nil; + for j := 0 to L-3 do begin + if (typ = nil) or (typ.kind = tyTypeDesc) then begin + s := newSymS(skType, a.sons[j], c); + s.typ := newTypeS(tyGenericParam, c) + end + else begin + s := newSymS(skGenericParam, a.sons[j], c); + s.typ := typ + end; + s.ast := def; s.typ.sym := s; - end; - if father <> nil then addSon(father, s.typ); - s.position := i; - n.sons[i] := newSymNode(s); - addDecl(c, s); + if father <> nil then addSon(father, s.typ); + s.position := i; + addSon(result, newSymNode(s)); + addDecl(c, s); + end end end; procedure addGenericParamListToScope(c: PContext; n: PNode); var i: int; - s: PSym; + a: PNode; begin if n.kind <> nkGenericParams then InternalError(n.info, 'addGenericParamListToScope'); for i := 0 to sonsLen(n)-1 do begin - if n.sons[i].kind <> nkSym then - InternalError(n.sons[i].info, 'addGenericParamListToScope'); - s := n.sons[i].sym; - addDecl(c, s); - end -end; - -function resolveGenericParams(c: PContext; n: PNode; - withinBind: bool = false): PNode; -var - i: int; - s: PSym; -begin - 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 + a := n.sons[i]; + if a.kind <> nkSym then internalError(a.info, 'addGenericParamListToScope'); + addDecl(c, a.sym) end end; @@ -652,7 +648,7 @@ function SemTypeSection(c: PContext; n: PNode): PNode; var i: int; s: PSym; - t: PType; + t, body: PType; a: PNode; begin result := n; @@ -674,7 +670,8 @@ begin s.typ := newTypeS(tyForward, c); s.typ.sym := s; // process pragmas: - if a.sons[0].kind = nkPragmaExpr then pragmaType(c, s, a.sons[0].sons[1]); + if a.sons[0].kind = nkPragmaExpr then + pragma(c, s, a.sons[0].sons[1], typePragmas); // add it here, so that recursive types are possible: addInterfaceDecl(c, s); a.sons[0] := newSymNode(s); @@ -689,23 +686,24 @@ begin if (a.sons[0].kind <> nkSym) then IllFormedAst(a); s := a.sons[0].sym; if (s.magic = mNone) and (a.sons[2] = nil) then - liMessage(a.info, errTypeXNeedsImplementation, s.name.s); + liMessage(a.info, errImplOfXexpected, s.name.s); if s.magic <> mNone then processMagicType(c, s); if a.sons[1] <> nil then begin - // we have a generic type declaration here, so we don't process the - // type's body: + // We have a generic type declaration here. In generic types, + // symbol lookup needs to be done here. openScope(c.tab); pushOwner(s); - s.typ.kind := tyGeneric; - semGenericParamList(c, a.sons[1], s.typ); - 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], false); - s.ast := a; + s.typ.kind := tyGenericBody; if s.typ.containerID <> 0 then InternalError(a.info, 'semTypeSection: containerID'); s.typ.containerID := getID(); + a.sons[1] := semGenericParamList(c, a.sons[1], s.typ); + addSon(s.typ, nil); // to be filled out later + s.ast := a; + body := semTypeNode(c, a.sons[2], nil); + if body <> nil then body.sym := s; + s.typ.sons[sonsLen(s.typ)-1] := body; + //debug(s.typ); popOwner(); closeScope(c.tab); end @@ -718,8 +716,6 @@ begin s.typ := t; s.ast := a; popOwner(); - if (tfAcyclic in t.flags) and (t.kind <> tyObject) then - liMessage(s.info, errInvalidPragmaX, 'acyclic'); end; end; // unfortunately we need another pass over the section for checking of @@ -741,15 +737,14 @@ begin s.typ.id := t.id; // same id end end; - if computeSize(s.typ) < 0 then - liMessage(s.info, errIllegalRecursionInTypeX, s.name.s); + checkConstructedType(s.info, s.typ); end end end; -procedure semParamList(c: PContext; n: PNode; s: PSym); +procedure semParamList(c: PContext; n, genericParams: PNode; s: PSym); begin - s.typ := semProcTypeNode(c, n, nil); + s.typ := semProcTypeNode(c, n, genericParams, nil); end; procedure addParams(c: PContext; n: PNode); @@ -780,62 +775,6 @@ begin liMessage(s.info, errXhasSideEffects, s.name.s); end; -function semIterator(c: PContext; n: PNode): PNode; -var - s: PSym; - oldP: PProcCon; -begin - result := n; - checkSonsLen(n, codePos+1); - if c.p.owner.kind <> skModule then - liMessage(n.info, errIteratorNotAllowed); - oldP := c.p; // restore later - s := semIdentVis(c, skIterator, n.sons[0], {@set}[sfStar]); - n.sons[namePos] := newSymNode(s); - include(s.flags, sfGlobal); - if sfStar in s.flags then include(s.flags, sfInInterface); - s.ast := n; - pushOwner(s); - if n.sons[genericParamsPos] <> nil then begin - // we have a generic type declaration here, so we don't process the - // type's body: - openScope(c.tab); - semGenericParamList(c, n.sons[genericParamsPos]); - end; - // process parameters: - if n.sons[paramsPos] <> nil then - semParamList(c, n.sons[ParamsPos], s) - else - liMessage(n.info, errIteratorNeedsReturnType); - s.typ.callConv := lastOptionEntry(c).defaultCC; - if n.sons[pragmasPos] <> nil then - pragmaIterator(c, s, n.sons[pragmasPos]); - s.options := gOptions; - if n.sons[codePos] <> nil then begin - if sfBorrow in s.flags then - liMessage(n.info, errImplOfXNotAllowed, s.name.s); - if n.sons[genericParamsPos] = nil then begin - c.p := newProcCon(s); - openScope(c.tab); - addParams(c, s.typ.n); - n.sons[codePos] := semStmtScope(c, n.sons[codePos]); - end - else begin - n.sons[codePos] := resolveGenericParams(c, n.sons[codePos]); - end - end - else if (sfBorrow in s.flags) then - semBorrow(c, n, s) - else - liMessage(n.info, errIteratorNeedsImplementation); - closeScope(c.tab); - popOwner(); - c.p := oldP; - // add it here, so that recursive iterators are impossible: - addInterfaceOverloadableSymAt(c, s, c.tab.tos-1); - //writeln(renderTree(n.sons[codePos], {@set}[renderIds])); -end; - procedure addResult(c: PContext; t: PType; const info: TLineInfo); var s: PSym; @@ -872,10 +811,10 @@ begin pushOwner(s); openScope(c.tab); - if (n.sons[genericParamsPos] <> nil) then InternalError(n.info, 'semLambda'); + if (n.sons[genericParamsPos] <> nil) then illFormedAst(n); // process parameters: if n.sons[paramsPos] <> nil then begin - semParamList(c, n.sons[ParamsPos], s); + semParamList(c, n.sons[ParamsPos], nil, s); addParams(c, s.typ.n); end else begin @@ -886,7 +825,7 @@ begin // we are in a nested proc: s.typ.callConv := ccClosure; if n.sons[pragmasPos] <> nil then - pragmaLambda(c, s, n.sons[pragmasPos]); + pragma(c, s, n.sons[pragmasPos], lambdaPragmas); s.options := gOptions; if n.sons[codePos] <> nil then begin @@ -905,10 +844,12 @@ begin result.typ := s.typ; end; -function semProcAux(c: PContext; n: PNode; kind: TSymKind): PNode; +function semProcAux(c: PContext; n: PNode; kind: TSymKind; + const validPragmas: TSpecialWords): PNode; var s, proto: PSym; oldP: PProcCon; + gp: PNode; begin result := n; checkSonsLen(n, codePos+1); @@ -925,11 +866,16 @@ begin pushOwner(s); openScope(c.tab); - if n.sons[genericParamsPos] <> nil then - semGenericParamList(c, n.sons[genericParamsPos]); + if n.sons[genericParamsPos] <> nil then begin + n.sons[genericParamsPos] := semGenericParamList(c, n.sons[genericParamsPos]); + gp := n.sons[genericParamsPos] + end + else + gp := newNodeI(nkGenericParams, n.info); // process parameters: if n.sons[paramsPos] <> nil then begin - semParamList(c, n.sons[ParamsPos], s); + semParamList(c, n.sons[ParamsPos], gp, s); + if sonsLen(gp) > 0 then n.sons[genericParamsPos] := gp; addParams(c, s.typ.n); end else begin @@ -951,8 +897,7 @@ begin else addDeclAt(c, s, c.tab.tos-2); if n.sons[pragmasPos] <> nil then - if kind = skMacro then pragmaMacro(c, s, n.sons[pragmasPos]) - else pragmaProc(c, s, n.sons[pragmasPos]); + pragma(c, s, n.sons[pragmasPos], validPragmas) end else begin if n.sons[pragmasPos] <> nil then @@ -981,15 +926,19 @@ begin if n.sons[codePos] <> nil then begin if [sfImportc, sfBorrow] * s.flags <> [] then liMessage(n.sons[codePos].info, errImplOfXNotAllowed, s.name.s); - if n.sons[genericParamsPos] = nil then begin + if (n.sons[genericParamsPos] = nil) then begin c.p := newProcCon(s); - addResult(c, s.typ.sons[0], n.info); + if (s.typ.sons[0] <> nil) and (kind <> skIterator) then + addResult(c, s.typ.sons[0], n.info); n.sons[codePos] := semStmtScope(c, n.sons[codePos]); - addResultNode(c, n); + if (s.typ.sons[0] <> nil) and (kind <> skIterator) then + addResultNode(c, n); end else begin - n.sons[codePos] := resolveGenericParams(c, n.sons[codePos]); - end; + if (s.typ.sons[0] <> nil) and (kind <> skIterator) then + addDecl(c, newSym(skUnknown, getIdent('result'), nil)); + n.sons[codePos] := semGenericStmtScope(c, n.sons[codePos]); + end end else begin if proto <> nil then @@ -1004,9 +953,21 @@ begin c.p := oldP; // restore end; +function semIterator(c: PContext; n: PNode): PNode; +var + t: PType; + s: PSym; +begin + result := semProcAux(c, n, skIterator, iteratorPragmas); + s := result.sons[namePos].sym; + t := s.typ; + if t.sons[0] = nil then liMessage(n.info, errXNeedsReturnType, 'iterator'); + if n.sons[codePos] = nil then liMessage(n.info, errImplOfXexpected, s.name.s); +end; + function semProc(c: PContext; n: PNode): PNode; begin - result := semProcAux(c, n, skProc); + result := semProcAux(c, n, skProc, procPragmas); end; function semConverterDef(c: PContext; n: PNode): PNode; @@ -1017,13 +978,11 @@ begin checkSonsLen(n, codePos+1); if n.sons[genericParamsPos] <> nil then liMessage(n.info, errNoGenericParamsAllowedForX, 'converter'); - result := semProcAux(c, n, skConverter); + result := semProcAux(c, n, skConverter, converterPragmas); s := result.sons[namePos].sym; t := s.typ; - if t.sons[0] = nil then - liMessage(n.info, errXNeedsReturnType, 'converter'); - if sonsLen(t) <> 2 then - liMessage(n.info, errXRequiresOneArgument, 'converter'); + if t.sons[0] = nil then liMessage(n.info, errXNeedsReturnType, 'converter'); + if sonsLen(t) <> 2 then liMessage(n.info, errXRequiresOneArgument, 'converter'); addConverter(c, s); end; @@ -1035,18 +994,17 @@ begin checkSonsLen(n, codePos+1); if n.sons[genericParamsPos] <> nil then liMessage(n.info, errNoGenericParamsAllowedForX, 'macro'); - result := semProcAux(c, n, skMacro); + result := semProcAux(c, n, skMacro, macroPragmas); s := result.sons[namePos].sym; t := s.typ; - if t.sons[0] = nil then - liMessage(n.info, errXNeedsReturnType, 'macro'); - if sonsLen(t) <> 2 then - liMessage(n.info, errXRequiresOneArgument, 'macro'); + if t.sons[0] = nil then liMessage(n.info, errXNeedsReturnType, 'macro'); + if sonsLen(t) <> 2 then liMessage(n.info, errXRequiresOneArgument, 'macro'); + if n.sons[codePos] = nil then liMessage(n.info, errImplOfXexpected, s.name.s); end; function evalInclude(c: PContext; n: PNode): PNode; var - i: int; + i, fileIndex: int; x: PNode; f, name, ext: string; begin @@ -1054,6 +1012,9 @@ begin addSon(result, n); // the rodwriter needs include information! for i := 0 to sonsLen(n)-1 do begin f := getModuleFile(n.sons[i]); + fileIndex := includeFilename(f); + if IntSetContainsOrIncl(c.includedFiles, fileIndex) then + liMessage(n.info, errRecursiveDependencyX, f); SplitFilename(f, name, ext); if cmpIgnoreCase(ext, '.'+TmplExt) = 0 then x := gIncludeTmplFile(f) @@ -1061,6 +1022,7 @@ begin x := gIncludeFile(f); x := semStmt(c, x); addSon(result, x); + IntSetExcl(c.includedFiles, fileIndex); end; end; @@ -1083,7 +1045,7 @@ begin if nfSem in n.flags then exit; case n.kind of nkAsgn: result := semAsgn(c, n); - nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, nkMacroStmt: + nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, nkMacroStmt, nkCallStrLit: result := semCommand(c, n); nkEmpty, nkCommentStmt, nkNilLit: begin end; nkBlockStmt: result := semBlock(c, n); @@ -1115,7 +1077,7 @@ begin nkReturnStmt: result := semReturn(c, n); nkAsmStmt: result := semAsm(c, n); nkYieldStmt: result := semYield(c, n); - nkPragma: pragmaStmt(c, c.p.owner, n); + nkPragma: pragma(c, c.p.owner, n, stmtPragmas); nkIteratorDef: result := semIterator(c, n); nkProcDef: result := semProc(c, n); nkConverterDef: result := semConverterDef(c, n); diff --git a/nim/semtempl.pas b/nim/semtempl.pas index b8107095f..f4173d9ff 100644..100755 --- a/nim/semtempl.pas +++ b/nim/semtempl.pas @@ -46,16 +46,17 @@ begin end end; -function evalTemplateAux(c: PContext; templ, actual: PNode; - sym: PSym): PNode; +function evalTemplateAux(c: PContext; templ, actual: PNode; sym: PSym): PNode; var i: int; + p: PSym; begin if templ = nil then begin result := nil; exit end; case templ.kind of nkSym: begin - if (templ.sym.kind = skParam) and (templ.sym.owner.id = sym.id) then - result := copyTree(actual.sons[templ.sym.position+1]) // BUGFIX: +1 + p := templ.sym; + if (p.kind = skParam) and (p.owner.id = sym.id) then + result := copyTree(actual.sons[p.position]) else result := copyNode(templ) end; @@ -74,19 +75,45 @@ var evalTemplateCounter: int = 0; // to prevend endless recursion in templates // instantation +function evalTemplateArgs(c: PContext; n: PNode; s: PSym): PNode; +var + f, a, i: int; + arg: PNode; +begin + f := sonsLen(s.typ); + // if the template has zero arguments, it can be called without ``()`` + // `n` is then a nkSym or something similar + case n.kind of + nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, nkCallStrLit: + a := sonsLen(n); + else a := 0 + end; + if a > f then liMessage(n.info, errWrongNumberOfArguments); + result := copyNode(n); + for i := 1 to f-1 do begin + if i < a then + arg := n.sons[i] + else + arg := copyTree(s.ast.sons[paramsPos].sons[i-1].sym.ast); + if arg = nil then liMessage(n.info, errWrongNumberOfArguments); + if not (s.typ.sons[i].kind in [tyTypeDesc, tyStmt, tyExpr]) then begin + // concrete type means semantic checking for argument: + arg := fitNode(c, s.typ.sons[i], semExprWithType(c, arg)); + end; + addSon(result, arg); + end +end; + function evalTemplate(c: PContext; n: PNode; sym: PSym): PNode; var - r: PNode; + args: PNode; begin inc(evalTemplateCounter); if evalTemplateCounter > 100 then liMessage(n.info, errTemplateInstantiationTooNested); // replace each param by the corresponding node: - r := sym.ast.sons[paramsPos].sons[0]; - if (r.kind <> nkIdent) then InternalError(r.info, 'evalTemplate'); - result := evalTemplateAux(c, sym.ast.sons[codePos], n, sym); - if r.ident.id = ord(wExpr) then result := semExpr(c, result) - else result := semStmt(c, result); + args := evalTemplateArgs(c, n, sym); + result := evalTemplateAux(c, sym.ast.sons[codePos], args, sym); dec(evalTemplateCounter); end; @@ -108,19 +135,19 @@ begin include(s.flags, sfUsed); end else begin - // semantic checking requires a type; ``fitNode`` deal with it + // semantic checking requires a type; ``fitNode`` deals 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; + //liMessage(n.info, warnUser, s.name.s + ' is here symchoice'); end end; -function resolveTemplateParams(c: PContext; n: PNode; - withinBind: bool): PNode; +function resolveTemplateParams(c: PContext; n: PNode; withinBind: bool): PNode; var i: int; s: PSym; @@ -153,20 +180,6 @@ begin end end; -function semTemplateParamKind(c: PContext; n, p: PNode): PNode; -begin - if (p = nil) or (p.kind <> nkIdent) then - liMessage(n.info, errInvalidParamKindX, renderTree(p)) - else begin - case p.ident.id of - ord(wExpr), ord(wStmt), ord(wTypeDesc): begin end; - else - liMessage(p.info, errInvalidParamKindX, p.ident.s) - end - end; - result := p; -end; - function transformToExpr(n: PNode): PNode; var i, realStmt: int; @@ -197,9 +210,7 @@ end; function semTemplateDef(c: PContext; n: PNode): PNode; var - s, param: PSym; - i, j, len, counter: int; - params, p, paramKind: PNode; + s: PSym; begin if c.p.owner.kind = skModule then begin s := semIdentVis(c, skTemplate, n.sons[0], {@set}[sfStar]); @@ -211,23 +222,6 @@ begin // check parameter list: pushOwner(s); openScope(c.tab); - params := n.sons[paramsPos]; - counter := 0; - for i := 1 to sonsLen(params)-1 do begin - p := params.sons[i]; - len := sonsLen(p); - paramKind := semTemplateParamKind(c, p, p.sons[len-2]); - if (p.sons[len-1] <> nil) then - liMessage(p.sons[len-1].info, errDefaultArgumentInvalid); - for j := 0 to len-3 do begin - param := newSymS(skParam, p.sons[j], c); - param.position := counter; - param.ast := paramKind; - inc(counter); - addDecl(c, param) - end; - end; - params.sons[0] := semTemplateParamKind(c, params, params.sons[0]); n.sons[namePos] := newSymNode(s); // check that no pragmas exist: @@ -236,9 +230,26 @@ begin // check that no generic parameters exist: if n.sons[genericParamsPos] <> nil then liMessage(n.info, errNoGenericParamsAllowedForX, 'template'); + if (n.sons[paramsPos] = nil) then begin + // use ``stmt`` as implicit result type + s.typ := newTypeS(tyProc, c); + s.typ.n := newNodeI(nkFormalParams, n.info); + addSon(s.typ, newTypeS(tyStmt, c)); + addSon(s.typ.n, newNodeIT(nkType, n.info, s.typ.sons[0])); + end + else begin + semParamList(c, n.sons[ParamsPos], nil, s); + if n.sons[paramsPos].sons[0] = nil then begin + // use ``stmt`` as implicit result type + s.typ.sons[0] := newTypeS(tyStmt, c); + s.typ.n.sons[0] := newNodeIT(nkType, n.info, s.typ.sons[0]); + end + end; + addParams(c, s.typ.n); + // resolve parameters: n.sons[codePos] := resolveTemplateParams(c, n.sons[codePos], false); - if params.sons[0].ident.id = ord(wExpr) then + if not (s.typ.sons[0].kind in [tyStmt, tyTypeDesc]) then n.sons[codePos] := transformToExpr(n.sons[codePos]); // only parameters are resolved, no type checking is performed diff --git a/nim/semtypes.pas b/nim/semtypes.pas index c968d4b72..934196de4 100644..100755 --- a/nim/semtypes.pas +++ b/nim/semtypes.pas @@ -140,13 +140,13 @@ begin liMessage(n.info, errXExpectsOneTypeParam, 'var'); end; -function semAbstract(c: PContext; n: PNode; prev: PType): PType; +function semDistinct(c: PContext; n: PNode; prev: PType): PType; begin - result := newOrPrevType(tyAbstract, prev, c); + result := newOrPrevType(tyDistinct, prev, c); if sonsLen(n) = 1 then addSon(result, semTypeNode(c, n.sons[0], nil)) else - liMessage(n.info, errXExpectsOneTypeParam, 'abstract'); + liMessage(n.info, errXExpectsOneTypeParam, 'distinct'); end; function semRangeAux(c: PContext; n: PNode; prev: PType): PType; @@ -233,8 +233,7 @@ begin result := qualifiedLookup(c, n, true); if (result <> nil) then begin include(result.flags, sfUsed); - if not (result.kind in [skTypeParam, skType]) then - liMessage(n.info, errTypeExpected); + if result.kind <> skType then liMessage(n.info, errTypeExpected); end else liMessage(n.info, errIdentifierExpected); @@ -275,87 +274,36 @@ begin end end end; -(* -function instGenericAux(c: PContext; templ, actual: PNode; - sym: PSym): PNode; -var - i: int; -begin - if templ = nil then begin result := nil; exit end; - case templ.kind of - nkSym: begin - if (templ.sym.kind = skTypeParam) then - //and (templ.sym.owner.id = sym.id) then - result := copyTree(actual.sons[templ.sym.position+1]) - else - result := copyNode(templ) - end; - nkNone..nkIdent, nkType..nkNilLit: // atom - result := copyNode(templ); - else begin - result := copyNode(templ); - newSons(result, sonsLen(templ)); - for i := 0 to sonsLen(templ)-1 do - result.sons[i] := instGenericAux(c, templ.sons[i], actual, sym); - end - end -end; *) function semGeneric(c: PContext; n: PNode; s: PSym; prev: PType): PType; var i: int; elem: PType; - inst: PNode; - cl: PInstantiateClosure; + isConcrete: bool; begin - if (s.typ = nil) or (s.typ.kind <> tyGeneric) then + if (s.typ = nil) or (s.typ.kind <> tyGenericBody) then liMessage(n.info, errCannotInstantiateX, s.name.s); - result := newOrPrevType(tyGenericInst, prev, c); // new ID... - result.containerID := s.typ.containerID; // ... but the same containerID - result.sym := s; + result := newOrPrevType(tyGenericInvokation, prev, c); if (s.typ.containerID = 0) then InternalError(n.info, 'semtypes.semGeneric'); - cl := newInstantiateClosure(c, n.info); - // check the number of supplied arguments suffices: - if sonsLen(n) <> sonsLen(s.typ) then begin - //MessageOut('n: ' +{&} toString(sonsLen(n)) +{&} ' s: ' - // +{&} toString(sonsLen(s.typ))); - liMessage(n.info, errWrongNumberOfTypeParams); - end; - // a generic type should be instantiated with itself: - // idTablePut(cl.typeMap, s.typ, result); + if sonsLen(n) <> sonsLen(s.typ) then + liMessage(n.info, errWrongNumberOfArguments); + addSon(result, s.typ); + isConcrete := true; // iterate over arguments: for i := 1 to sonsLen(n)-1 do begin elem := semTypeNode(c, n.sons[i], nil); - if elem.kind = tyGenericParam then - result.kind := tyGeneric // prevend type from instantiation - else - idTablePut(cl.typeMap, s.typ.sons[i-1], elem); + if elem.kind = tyGenericParam then isConcrete := false; addSon(result, elem); end; - if s.ast <> nil then begin - if (result.kind = tyGenericInst) then begin - // inst := instGenericAux(c, s.ast.sons[2], n, s); - internalError(n.info, 'Generic containers not implemented'); - // XXX: implementation does not work this way - // we need to do the following: - // traverse and copy the type and replace any tyGenericParam type - // does checking of instantiated type for us: - elem := instantiateType(cl, s.typ); //semTypeNode(c, inst, nil); - elem.id := result.containerID; - addSon(result, elem); - end - else - addSon(result, nil); + if isConcrete then begin + if s.ast = nil then liMessage(n.info, errCannotInstantiateX, s.name.s); + result := instGenericContainer(c, n, result); end - else - liMessage(n.info, errCannotInstantiateX, s.name.s); - (*if computeSize(result) < 0 then - liMessage(s.info, errIllegalRecursionInTypeX, s.name.s);*) end; function semIdentVis(c: PContext; kind: TSymKind; n: PNode; const allowed: TSymFlags): PSym; -// identifier with visability +// identifier with visibility var v: PIdent; begin @@ -388,9 +336,9 @@ begin skType: begin // process pragmas later, because result.typ has not been set yet end; - skField: pragmaField(c, result, n.sons[1]); - skVar: pragmaVar(c, result, n.sons[1]); - skConst: pragmaConst(c, result, n.sons[1]); + skField: pragma(c, result, n.sons[1], fieldPragmas); + skVar: pragma(c, result, n.sons[1], varPragmas); + skConst: pragma(c, result, n.sons[1], constPragmas); else begin end end end @@ -546,8 +494,7 @@ begin for i := 0 to sonsLen(n)-1 do begin semRecordNodeAux(c, n.sons[i], check, pos, a, rectype); end; - if a <> father then - addSon(father, a); + if a <> father then addSon(father, a); end; nkIdentDefs: begin checkMinSonsLen(n, 3); @@ -644,10 +591,8 @@ begin end else base := nil; - if n.kind = nkObjectTy then - result := newOrPrevType(tyObject, prev, c) - else - InternalError(n.info, 'semObjectNode'); + if n.kind <> nkObjectTy then InternalError(n.info, 'semObjectNode'); + result := newOrPrevType(tyObject, prev, c); addSon(result, base); result.n := newNodeI(nkRecList, n.info); semRecordNodeAux(c, n.sons[2], check, pos, result.n, result.sym); @@ -655,26 +600,75 @@ begin liMessage(n.sons[1].info, errInheritanceOnlyWithNonFinalObjects); end; -function semProcTypeNode(c: PContext; n: PNode; prev: PType): PType; +function addTypeVarsOfGenericBody(c: PContext; t: PType; genericParams: PNode; + var cl: TIntSet): PType; +var + i, L: int; + s: PSym; +begin + result := t; + if (t = nil) then exit; + if IntSetContainsOrIncl(cl, t.id) then exit; + case t.kind of + tyGenericBody: begin + result := newTypeS(tyGenericInvokation, c); + addSon(result, t); + for i := 0 to sonsLen(t)-2 do begin + if t.sons[i].kind <> tyGenericParam then + InternalError('addTypeVarsOfGenericBody'); + s := copySym(t.sons[i].sym); + s.position := sonsLen(genericParams); + addDecl(c, s); + addSon(genericParams, newSymNode(s)); + addSon(result, t.sons[i]); + end; + end; + tyGenericInst: begin + L := sonsLen(t)-1; + t.sons[L] := addTypeVarsOfGenericBody(c, t.sons[L], genericParams, cl); + end; + tyGenericInvokation: begin + for i := 1 to sonsLen(t)-1 do + t.sons[i] := addTypeVarsOfGenericBody(c, t.sons[i], genericParams, cl); + end + else begin + for i := 0 to sonsLen(t)-1 do + t.sons[i] := addTypeVarsOfGenericBody(c, t.sons[i], genericParams, cl); + end + end +end; + +function paramType(c: PContext; n, genericParams: PNode; + var cl: TIntSet): PType; +begin + result := semTypeNode(c, n, nil); + if (genericParams <> nil) and (sonsLen(genericParams) = 0) then + result := addTypeVarsOfGenericBody(c, result, genericParams, cl); +end; + +function semProcTypeNode(c: PContext; n, genericParams: PNode; + prev: PType): PType; var i, j, len, counter: int; a, def, res: PNode; typ: PType; arg: PSym; - check: TIntSet; + check, cl: TIntSet; begin checkMinSonsLen(n, 1); result := newOrPrevType(tyProc, prev, c); result.callConv := lastOptionEntry(c).defaultCC; result.n := newNodeI(nkFormalParams, n.info); + if (genericParams <> nil) and (sonsLen(genericParams) = 0) then + IntSetInit(cl); if n.sons[0] = nil then begin addSon(result, nil); // return type addSon(result.n, newNodeI(nkType, n.info)); // BUGFIX: nkType must exist! + // XXX but it does not, if n.sons[paramsPos] == nil? end else begin - addSon(result, semTypeNode(c, n.sons[0], nil)); // return type + addSon(result, nil); res := newNodeI(nkType, n.info); - res.typ := result.sons[0]; addSon(result.n, res); end; IntSetInit(check); @@ -685,7 +679,7 @@ begin checkMinSonsLen(a, 3); len := sonsLen(a); if a.sons[len-2] <> nil then - typ := semTypeNode(c, a.sons[len-2], nil) + typ := paramType(c, a.sons[len-2], genericParams, cl) else typ := nil; if a.sons[len-1] <> nil then begin @@ -712,6 +706,11 @@ begin addSon(result.n, newSymNode(arg)); addSon(result, typ); end + end; + // NOTE: semantic checking of the result type needs to be done here! + if n.sons[0] <> nil then begin + result.sons[0] := paramType(c, n.sons[0], genericParams, cl); + res.typ := result.sons[0]; end end; @@ -751,6 +750,7 @@ end; function semTypeNode(c: PContext; n: PNode; prev: PType): PType; var s: PSym; + t: PType; begin result := nil; if n = nil then exit; @@ -784,11 +784,12 @@ begin end end; nkSym: begin - if (n.sym.kind in [skTypeParam, skType]) and (n.sym.typ <> nil) then begin + if (n.sym.kind = skType) and (n.sym.typ <> nil) then begin + t := n.sym.typ; if prev = nil then - result := n.sym.typ + result := t else begin - assignType(prev, s.typ); + assignType(prev, t); result := prev; end; include(n.sym.flags, sfUsed); // BUGFIX @@ -801,14 +802,14 @@ begin nkRefTy: result := semAnyRef(c, n, tyRef, 'ref', prev); nkPtrTy: result := semAnyRef(c, n, tyPtr, 'ptr', prev); nkVarTy: result := semVarType(c, n, prev); - nkAbstractTy: result := semAbstract(c, n, prev); + nkDistinctTy: result := semDistinct(c, n, prev); nkProcTy: begin checkSonsLen(n, 2); - result := semProcTypeNode(c, n.sons[0], prev); + result := semProcTypeNode(c, n.sons[0], nil, prev); // dummy symbol for `pragma`: s := newSymS(skProc, newIdentNode(getIdent('dummy'), n.info), c); s.typ := result; - pragmaProcType(c, s, n.sons[1]); + pragma(c, s, n.sons[1], procTypePragmas); end; nkEnumTy: result := semEnum(c, n, prev); nkType: result := n.typ; @@ -859,6 +860,9 @@ begin exit end; mNil: setMagicType(m, tyNil, ptrSize); + mExpr: setMagicType(m, tyExpr, 0); + mStmt: setMagicType(m, tyStmt, 0); + mTypeDesc: setMagicType(m, tyTypeDesc, 0); mArray, mOpenArray, mRange, mSet, mSeq, mOrdinal: exit; else liMessage(m.info, errTypeExpected); end; diff --git a/nim/sigmatch.pas b/nim/sigmatch.pas index ccd05d413..aa53a741c 100644..100755 --- a/nim/sigmatch.pas +++ b/nim/sigmatch.pas @@ -43,7 +43,7 @@ begin c.call := nil; c.baseTypeMatch := false; initIdTable(c.bindings); - assert(c.callee <> nil); + //assert(c.callee <> nil); end; procedure copyCandidate(var a: TCandidate; const b: TCandidate); @@ -117,7 +117,7 @@ end; function typeRel(var mapping: TIdTable; f, a: PType): TTypeRelation; overload; forward; -function concreteType(t: PType): PType; +function concreteType(const mapping: TIdTable; t: PType): PType; begin case t.kind of tyArrayConstr: begin // make it an array @@ -126,6 +126,14 @@ begin addSon(result, t.sons[1]); // XXX: semantic checking for the type? end; tyNil: result := nil; // what should it be? + tyGenericParam: begin + result := t; + while true do begin + result := PType(idTableGet(mapping, t)); + if result = nil then InternalError('lookup failed'); + if result.kind <> tyGenericParam then break + end + end; else result := t // Note: empty is valid here end end; @@ -218,8 +226,9 @@ begin // is a subtype of f? result := isNone; assert(f <> nil); assert(a <> nil); - if (a.kind = tyGenericInst) and - (skipTypes(f, {@set}[tyVar]).kind <> tyGeneric) then begin + if (a.kind = tyGenericInst) and not + (skipTypes(f, {@set}[tyVar]).kind in [tyGenericBody, tyGenericInvokation]) + then begin result := typeRel(mapping, f, lastSon(a)); exit end; @@ -348,8 +357,8 @@ begin // is a subtype of f? else if isObjectSubtype(a, f) then result := isSubtype end end; - tyAbstract: begin - if (a.kind = tyAbstract) and (a.id = f.id) then result := isEqual; + tyDistinct: begin + if (a.kind = tyDistinct) and (a.id = f.id) then result := isEqual; end; tySet: begin if a.kind = tySet then begin @@ -415,6 +424,8 @@ begin // is a subtype of f? result := isNone end else if a.sons[0] <> nil then + result := isNone; + if (tfNoSideEffect in f.flags) and not (tfNoSideEffect in a.flags) then result := isNone end end @@ -458,12 +469,11 @@ begin // is a subtype of f? end; tyGenericInst: begin result := typeRel(mapping, lastSon(f), a); - end; - tyGeneric: begin + end; (* + tyGenericBody: begin x := PType(idTableGet(mapping, f)); if x = nil then begin assert(f.containerID <> 0); - assert(lastSon(f) = nil); if (a.kind = tyGenericInst) and (f.containerID = a.containerID) and (sonsLen(a) = sonsLen(f)) then begin for i := 0 to sonsLen(f)-2 do begin @@ -476,22 +486,64 @@ begin // is a subtype of f? else begin result := typeRel(mapping, x, a) // check if it fits end + end; *) + tyGenericBody: begin + result := typeRel(mapping, lastSon(f), a); + end; + tyGenericInvokation: begin + assert(f.sons[0].kind = tyGenericBody); + if a.kind = tyGenericInvokation then begin + InternalError('typeRel: tyGenericInvokation -> tyGenericInvokation'); + end; + if (a.kind = tyGenericInst) then begin + if (f.sons[0].containerID = a.sons[0].containerID) + and (sonsLen(a)-1 = sonsLen(f)) then begin + assert(a.sons[0].kind = tyGenericBody); + for i := 1 to sonsLen(f)-1 do begin + if a.sons[i].kind = tyGenericParam then begin + InternalError('wrong instantiated type!'); + end; + if typeRel(mapping, f.sons[i], a.sons[i]) < isGeneric then exit; + end; + result := isGeneric; + end (* + else begin + MessageOut('came here: ' + toString(sonsLen(f)) + ' ' + + toString(sonsLen(a)) + ' '+ + toString(f.sons[0].containerID) + ' '+ + toString(a.sons[0].containerID)); + end *) + end + else begin + result := typeRel(mapping, f.sons[0], a); + if result <> isNone then begin + // we steal the generic parameters from the tyGenericBody: + for i := 1 to sonsLen(f)-1 do begin + x := PType(idTableGet(mapping, f.sons[0].sons[i-1])); + if (x = nil) or (x.kind = tyGenericParam) then + InternalError('wrong instantiated type!'); + idTablePut(mapping, f.sons[i], x); + end + end + end end; tyGenericParam: begin x := PType(idTableGet(mapping, f)); if x = nil then begin if sonsLen(f) = 0 then begin // no constraints - concrete := concreteType(a); + concrete := concreteType(mapping, a); if concrete <> nil then begin + //MessageOut('putting: ' + f.sym.name.s); idTablePut(mapping, f, concrete); result := isGeneric end; end else begin + InternalError(f.sym.info, 'has constraints: ' + f.sym.name.s); // check constraints: for i := 0 to sonsLen(f)-1 do begin if typeRel(mapping, f.sons[i], a) >= isSubtype then begin - concrete := concreteType(a); + concrete := concreteType(mapping, a); if concrete <> nil then begin idTablePut(mapping, f, concrete); result := isGeneric @@ -503,10 +555,20 @@ begin // is a subtype of f? end else if a.kind = tyEmpty then result := isGeneric - else begin - result := typeRel(mapping, x, a); // check if it fits - end - end + else if x.kind = tyGenericParam then + result := isGeneric + else + result := typeRel(mapping, x, a) // check if it fits + end; + tyExpr, tyStmt, tyTypeDesc: begin + if a.kind = f.kind then result := isEqual + else + case a.kind of + tyExpr, tyStmt, tyTypeDesc: result := isGeneric; + tyNil: result := isSubtype; + else begin end + end + end; else internalError('typeRel(' +{&} typeKindToStr[f.kind] +{&} ')'); end end; @@ -524,7 +586,7 @@ function getInstantiatedType(c: PContext; arg: PNode; const m: TCandidate; begin result := PType(idTableGet(m.bindings, f)); if result = nil then begin - result := generateTypeInstance(c, m.bindings, arg.info, f); + result := generateTypeInstance(c, m.bindings, arg, f); end; if result = nil then InternalError(arg.info, 'getInstantiatedType'); end; @@ -630,8 +692,9 @@ var x, y, z: TCandidate; r: TTypeRelation; begin - if (arg = nil) or (arg.kind <> nkSymChoice) then + if (arg = nil) or (arg.kind <> nkSymChoice) then begin result := ParamTypesMatchAux(c, m, f, a, arg) + end 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 @@ -645,16 +708,19 @@ begin 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 + // iterators are not first class yet, so ignore them + if arg.sons[i].sym.kind in {@set}[skProc, skConverter] then 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 @@ -818,13 +884,14 @@ begin end end; -function semDirectCall(c: PContext; n: PNode): PNode; +function semDirectCall(c: PContext; n: PNode; filter: TSymKinds): PNode; var sym: PSym; o: TOverloadIter; x, y, z: TCandidate; cmp: int; begin + //liMessage(n.info, warnUser, renderTree(n)); sym := initOverloadIter(o, c, n.sons[0]); result := nil; if sym = nil then exit; @@ -833,7 +900,7 @@ begin initCandidate(y, sym.typ); y.calleeSym := sym; while sym <> nil do begin - if sym.kind in [skProc, skIterator, skConverter] then begin + if sym.kind in filter then begin initCandidate(z, sym.typ); z.calleeSym := sym; matches(c, n, z); diff --git a/nim/strutils.pas b/nim/strutils.pas index f34379fcb..be20b52b2 100644..100755 --- a/nim/strutils.pas +++ b/nim/strutils.pas @@ -66,7 +66,7 @@ function repeatChar(count: int; c: Char = ' '): string; type TStringSeq = array of string; TCharSet = set of Char; -function splitSeq(const s: string; const seps: TCharSet): TStringSeq; +function split(const s: string; const seps: TCharSet): TStringSeq; function startsWith(const s, prefix: string): bool; function endsWith(const s, postfix: string): bool; @@ -78,9 +78,15 @@ function strip(const s: string; const chars: TCharSet = WhiteSpace): string; function allCharsInSet(const s: string; const theSet: TCharSet): bool; function quoteIfContainsWhite(const s: string): string; +procedure addSep(var dest: string; sep: string = ', '); implementation +procedure addSep(var dest: string; sep: string = ', '); +begin + if length(dest) > 0 then add(dest, sep) +end; + function quoteIfContainsWhite(const s: string): string; begin if ((find(s, ' ') >= strStart) @@ -148,7 +154,7 @@ begin end end; -function splitSeq(const s: string; const seps: TCharSet): TStringSeq; +function split(const s: string; const seps: TCharSet): TStringSeq; var first, last, len: int; begin diff --git a/nim/syntaxes.pas b/nim/syntaxes.pas index 1068064ce..1068064ce 100644..100755 --- a/nim/syntaxes.pas +++ b/nim/syntaxes.pas diff --git a/nim/tigen.pas b/nim/tigen.pas index 687b70920..687b70920 100644..100755 --- a/nim/tigen.pas +++ b/nim/tigen.pas diff --git a/nim/transf.pas b/nim/transf.pas index 3e3b2a611..79f65b754 100644..100755 --- a/nim/transf.pas +++ b/nim/transf.pas @@ -124,7 +124,7 @@ Should be transformed into:: return a[i] block L1: inc(c.i) -More efficient, but not implementable: +More efficient, but not implementable:: type TItemsClosure = record @@ -288,7 +288,7 @@ end; function inlineIter(c: PTransf; n: PNode): PNode; var - i: int; + i, j, L: int; it: PNode; newVar: PSym; begin @@ -304,16 +304,33 @@ begin for i := 0 to sonsLen(result)-1 do begin it := result.sons[i]; if it.kind = nkCommentStmt then continue; - if (it.kind <> nkIdentDefs) or (it.sons[0].kind <> nkSym) then - InternalError(it.info, 'inlineIter'); - newVar := copySym(it.sons[0].sym); - include(newVar.flags, sfFromGeneric); - // fixes a strange bug for rodgen: - //include(it.sons[0].sym.flags, sfFromGeneric); - newVar.owner := getCurrOwner(c); - IdNodeTablePut(c.transCon.mapping, it.sons[0].sym, newSymNode(newVar)); - it.sons[0] := newSymNode(newVar); - it.sons[2] := transform(c, it.sons[2]); + if it.kind = nkIdentDefs then begin + if (it.sons[0].kind <> nkSym) then + InternalError(it.info, 'inlineIter'); + newVar := copySym(it.sons[0].sym); + include(newVar.flags, sfFromGeneric); + // fixes a strange bug for rodgen: + //include(it.sons[0].sym.flags, sfFromGeneric); + newVar.owner := getCurrOwner(c); + IdNodeTablePut(c.transCon.mapping, it.sons[0].sym, newSymNode(newVar)); + it.sons[0] := newSymNode(newVar); + it.sons[2] := transform(c, it.sons[2]); + end + else begin + if it.kind <> nkVarTuple then + InternalError(it.info, 'inlineIter: not nkVarTuple'); + L := sonsLen(it); + for j := 0 to L-3 do begin + newVar := copySym(it.sons[j].sym); + include(newVar.flags, sfFromGeneric); + newVar.owner := getCurrOwner(c); + IdNodeTablePut(c.transCon.mapping, it.sons[j].sym, + newSymNode(newVar)); + it.sons[j] := newSymNode(newVar); + end; + assert(it.sons[L-2] = nil); + it.sons[L-1] := transform(c, it.sons[L-1]); + end end end else begin @@ -758,7 +775,8 @@ function getMergeOp(n: PNode): PSym; begin result := nil; case n.kind of - nkCall, nkHiddenCallConv, nkCommand, nkInfix, nkPrefix, nkPostfix: begin + nkCall, nkHiddenCallConv, nkCommand, nkInfix, nkPrefix, nkPostfix, + nkCallStrLit: begin if (n.sons[0].Kind = nkSym) and (n.sons[0].sym.kind = skProc) and (sfMerge in n.sons[0].sym.flags) then result := n.sons[0].sym; @@ -873,7 +891,8 @@ begin n.sons[0] := transform(c, n.sons[0]); n.sons[1] := transformContinue(c, n.sons[1]); end; - nkCall, nkHiddenCallConv, nkCommand, nkInfix, nkPrefix, nkPostfix: + nkCall, nkHiddenCallConv, nkCommand, nkInfix, nkPrefix, nkPostfix, + nkCallStrLit: result := transformCall(c, result); nkAddr, nkHiddenAddr: result := transformAddrDeref(c, n, nkDerefExpr, nkHiddenDeref); diff --git a/nim/transtmp.pas b/nim/transtmp.pas index 77ba157f3..15a07f5a2 100644..100755 --- a/nim/transtmp.pas +++ b/nim/transtmp.pas @@ -140,7 +140,7 @@ begin addSon(father, newAsgnStmt(dest, src)); end end; - nkCall, nkCommand: begin + nkCall, nkCommand, nkCallStrLit: begin end; diff --git a/nim/trees.pas b/nim/trees.pas index 4df85f6bb..0e0c04a22 100644..100755 --- a/nim/trees.pas +++ b/nim/trees.pas @@ -144,21 +144,19 @@ end; function getOpSym(op: PNode): PSym; begin - if not (op.kind in [nkCall, nkGenericCall, nkHiddenCallConv, nkCommand]) then + if not (op.kind in [nkCall, nkHiddenCallConv, nkCommand, nkCallStrLit]) then result := nil else begin if (sonsLen(op) <= 0) then InternalError(op.info, 'getOpSym'); - case op.sons[0].Kind of - nkSym, nkQualified: result := op.sons[0].sym; - else result := nil - end + if op.sons[0].Kind = nkSym then result := op.sons[0].sym + else result := nil end end; function getMagic(op: PNode): TMagic; begin case op.kind of - nkCall, nkHiddenCallConv, nkCommand: begin + nkCall, nkHiddenCallConv, nkCommand, nkCallStrLit: begin case op.sons[0].Kind of nkSym: begin result := op.sons[0].sym.magic; @@ -166,9 +164,6 @@ begin else result := mNone end end; - nkExplicitTypeListCall, nkGenericCall: begin - result := getMagic(op.sons[sonsLen(op)-1]); - end; else result := mNone end diff --git a/nim/treetab.pas b/nim/treetab.pas index 31d7aa0cf..31d7aa0cf 100644..100755 --- a/nim/treetab.pas +++ b/nim/treetab.pas diff --git a/nim/types.pas b/nim/types.pas index d2aee2413..a881b2f11 100644..100755 --- a/nim/types.pas +++ b/nim/types.pas @@ -48,7 +48,7 @@ function mutateType(t: PType; iter: TTypeMutator; closure: PObject): PType; function SameType(x, y: PType): Boolean; function SameTypeOrNil(a, b: PType): Boolean; -function equalOrAbstractOf(x, y: PType): bool; +function equalOrDistinctOf(x, y: PType): bool; type TParamsEquality = (paramsNotEqual, // parameters are not equal @@ -66,11 +66,11 @@ function isOrdinalType(t: PType): Boolean; function enumHasWholes(t: PType): Boolean; const - abstractPtrs = {@set}[tyVar, tyPtr, tyRef, tyGenericInst, tyAbstract, tyOrdinal]; - abstractVar = {@set}[tyVar, tyGenericInst, tyAbstract, tyOrdinal]; - abstractRange = {@set}[tyGenericInst, tyRange, tyAbstract, tyOrdinal]; - abstractVarRange = {@set}[tyGenericInst, tyRange, tyVar, tyAbstract, tyOrdinal]; - abstractInst = {@set}[tyGenericInst, tyAbstract, tyOrdinal]; + abstractPtrs = {@set}[tyVar, tyPtr, tyRef, tyGenericInst, tyDistinct, tyOrdinal]; + abstractVar = {@set}[tyVar, tyGenericInst, tyDistinct, tyOrdinal]; + abstractRange = {@set}[tyGenericInst, tyRange, tyDistinct, tyOrdinal]; + abstractVarRange = {@set}[tyGenericInst, tyRange, tyVar, tyDistinct, tyOrdinal]; + abstractInst = {@set}[tyGenericInst, tyDistinct, tyOrdinal]; function skipTypes(t: PType; kinds: TTypeKinds): PType; @@ -202,7 +202,7 @@ function elemType(t: PType): PType; begin assert(t <> nil); case t.kind of - tyGenericInst, tyAbstract: result := elemType(lastSon(t)); + tyGenericInst, tyDistinct: result := elemType(lastSon(t)); tyArray, tyArrayConstr: result := t.sons[1]; else result := t.sons[0]; end; @@ -317,12 +317,17 @@ begin result := iter(t, closure); if result then exit; if not IntSetContainsOrIncl(marker, t.id) then begin - for i := 0 to sonsLen(t)-1 do begin - result := iterOverTypeAux(marker, t.sons[i], iter, closure); - if result then exit; - end; - if t.n <> nil then - result := iterOverNode(marker, t.n, iter, closure) + case t.kind of + tyGenericInst, tyGenericBody: + result := iterOverTypeAux(marker, lastSon(t), iter, closure); + else begin + for i := 0 to sonsLen(t)-1 do begin + result := iterOverTypeAux(marker, t.sons[i], iter, closure); + if result then exit; + end; + if t.n <> nil then result := iterOverNode(marker, t.n, iter, closure) + end + end end end; @@ -388,7 +393,7 @@ begin if not result then result := searchTypeNodeForAux(t.n, predicate, marker); end; - tyGenericInst, tyAbstract: + tyGenericInst, tyDistinct: result := searchTypeForAux(lastSon(t), predicate, marker); tyArray, tyArrayConstr, tySet, tyTuple: begin for i := 0 to sonsLen(t)-1 do begin @@ -421,7 +426,7 @@ end; function isObjectWithTypeFieldPredicate(t: PType): bool; begin result := (t.kind = tyObject) and (t.sons[0] = nil) - and not (sfPure in t.sym.flags) + and not ((t.sym <> nil) and (sfPure in t.sym.flags)) and not (tfFinal in t.flags); end; @@ -447,7 +452,7 @@ begin if result = frNone then if isObjectWithTypeFieldPredicate(t) then result := frHeader end; - tyGenericInst, tyAbstract: + tyGenericInst, tyDistinct: result := analyseObjectWithTypeFieldAux(lastSon(t), marker); tyArray, tyArrayConstr, tyTuple: begin for i := 0 to sonsLen(t)-1 do begin @@ -491,7 +496,7 @@ begin result := searchTypeFor(typ, isHiddenPointer); end; -function canFormAcycleAux(var marker: TIntSet; t: PType; +function canFormAcycleAux(var marker: TIntSet; typ: PType; startId: int): bool; forward; function canFormAcycleNode(var marker: TIntSet; n: PNode; startId: int): bool; @@ -514,14 +519,17 @@ begin end end; -function canFormAcycleAux(var marker: TIntSet; t: PType; startId: int): bool; +function canFormAcycleAux(var marker: TIntSet; typ: PType; startId: int): bool; var i: int; + t: PType; begin result := false; - if t = nil then exit; + if typ = nil then exit; + if tfAcyclic in typ.flags then exit; + t := skipTypes(typ, abstractInst); if tfAcyclic in t.flags then exit; - case skipTypes(t, abstractInst).kind of + case t.kind of tyTuple, tyObject, tyRef, tySequence, tyArray, tyArrayConstr, tyOpenArray: begin if not IntSetContainsOrIncl(marker, t.id) then begin @@ -606,8 +614,10 @@ end; function TypeToString(typ: PType; prefer: TPreferedDesc = preferName): string; const typeToStr: array [TTypeKind] of string = ( - 'None', 'bool', 'Char', 'empty', 'Array Constructor [$1]', 'nil', - 'Generic', 'GenericInst', 'GenericParam', 'abstract $1', + 'None', 'bool', 'Char', 'empty', 'Array Constructor [$1]', 'nil', 'expr', + 'stmt', 'typeDesc', + 'GenericInvokation', + 'GenericBody', 'GenericInst', 'GenericParam', 'distinct $1', 'enum', 'ordinal[$1]', 'array[$1, $2]', 'object', 'tuple', 'set[$1]', 'range[$1]', 'ptr ', 'ref ', 'var ', 'seq[$1]', 'proc', 'pointer', @@ -618,6 +628,7 @@ const var t: PType; i: int; + prag: string; begin t := typ; result := ''; @@ -637,6 +648,14 @@ begin result := 'array[' +{&} typeToString(t.sons[0]) +{&} ', ' +{&} typeToString(t.sons[1]) +{&} ']' end; + tyGenericInvokation, tyGenericBody: begin + result := typeToString(t.sons[0]) + '['; + for i := 1 to sonsLen(t)-1 do begin + if i > 1 then add(result, ', '); + add(result, typeToString(t.sons[i])); + end; + addChar(result, ']'); + end; tyArrayConstr: result := 'Array constructor[' +{&} rangeToStr(t.sons[0].n) +{&} ', ' +{&} typeToString(t.sons[1]) +{&} ']'; @@ -644,7 +663,7 @@ begin tyOrdinal: result := 'ordinal[' +{&} typeToString(t.sons[0]) +{&} ']'; tySet: result := 'set[' +{&} typeToString(t.sons[0]) +{&} ']'; tyOpenArray: result := 'openarray[' +{&} typeToString(t.sons[0]) +{&} ']'; - tyAbstract: result := 'abstract ' +{&} typeToString(t.sons[0], preferName); + tyDistinct: result := 'distinct ' +{&} typeToString(t.sons[0], preferName); tyTuple: begin // we iterate over t.sons here, because t.n may be nil result := 'tuple['; @@ -679,8 +698,13 @@ begin addChar(result, ')'); if t.sons[0] <> nil then add(result, ': ' +{&} TypeToString(t.sons[0])); - if t.callConv <> ccDefault then - add(result, '{.' +{&} CallingConvToStr[t.callConv] +{&} '.}'); + if t.callConv <> ccDefault then prag := CallingConvToStr[t.callConv] + else prag := ''; + if tfNoSideEffect in t.flags then begin + addSep(prag); + add(prag, 'noSideEffect') + end; + if length(prag) <> 0 then add(result, '{.' +{&} prag +{&} '.}'); end; else begin result := typeToStr[t.kind] @@ -730,7 +754,7 @@ begin result := t.n.sons[0].sym.position; end; end; - tyGenericInst, tyAbstract: result := firstOrd(lastSon(t)); + tyGenericInst, tyDistinct: result := firstOrd(lastSon(t)); else begin InternalError('invalid kind for first(' +{&} typeKindToStr[t.kind] +{&} ')'); @@ -766,7 +790,7 @@ begin assert(t.n.sons[sonsLen(t.n)-1].kind = nkSym); result := t.n.sons[sonsLen(t.n)-1].sym.position; end; - tyGenericInst, tyAbstract: result := firstOrd(lastSon(t)); + tyGenericInst, tyDistinct: result := firstOrd(lastSon(t)); else begin InternalError('invalid kind for last(' +{&} typeKindToStr[t.kind] +{&} ')'); @@ -779,7 +803,7 @@ function lengthOrd(t: PType): biggestInt; begin case t.kind of tyInt64, tyInt32, tyInt: result := lastOrd(t); - tyAbstract: result := lengthOrd(t.sons[0]); + tyDistinct: result := lengthOrd(t.sons[0]); else result := lastOrd(t) - firstOrd(t) + 1; end end; @@ -868,7 +892,7 @@ begin SameLiteral(a.sons[1], b.sons[1]) end; -function sameTuple(a, b: PType; AbstractOf: bool): boolean; +function sameTuple(a, b: PType; DistinctOf: bool): boolean; // two tuples are equivalent iff the names, types and positions are the same; // however, both types may not have any field names (t.n may be nil) which // complicates the matter a bit. @@ -879,8 +903,8 @@ begin if sonsLen(a) = sonsLen(b) then begin result := true; for i := 0 to sonsLen(a)-1 do begin - if AbstractOf then - result := equalOrAbstractOf(a.sons[i], b.sons[i]) + if DistinctOf then + result := equalOrDistinctOf(a.sons[i], b.sons[i]) else result := SameType(a.sons[i], b.sons[i]); if not result then exit @@ -914,15 +938,15 @@ begin if a.kind <> b.kind then begin result := false; exit end; case a.Kind of tyEmpty, tyChar, tyBool, tyNil, tyPointer, tyString, tyCString, - tyInt..tyFloat128: + tyInt..tyFloat128, tyExpr, tyStmt, tyTypeDesc: result := true; - tyEnum, tyForward, tyObject, tyAbstract: + tyEnum, tyForward, tyObject, tyDistinct: result := (a.id = b.id); tyTuple: result := sameTuple(a, b, false); tyGenericInst: result := sameType(lastSon(a), lastSon(b)); - tyGenericParam, tyGeneric, tySequence, tyOrdinal, + tyGenericParam, tyGenericInvokation, tyGenericBody, tySequence, tyOrdinal, tyOpenArray, tySet, tyRef, tyPtr, tyVar, tyArrayConstr, tyArray, tyProc: begin if sonsLen(a) = sonsLen(b) then begin @@ -946,7 +970,7 @@ begin end end; -function equalOrAbstractOf(x, y: PType): bool; +function equalOrDistinctOf(x, y: PType): bool; var i: int; a, b: PType; @@ -958,26 +982,26 @@ begin assert(a <> nil); assert(b <> nil); if a.kind <> b.kind then begin - if a.kind = tyAbstract then a := a.sons[0]; + if a.kind = tyDistinct then a := a.sons[0]; if a.kind <> b.kind then begin result := false; exit end end; case a.Kind of tyEmpty, tyChar, tyBool, tyNil, tyPointer, tyString, tyCString, - tyInt..tyFloat128: + tyInt..tyFloat128, tyExpr, tyStmt, tyTypeDesc: result := true; - tyEnum, tyForward, tyObject, tyAbstract: + tyEnum, tyForward, tyObject, tyDistinct: result := (a.id = b.id); tyTuple: result := sameTuple(a, b, true); tyGenericInst: - result := equalOrAbstractOf(lastSon(a), lastSon(b)); - tyGenericParam, tyGeneric, tySequence, tyOrdinal, + result := equalOrDistinctOf(lastSon(a), lastSon(b)); + tyGenericParam, tyGenericInvokation, tyGenericBody, tySequence, tyOrdinal, tyOpenArray, tySet, tyRef, tyPtr, tyVar, tyArrayConstr, tyArray, tyProc: begin if sonsLen(a) = sonsLen(b) then begin result := true; for i := 0 to sonsLen(a)-1 do begin - result := equalOrAbstractOf(a.sons[i], b.sons[i]); + result := equalOrDistinctOf(a.sons[i], b.sons[i]); if not result then exit end; if result and (a.kind = tyProc) then @@ -987,7 +1011,7 @@ begin result := false; end; tyRange: begin - result := equalOrAbstractOf(a.sons[0], b.sons[0]) + result := equalOrDistinctOf(a.sons[0], b.sons[0]) and SameValue(a.n.sons[0], b.n.sons[0]) and SameValue(a.n.sons[1], b.n.sons[1]) end; @@ -995,7 +1019,7 @@ begin end end; -function typeAllowedAux(var marker: TIntSet; t: PType; +function typeAllowedAux(var marker: TIntSet; typ: PType; kind: TSymKind): bool; forward; function typeAllowedNode(var marker: TIntSet; n: PNode; kind: TSymKind): bool; @@ -1005,6 +1029,7 @@ begin result := true; if n <> nil then begin result := typeAllowedAux(marker, n.typ, kind); + if not result then debug(n.typ); if result then case n.kind of nkNone..nkNilLit: begin end; @@ -1018,24 +1043,27 @@ begin end end; -function typeAllowedAux(var marker: TIntSet; t: PType; kind: TSymKind): bool; +function typeAllowedAux(var marker: TIntSet; typ: PType; kind: TSymKind): bool; var i: int; + t, t2: PType; begin assert(kind in [skVar, skConst, skParam]); result := true; - if t = nil then exit; + if typ = nil then exit; // if we have already checked the type, return true, because we stop the // evaluation if something is wrong: - if IntSetContainsOrIncl(marker, t.id) then exit; - case skipTypes(t, abstractInst).kind of + if IntSetContainsOrIncl(marker, typ.id) then exit; + t := skipTypes(typ, abstractInst); + case t.kind of tyVar: begin - case skipTypes(t.sons[0], abstractInst).kind of + t2 := skipTypes(t.sons[0], abstractInst); + case t2.kind of tyVar: result := false; // ``var var`` is always an invalid type: tyOpenArray: result := (kind = skParam) and - typeAllowedAux(marker, t.sons[0], kind); + typeAllowedAux(marker, t2, kind); else result := (kind <> skConst) and - typeAllowedAux(marker, t.sons[0], kind); + typeAllowedAux(marker, t2, kind); end end; tyProc: begin @@ -1046,12 +1074,16 @@ begin if t.sons[0] <> nil then result := typeAllowedAux(marker, t.sons[0], skVar) end; - tyGeneric, tyGenericParam, tyForward, tyNone: result := false; + tyExpr, tyStmt, tyTypeDesc: result := true; + tyGenericBody, tyGenericParam, tyForward, tyNone, tyGenericInvokation: begin + result := false; + //InternalError('shit found'); + end; tyEmpty, tyNil: result := kind = skConst; tyString, tyBool, tyChar, tyEnum, tyInt..tyFloat128, tyCString, tyPointer: result := true; tyOrdinal: result := kind = skParam; - tyGenericInst, tyAbstract: + tyGenericInst, tyDistinct: result := typeAllowedAux(marker, lastSon(t), kind); tyRange: result := skipTypes(t.sons[0], abstractInst).kind in @@ -1074,8 +1106,8 @@ begin result := typeAllowedAux(marker, t.sons[i], skVar); if not result then exit end; - if t.n <> nil then result := typeAllowedNode(marker, t.n, skVar) - end + if t.n <> nil then result := typeAllowedNode(marker, t.n, skVar); + end; end end; @@ -1221,7 +1253,7 @@ begin if result < 0 then exit; maxAlign := a end - else if typ.kind = tyObject then begin + else if isObjectWithTypeFieldPredicate(typ) then begin result := intSize; maxAlign := result; end else begin @@ -1233,7 +1265,7 @@ begin if a < maxAlign then a := maxAlign; result := align(result, a); end; - tyGenericInst, tyAbstract: begin + tyGenericInst, tyDistinct, tyGenericBody: begin result := computeSizeAux(lastSon(typ), a); end; else begin diff --git a/nim/wordrecg.pas b/nim/wordrecg.pas index 1f4513ed5..9bf3de256 100644..100755 --- a/nim/wordrecg.pas +++ b/nim/wordrecg.pas @@ -39,10 +39,10 @@ type // i = i + 1 //cog.out(idents) //]]] - wAbstract, wAddr, wAnd, wAs, - wAsm, wBind, wBlock, wBreak, - wCase, wCast, wConst, wContinue, - wConverter, wDiscard, wDiv, wElif, + wAddr, wAnd, wAs, wAsm, + wBind, wBlock, wBreak, wCase, + wCast, wConst, wContinue, wConverter, + wDiscard, wDistinct, wDiv, wElif, wElse, wEnd, wEnum, wExcept, wFinally, wFor, wFrom, wGeneric, wIf, wImplies, wImport, wIn, @@ -81,13 +81,13 @@ type wBorrow, wRun, wR, wVerbosity, wV, wHelp, wH, wSymbolFiles, wFieldChecks, wX, wVersion, wAdvanced, wSkipcfg, wSkipProjCfg, wCc, wGenscript, wCheckPoint, wCheckPoints, - wMaxErr, wExpr, wStmt, wTypeDesc, - wSubsChar, wAstCache, wAcyclic, wIndex, + wNoMain, + wSubsChar, wAcyclic, wIndex, // commands: wCompileToC, wCompileToCpp, wCompileToEcmaScript, wCompileToLLVM, wPretty, wDoc, wPas, wGenDepend, wListDef, wCheck, wParse, wScan, wBoot, wLazy, - wRst2html, wI, + wRst2html, wRst2tex, wI, // special for the preprocessor of configuration files: wWrite, wPutEnv, wPrependEnv, wAppendEnv, // additional Pascal keywords: @@ -107,16 +107,15 @@ type const oprLow = ord(wColon); oprHigh = ord(wHat); - specialWords: array [low(TSpecialWord)..high(TSpecialWord)] - of string = ('', + specialWords: array [low(TSpecialWord)..high(TSpecialWord)] of string = ('', // keywords: //[[[cog //cog.out(strings) //]]] - 'abstract', 'addr', 'and', 'as', - 'asm', 'bind', 'block', 'break', - 'case', 'cast', 'const', 'continue', - 'converter', 'discard', 'div', 'elif', + 'addr', 'and', 'as', 'asm', + 'bind', 'block', 'break', 'case', + 'cast', 'const', 'continue', 'converter', + 'discard', 'distinct', 'div', 'elif', 'else', 'end', 'enum', 'except', 'finally', 'for', 'from', 'generic', 'if', 'implies', 'import', 'in', @@ -155,12 +154,12 @@ const 'borrow', 'run', 'r'+'', 'verbosity', 'v'+'', 'help', 'h'+'', 'symbolfiles', 'fieldchecks', 'x'+'', 'version', 'advanced', 'skipcfg', 'skipprojcfg', 'cc', 'genscript', 'checkpoint', 'checkpoints', - 'maxerr', 'expr', 'stmt', 'typedesc', - 'subschar', 'astcache', 'acyclic', 'index', + 'nomain', + 'subschar', 'acyclic', 'index', // commands: 'compiletoc', 'compiletocpp', 'compiletoecmascript', 'compiletollvm', 'pretty', 'doc', 'pas', 'gendepend', 'listdef', 'check', 'parse', - 'scan', 'boot', 'lazy', 'rst2html', 'i'+'', + 'scan', 'boot', 'lazy', 'rst2html', 'rst2tex', 'i'+'', // special for the preprocessor of configuration files: 'write', 'putenv', 'prependenv', 'appendenv', |