too many changes to list

This commit is contained in:
Andreas Rumpf 2008-08-23 11:16:44 +02:00
commit 07d5a8085b
200 changed files with 24344 additions and 17809 deletions

View file

@ -2,6 +2,10 @@
# (c) 2008 Andreas Rumpf # (c) 2008 Andreas Rumpf
# Feel free to edit the templates as you need. # Feel free to edit the templates as you need.
split.item.toc = "25"
# too long entries in the table of contents get truncated
# after this number of characters
doc.section = """ doc.section = """
<div class="section" id="$sectionID"> <div class="section" id="$sectionID">
<h1><a class="toc-backref" href="#$sectionTitleID">$sectionTitle</a></h1> <h1><a class="toc-backref" href="#$sectionTitleID">$sectionTitle</a></h1>
@ -52,10 +56,10 @@ $content
""" """
doc.file = """<?xml version="1.0" encoding="utf-8" ?> doc.file = """<?xml version="1.0" encoding="utf-8" ?>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<!-- This file is generated by Nimrod. --> <!-- This file is generated by Nimrod. -->
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head> <head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>$title</title> <title>$title</title>
@ -88,7 +92,7 @@ span.Command, span.Rule, span.Hyperlink, span.Label, span.Reference,
span.Other {color: black} span.Other {color: black}
div.navigation { div.navigation {
float: left; width: 20em; float: left; width: 25em;
margin: 0; padding: 0; /* margin: 0; padding: 0; /*
border: 1px dashed gold; */ border: 1px dashed gold; */
outline: 3px outset #99ff99; //gold; outline: 3px outset #99ff99; //gold;
@ -109,7 +113,7 @@ div.navigation ul li a:hover {
} }
div.content { div.content {
margin-left: 20em; margin-left: 25em;
padding: 0 1em; padding: 0 1em;
border: 1px dashed gold; border: 1px dashed gold;
min-width: 16em; min-width: 16em;
@ -285,4 +289,3 @@ $content
</html> </html>
""" """
@write "used doctempl.cfg"

View file

@ -9,7 +9,7 @@
# Environment variables cannot be used in the options, however! # Environment variables cannot be used in the options, however!
# Just call the compiler with several options: # Just call the compiler with several options:
cc = @if unix: gcc @else: llvm_gcc @end cc = @if unix: gcc @else: vcc @end
lib="$nimrod/lib" lib="$nimrod/lib"
path="$lib/base" path="$lib/base"
path="$lib/base/gtk" path="$lib/base/gtk"
@ -17,13 +17,22 @@ path="$lib/base/cairo"
path="$lib/base/x11" path="$lib/base/x11"
path="$lib/windows" path="$lib/windows"
path="$lib/posix" path="$lib/posix"
path="$lib/ecmas"
path="$lib/extra" path="$lib/extra"
@if release:
checks:off
stacktrace:off
debugger:off
line_dir:off
@end
# additional defines: # additional defines:
#define="" #define=""
# additional options always passed to the compiler: # additional options always passed to the compiler:
force_build force_build
line_dir=off line_dir=off
cfilecache=on
hint[LineTooLong]=off hint[LineTooLong]=off
hint[XDeclaredButNotUsed]=off hint[XDeclaredButNotUsed]=off
@ -40,7 +49,7 @@ hint[XDeclaredButNotUsed]=off
# Configuration for the LLVM GCC compiler: # Configuration for the LLVM GCC compiler:
@if windows: @if windows:
llvm_gcc.path = r"dist\llvm-gcc4.2\bin" llvm_gcc.path = r"$nimrod\dist\llvm-gcc4.2\bin"
@end @end
llvm_gcc.options.debug = "-g" llvm_gcc.options.debug = "-g"
llvm_gcc.options.always = "-w" llvm_gcc.options.always = "-w"
@ -59,14 +68,15 @@ bcc.options.size = "-O1 -6"
# Configuration for the Visual C/C++ compiler: # Configuration for the Visual C/C++ compiler:
@if vcc: @if vcc:
@prepend_env path r"C:\Eigenes\compiler\vcc2005\Common7\IDE;" @prepend_env path r"C:\Programme\Microsoft Visual Studio 9.0\Common7\IDE;"
@prepend_env INCLUDE r"C:\Eigenes\compiler\vcc2005\VC\include;C:\Eigenes\compiler\vcc2005\VC\ATLMFC\INCLUDE;" @prepend_env INCLUDE r"C:\Programme\Microsoft Visual Studio 9.0\VC\include;C:\Programme\Microsoft Visual Studio 9.0\VC\ATLMFC\INCLUDE;C:\Programme\Microsoft SDKs\Windows\v6.0A\Include;"
@prepend_env LIB r"C:\Eigenes\compiler\vcc2005\VC\lib;C:\Eigenes\compiler\vcc2005\SDK\v2.0\Lib;" @prepend_env LIB r"C:\Programme\Microsoft Visual Studio 9.0\VC\lib;C:\Programme\Microsoft Visual Studio 9.0\SDK\v2.0\Lib;C:\Programme\Microsoft SDKs\Windows\v6.0A\Lib;"
passl: r"/F33554432" # set the stack size to 8 MB
@end @end
@if windows: @if windows:
vcc.path = r"C:\Eigenes\compiler\vcc2005\VC\bin" vcc.path = r"C:\Programme\Microsoft Visual Studio 9.0\VC\bin"
@end @end
vcc.options.debug = "/GZ /ZI" vcc.options.debug = "/RTC1 /ZI"
vcc.options.always = "/nologo" vcc.options.always = "/nologo"
vcc.options.speed = "/Ogityb2 /G7 /arch:SSE2" vcc.options.speed = "/Ogityb2 /G7 /arch:SSE2"
vcc.options.size = "/O1 /G7" vcc.options.size = "/O1 /G7"
@ -113,10 +123,11 @@ lcc.options.size = "-O -p6"
# Configuration for the Tiny C Compiler: # Configuration for the Tiny C Compiler:
@if windows: @if windows:
tcc.path = r"C:\eigenes\compiler\tcc\bin" tcc.path = r"C:\Eigenes\compiler\tcc-0.9.23\tcc"
tcc.options.always = r"-IC:\Eigenes\compiler\tcc-0.9.23\include " &
r"-IC:\Eigenes\compiler\tcc-0.9.23\include\winapi"
@end @end
tcc.options.debug = "-b" tcc.options.debug = ""
tcc.options.always = ""
tcc.options.speed = "" tcc.options.speed = ""
tcc.options.size = "" tcc.options.size = ""
@ -137,4 +148,9 @@ icc.options.always = "-w"
icc.options.speed = "-O3 -ffast-math" icc.options.speed = "-O3 -ffast-math"
icc.options.size = "-Os -ffast-math" icc.options.size = "-Os -ffast-math"
@write "used default config file" @write "used special config file"
@if ecmascript:
@write "Target is ECMAScript! No unsafe features are allowed!"
@end

View file

@ -9,7 +9,7 @@
{ {
'SymFlag': [ # already 32 flags! 'SymFlag': [ # already 32 flags!
'sfGeneric', # whether an operator, proc or type is generic 'sfTypeCheck', # wether macro parameters should be type checked
'sfForward', # symbol is forward directed 'sfForward', # symbol is forward directed
'sfImportc', # symbol is external; imported 'sfImportc', # symbol is external; imported
'sfExportc', # symbol is exported (under a specified name) 'sfExportc', # symbol is exported (under a specified name)
@ -26,7 +26,7 @@
'sfMainModule', # module is the main module 'sfMainModule', # module is the main module
'sfSystemModule', # module is the system module 'sfSystemModule', # module is the system module
'sfNoReturn', # proc never returns (an exit proc) 'sfNoReturn', # proc never returns (an exit proc)
'sfReturnsNew', # proc returns new allocated thing (allows optimizations) 'sfAddrTaken', # the variable's address is taken (ex- or implicitely)
'sfInInterface', # symbol is in interface section declared 'sfInInterface', # symbol is in interface section declared
'sfNoStatic', # symbol is used within an iterator (needed for codegen) 'sfNoStatic', # symbol is used within an iterator (needed for codegen)
# so it cannot be 'static' in the C code # so it cannot be 'static' in the C code
@ -56,19 +56,19 @@
# is used to speed up semantic checking a bit # is used to speed up semantic checking a bit
'tfEnumHasWholes', # enum cannot be mapped into a range 'tfEnumHasWholes', # enum cannot be mapped into a range
'tfVarargs', # procedure has C styled varargs 'tfVarargs', # procedure has C styled varargs
'tfAssignable' # can the type be assigned to? 'tfFinal' # is the object final?
], ],
'TypeKind': [ # order is important! 'TypeKind': [ # order is important!
# Don't forget to change hti.nim if you make a change here # Don't forget to change hti.nim if you make a change here
'tyNone', 'tyBool', 'tyChar', 'tyNone', 'tyBool', 'tyChar',
'tyEmptySet', 'tyArrayConstr', 'tyNil', 'tyRecordConstr', 'tyEmptySet', 'tyArrayConstr', 'tyNil',
'tyGeneric', 'tyGeneric',
'tyGenericInst', # instantiated generic type 'tyGenericInst', # instantiated generic type
'tyGenericParam', 'tyGenericParam',
'tyEnum', 'tyAnyEnum', 'tyEnum',
'tyAnyEnum',
'tyArray', 'tyArray',
'tyRecord',
'tyObject', 'tyObject',
'tyTuple', 'tyTuple',
'tySet', 'tySet',
@ -84,6 +84,14 @@
'tyFloat', 'tyFloat32', 'tyFloat64', 'tyFloat128' 'tyFloat', 'tyFloat32', 'tyFloat64', 'tyFloat128'
], ],
'NodeFlag': [ # keep this number under 16 for performance reasons!
'nfNone',
'nfBase2', # nfBase10 is default, so not needed
'nfBase8',
'nfBase16',
'nfAllConst' # used to mark complex expressions constant
],
'NodeKind': [ # these are pure nodes 'NodeKind': [ # these are pure nodes
# order is extremely important, because ranges are used to check whether # order is extremely important, because ranges are used to check whether
# a node belongs to a certain class # a node belongs to a certain class
@ -97,7 +105,6 @@
'nkType', # node is used for its typ field 'nkType', # node is used for its typ field
'nkCharLit', # a character literal '' 'nkCharLit', # a character literal ''
'nkRCharLit', # a raw character literal r''
'nkIntLit', # an integer literal 'nkIntLit', # an integer literal
'nkInt8Lit', 'nkInt8Lit',
@ -110,6 +117,8 @@
'nkStrLit', # a string literal "" 'nkStrLit', # a string literal ""
'nkRStrLit', # a raw string literal r"" 'nkRStrLit', # a raw string literal r""
'nkTripleStrLit', # a triple string literal """ 'nkTripleStrLit', # a triple string literal """
'nkMetaNode', # difficult to explan; represents itself
# (used for macros)
'nkNilLit', # the nil literal 'nkNilLit', # the nil literal
# end of atoms # end of atoms
'nkDotCall', # used to temporarily flag a nkCall node; this is used 'nkDotCall', # used to temporarily flag a nkCall node; this is used
@ -126,7 +135,7 @@
'nkInfix', # a call like (a + b) 'nkInfix', # a call like (a + b)
'nkPrefix', # a call like !a 'nkPrefix', # a call like !a
'nkPostfix', # something like a! (also used for visibility) 'nkPostfix', # something like a! (also used for visibility)
'nkPar', # syntactic () 'nkPar', # syntactic (); may be a tuple constructor
'nkCurly', # syntactic {} 'nkCurly', # syntactic {}
'nkBracket', # syntactic [] 'nkBracket', # syntactic []
'nkBracketExpr', # an expression like a[i..j, k] 'nkBracketExpr', # an expression like a[i..j, k]
@ -142,14 +151,7 @@
'nkAccQuoted', # `a` as a node 'nkAccQuoted', # `a` as a node
'nkHeaderQuoted', # `a(x: int)` as a node 'nkHeaderQuoted', # `a(x: int)` as a node
'nkSetConstr', # a set constructor {}
'nkConstSetConstr', # a set constructor with only constant expressions
'nkArrayConstr', # an array constructor []
'nkConstArrayConstr', # an array constructor with only constant expressions
'nkRecordConstr', # a record constructor []
'nkConstRecordConstr', # a record constructor with only constant expressions
'nkTableConstr', # a table constructor {expr: expr} 'nkTableConstr', # a table constructor {expr: expr}
'nkConstTableConstr', # a table constructor with only constant expressions
'nkQualified', # describes a.b for qualified identifiers 'nkQualified', # describes a.b for qualified identifiers
'nkHiddenStdConv', # an implicit standard type conversion 'nkHiddenStdConv', # an implicit standard type conversion
'nkHiddenSubConv', # an implicit type conversion from a subtype 'nkHiddenSubConv', # an implicit type conversion from a subtype
@ -158,6 +160,16 @@
'nkConv', # a type conversion 'nkConv', # a type conversion
'nkCast', # a type cast 'nkCast', # a type cast
'nkAddr', # a addr expression 'nkAddr', # a addr expression
'nkHiddenAddr', # implicit address operator
'nkHiddenDeref', # implicit ^ operator
'nkObjDownConv', # down conversion between object types
'nkObjUpConv', # up conversion between object types
'nkChckRangeF', # range check for floats
'nkChckRange64', # range check for 64 bit ints
'nkChckRange', # range check for ints
'nkStringToCString', # string to cstring
'nkCStringToString', # cstring to string
'nkPassAsOpenArray', # thing is passed as an open array
# end of expressions # end of expressions
'nkAsgn', # a = b 'nkAsgn', # a = b
@ -198,8 +210,6 @@
'nkBreakStmt', # a break statement 'nkBreakStmt', # a break statement
'nkContinueStmt', # a continue statement 'nkContinueStmt', # a continue statement
'nkBlockStmt', # a block statement 'nkBlockStmt', # a block statement
'nkGotoStmt', # used by the transformation pass; first son is a sym
# node containing a label
'nkDiscardStmt', # a discard statement 'nkDiscardStmt', # a discard statement
'nkStmtList', # a list of statements 'nkStmtList', # a list of statements
'nkImportStmt', # an import statement 'nkImportStmt', # an import statement
@ -218,8 +228,8 @@
# types as syntactic trees: # types as syntactic trees:
'nkTypeOfExpr', 'nkTypeOfExpr',
'nkRecordTy',
'nkObjectTy', 'nkObjectTy',
'nkTupleTy',
'nkRecList', # list of record/object parts 'nkRecList', # list of record/object parts
'nkRecCase', # case section of record/object 'nkRecCase', # case section of record/object
'nkRecWhen', # when section of record/object 'nkRecWhen', # when section of record/object
@ -228,7 +238,8 @@
'nkVarTy', 'nkVarTy',
'nkProcTy', 'nkProcTy',
'nkEnumTy', 'nkEnumTy',
'nkEnumFieldDef' # `ident = expr` in an enumeration 'nkEnumFieldDef', # `ident = expr` in an enumeration
'nkReturnToken', # token used for interpretation
], ],
'SymKind': [ 'SymKind': [

View file

@ -4,6 +4,7 @@ Command::
compile compile project with default code generator (C) compile compile project with default code generator (C)
compile_to_c compile project with C code generator compile_to_c compile project with C code generator
compile_to_cpp compile project with C++ code generator compile_to_cpp compile project with C++ code generator
compile_to_ecmascript compile project to ECMAScript code (experimental)
doc generate the documentation for inputfile; doc generate the documentation for inputfile;
with --run switch opens it with $BROWSER with --run switch opens it with $BROWSER
Arguments: Arguments:
@ -18,6 +19,8 @@ Options:
--line_trace:on|off code generation for line trace ON|OFF --line_trace:on|off code generation for line trace ON|OFF
--debugger:on|off turn Embedded Nimrod Debugger ON|OFF --debugger:on|off turn Embedded Nimrod Debugger ON|OFF
-x, --checks:on|off code generation for all runtime checks ON|OFF -x, --checks:on|off code generation for all runtime checks ON|OFF
--obj_checks:on|off code generation for obj conversion checks ON|OFF
--field_checks:on|off code generation for case record fields ON|OFF
--range_checks:on|off code generation for range checks ON|OFF --range_checks:on|off code generation for range checks ON|OFF
--bound_checks:on|off code generation for bound checks ON|OFF --bound_checks:on|off code generation for bound checks ON|OFF
--overflow_checks:on|off code generation for over-/underflow checks ON|OFF --overflow_checks:on|off code generation for over-/underflow checks ON|OFF

View file

@ -10,9 +10,9 @@ macro method mod
nil not notin nil not notin
object of or out object of or out
proc ptr proc ptr
raise record ref return raise ref return
shl shr shl shr
template try type template try tuple type
var var
when where while with without when where while with without
xor xor

View file

@ -113,8 +113,13 @@
'UnaryPlusF64', 'UnaryPlusF64',
'UnaryMinusF64', 'UnaryMinusF64',
'AbsF64', 'AbsF64',
'Ze', 'Ze8ToI',
'Ze64', 'Ze8ToI64',
'Ze16ToI',
'Ze16ToI64',
'Ze32ToI64',
'ZeIToI64',
'ToU8', 'ToU8',
'ToU16', 'ToU16',
'ToU32', 'ToU32',
@ -123,6 +128,14 @@
'ToInt', 'ToInt',
'ToBiggestInt', 'ToBiggestInt',
'CharToStr',
'BoolToStr',
'IntToStr', # $ for ints
'Int64ToStr',
'FloatToStr',
'CStrToStr',
'StrToStr',
# special ones: # special ones:
'And', 'And',
'Or', 'Or',
@ -156,12 +169,12 @@
'SetLengthSeq', 'SetLengthSeq',
'Assert', 'Assert',
'Swap', 'Swap',
'IsNil',
# magic type constructors: # magic type constructors:
'Array', 'Array',
'OpenArray', 'OpenArray',
'Range', 'Range',
'Tuple',
'Set', 'Set',
'Seq', 'Seq',
@ -172,5 +185,38 @@
'NimrodMajor', 'NimrodMajor',
'NimrodMinor', 'NimrodMinor',
'NimrodPatch', 'NimrodPatch',
'CpuEndian' 'CpuEndian',
'NaN',
'Inf',
'NegInf',
# magics for modifying the AST (macro support)
'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'
] ]

View file

@ -23,7 +23,7 @@
{'errInvalidToken': 'invalid token: $1'}, {'errInvalidToken': 'invalid token: $1'},
{'errLineTooLong': 'line too long'}, {'errLineTooLong': 'line too long'},
{'errInvalidNumber': '$1 is not a valid number'}, {'errInvalidNumber': '$1 is not a valid number'},
{'errNumberOutOfRange': '$1 is too large or too small'}, {'errNumberOutOfRange': 'number $1 out of valid range'},
{'errNnotAllowedInCharacter': '\\n not allowed in character literal'}, {'errNnotAllowedInCharacter': '\\n not allowed in character literal'},
{'errClosingBracketExpected': "closing ']' expected, but end of file reached"}, {'errClosingBracketExpected': "closing ']' expected, but end of file reached"},
{'errMissingFinalQuote': "missing final '"}, {'errMissingFinalQuote': "missing final '"},
@ -32,10 +32,6 @@
{'errTokenExpected': "'$1' expected"}, {'errTokenExpected': "'$1' expected"},
{'errStringAfterIncludeExpected': "string after 'include' expected"}, {'errStringAfterIncludeExpected': "string after 'include' expected"},
{'errRecursiveInclude': "recursive include file: '$1'"}, {'errRecursiveInclude': "recursive include file: '$1'"},
{'errAtIfExpected': "'@if' expected"},
{'errAtIfExpectedBeforeElse': "'@if' expected before '@else'"},
{'errAtIfExpectedBeforeElif': "'@if' expected before '@elif'"},
{'errAtEndExpected': "'@end' expected"},
{'errOnOrOffExpected': "'on' or 'off' expected"}, {'errOnOrOffExpected': "'on' or 'off' expected"},
{'errNoneSpeedOrSizeExpected': "'none', 'speed' or 'size' expected"}, {'errNoneSpeedOrSizeExpected': "'none', 'speed' or 'size' expected"},
{'errInvalidPragma': 'invalid pragma'}, {'errInvalidPragma': 'invalid pragma'},
@ -157,13 +153,13 @@
{'errSizeTooBig': "computing the type's size produced an overflow"}, {'errSizeTooBig': "computing the type's size produced an overflow"},
{'errSetTooBig': 'set is too large'}, {'errSetTooBig': 'set is too large'},
{'errBaseTypeMustBeOrdinal': 'base type of a set must be an ordinal'}, {'errBaseTypeMustBeOrdinal': 'base type of a set must be an ordinal'},
{'errInheritanceOnlyWithObjects': 'inheritance only works with an object'}, {'errInheritanceOnlyWithNonFinalObjects': 'inheritance only works non-final objects'},
{'errInheritanceOnlyWithEnums': 'inheritance only works with an enum'}, {'errInheritanceOnlyWithEnums': 'inheritance only works with an enum'},
{'errIllegalRecursionInTypeX': "illegal recursion in type '$1'"}, {'errIllegalRecursionInTypeX': "illegal recursion in type '$1'"},
{'errCannotInstantiateX': "cannot instantiate: '$1'"}, {'errCannotInstantiateX': "cannot instantiate: '$1'"},
{'errExprHasNoAddress': 'expression has no address'}, {'errExprHasNoAddress': "expression has no address"},
{'errVarForOutParamNeeded': {'errVarForOutParamNeeded':
'to an out parameter a variable needs to be passed'}, "for a 'var' type a variable needs to be passed"},
{'errPureTypeMismatch': 'type mismatch'}, {'errPureTypeMismatch': 'type mismatch'},
{'errTypeMismatch': 'type mismatch: got ('}, {'errTypeMismatch': 'type mismatch: got ('},
{'errButExpected': 'but expected one of: '}, {'errButExpected': 'but expected one of: '},
@ -243,6 +239,20 @@
{'errWhitespaceExpected': "whitespace expected, got '$1'"}, {'errWhitespaceExpected': "whitespace expected, got '$1'"},
{'errXisNoValidIndexFile': "'$1' is no valid index file"}, {'errXisNoValidIndexFile': "'$1' is no valid index file"},
{'errCannotRenderX': "cannot render reStructuredText element '$1'"}, {'errCannotRenderX': "cannot render reStructuredText element '$1'"},
{'errVarVarTypeNotAllowed': "type 'var var' is not allowed"},
{'errIsExpectsTwoArguments': "'is' expects two arguments"},
{'errIsExpectsObjectTypes': "'is' expects object types"},
{'errXcanNeverBeOfThisSubtype': "'$1' can never be of this subtype"},
{'errTooManyIterations': "interpretation requires too many iterations"},
{'errCannotInterpretNodeX': "cannot interpret node kind '$1'"},
{'errFieldXNotFound': "field '$1' cannot be found"},
{'errInvalidConversionFromTypeX': "invalid conversion from type '$1'"},
{'errAssertionFailed': "assertion failed"},
{'errCannotGenerateCodeForX': "cannot generate code for '$1'"},
{'errXNeedsReturnType': "converter needs return type"},
{'errXRequiresOneArgument': "converter requires one parameter"},
{'errUnhandledExceptionX': "unhandled exception: $1"},
{'errCyclicTree': "macro returned a cyclic abstract syntax tree"},
# user error message: # user error message:
{'errUser': '$1'}, {'errUser': '$1'},
@ -276,6 +286,8 @@
{'hintMo2FileInvalid': "mo2 file '$1' is invalid"}, {'hintMo2FileInvalid': "mo2 file '$1' is invalid"},
{'hintModuleHasChanged': "module '$1' has been changed"}, {'hintModuleHasChanged': "module '$1' has been changed"},
{'hintCannotOpenMo2File': "mo2 file '$1' does not exist"}, {'hintCannotOpenMo2File': "mo2 file '$1' does not exist"},
{'hintQuitCalled': "quit() called"},
{'hintProcessing': "processing"},
# user hint message: # user hint message:
{'hintUser': '$1'} {'hintUser': '$1'}

View file

@ -3,6 +3,9 @@
The documentation consists of several documents: The documentation consists of several documents:
- | `First steps after installation <steps.html>`_
| Read this after installation for a quick introduction.
- | `Nimrod manual <manual.html>`_ - | `Nimrod manual <manual.html>`_
| Read this to get to know the Nimrod programming system. | Read this to get to know the Nimrod programming system.
@ -23,4 +26,3 @@ The documentation consists of several documents:
- | `Index <theindex.html>`_ - | `Index <theindex.html>`_
| The generated index. Often the quickest way to find the piece of | The generated index. Often the quickest way to find the piece of
information you need. information you need.

View file

@ -78,6 +78,7 @@ typeDescK ::= VAR typeDesc
| REF typeDesc | REF typeDesc
| PTR typeDesc | PTR typeDesc
| TYPE expr | TYPE expr
| TUPLE tupleDesc
| PROC paramList [pragma] | PROC paramList [pragma]
typeDesc ::= typeDescK | primary typeDesc ::= typeDescK | primary
@ -157,23 +158,23 @@ colonAndEquals ::= [COLON typeDesc] EQUALS expr
constDecl ::= symbol ["*"] [pragma] colonAndEquals [COMMENT | IND COMMENT] constDecl ::= symbol ["*"] [pragma] colonAndEquals [COMMENT | IND COMMENT]
| COMMENT | COMMENT
constSection ::= CONST indPush constDecl (SAD constDecl)* DED constSection ::= CONST indPush constDecl (SAD constDecl)* DED
typeDef ::= typeDesc | recordDef | objectDef | enumDef typeDef ::= typeDesc | objectDef | enumDef
recordIdentPart ::= objectIdentPart ::=
(symbol ["*" | "-"] [pragma] optComma)+ COLON typeDesc [COMMENT | IND COMMENT] (symbol ["*" | "-"] [pragma] optComma)+ COLON typeDesc [COMMENT | IND COMMENT]
recordWhen ::= WHEN expr COLON [COMMENT] recordPart objectWhen ::= WHEN expr COLON [COMMENT] objectPart
(ELIF expr COLON [COMMENT] recordPart)* (ELIF expr COLON [COMMENT] objectPart)*
[ELSE COLON [COMMENT] recordPart] [ELSE COLON [COMMENT] objectPart]
recordCase ::= CASE expr COLON typeDesc [COMMENT] objectCase ::= CASE expr COLON typeDesc [COMMENT]
(OF sliceList COLON [COMMENT] recordPart)* (OF sliceList COLON [COMMENT] objectPart)*
[ELSE COLON [COMMENT] recordPart] [ELSE COLON [COMMENT] objectPart]
recordPart ::= recordWhen | recordCase | recordIdentPart objectPart ::= objectWhen | objectCase | objectIdentPart
| indPush recordPart (SAD recordPart)* DED | indPush objectPart (SAD objectPart)* DED
recordDef ::= RECORD [pragma] recordPart tupleDesc ::= BRACKET_LE optInd ((symbol optComma)+ COLON typeDesc optComma)* BRACKET_RI
objectDef ::= OBJECT [pragma] [OF typeDesc] recordPart objectDef ::= OBJECT [pragma] [OF typeDesc] objectPart
enumDef ::= ENUM [OF typeDesc] (symbol [EQUALS expr] optComma [COMMENT | IND COMMENT])+ enumDef ::= ENUM [OF typeDesc] (symbol [EQUALS expr] optComma [COMMENT | IND COMMENT])+
typeDecl ::= COMMENT typeDecl ::= COMMENT

View file

@ -13,36 +13,119 @@ Advanced libraries are in the ``lib/base`` directory.
Basic libraries Basic libraries
=============== ===============
* `System <system.html>`_ * `system <system.html>`_
Basic procs and operators that every program needs. It also provides IO Basic procs and operators that every program needs. It also provides IO
facilities for reading and writing text and binary files. It is imported facilities for reading and writing text and binary files. It is imported
implicitly by the compiler. Do not import it directly. It relies on compiler implicitly by the compiler. Do not import it directly. It relies on compiler
magic to work. magic to work.
* `Strutils <strutils.html>`_ * `strutils <strutils.html>`_
This module contains common string handling operations like converting a This module contains common string handling operations like converting a
string into uppercase, splitting a string into substrings, searching for string into uppercase, splitting a string into substrings, searching for
substrings, replacing substrings. substrings, replacing substrings.
* `OS <os.html>`_ * `os <os.html>`_
Basic operating system facilities like retrieving environment variables, Basic operating system facilities like retrieving environment variables,
reading command line arguments, working with directories, running shell reading command line arguments, working with directories, running shell
commands, etc. This module is -- like any other basic library -- commands, etc. This module is -- like any other basic library --
platform independant. platform independant.
* `Math <math.html>`_ * `math <math.html>`_
Mathematical operations like cosine, square root. Mathematical operations like cosine, square root.
* `Complex <complex.html>`_ * `complex <complex.html>`_
This module implements complex numbers and their mathematical operations. This module implements complex numbers and their mathematical operations.
* `Times <times.html>`_ * `times <times.html>`_
The ``times`` module contains basic support for working with time. The ``times`` module contains basic support for working with time.
* `parseopt <parseopt.html>`_
The ``parseopt`` module implements a command line option parser. This
supports long and short command options with optional values and command line
arguments.
* `parsecfg <parsecfg.html>`_
The ``parsecfg`` module implements a high performance configuration file
parser. The configuration file's syntax is similar to the Windows ``.ini``
format, but much more powerful, as it is not a line based parser. String
literals, raw string literals and triple quote string literals are supported
as in the Nimrod programming language.
* `strtabs <strtabs.html>`_
The ``strtabs`` module implements an efficient hash table that is a mapping
from strings to strings. Supports a case-sensitive, case-insensitive and
style-insensitive mode. An efficient string substitution operator ``%``
for the string table is also provided.
* `hashes <hashes.html>`_
This module implements efficient computations of hash values for diverse
Nimrod types.
* `lexbase <lexbase.html>`_
This is a low leve module that implements an extremely efficent buffering
scheme for lexers and parsers. This is used by the ``parsecfg`` module.
Advanced libaries Advanced libaries
================= =================
* `Regexprs <regexprs.html>`_ * `regexprs <regexprs.html>`_
This module contains procedures and operators for handling regular This module contains procedures and operators for handling regular
expressions. expressions.
* `dialogs <dialogs.html>`_
This module implements portable dialogs for Nimrod; the implementation
builds on the GTK interface. On Windows, native dialogs are shown if
appropriate.
Wrappers
========
Note that the generated HTML for some of these wrappers is so huge, that it is
not contained in the distribution. You can then find them on the website.
* `posix <posix.html>`_
Contains a wrapper for the POSIX standard.
* `windows <windows.html>`_
Contains a wrapper for the Win32 API.
* `shellapi <shellapi.html>`_
Contains a wrapper for the ``shellapi.h`` header.
* `shfolder <shfolder.html>`_
Contains a wrapper for the ``shfolder.h`` header.
* `mmsystem <mmsystem.html>`_
Contains a wrapper for the ``mmsystem.h`` header.
* `ole2 <ole2.html>`_
Contains GUIDs for OLE2 automation support.
* `nb30 <nb30.html>`_
This module contains the definitions for portable NetBIOS 3.0 support.
* `cairo <cairo.html>`_
Wrapper for the cairo library.
* `cairoft <cairoft.html>`_
Wrapper for the cairoft library.
* `cairowin32 <cairowin32.html>`_
Wrapper for the cairowin32 library.
* `cairoxlib <cairoxlib.html>`_
Wrapper for the cairoxlib library.
* `atk <atk.html>`_
Wrapper for the atk library.
* `gdk2 <gdk2.html>`_
Wrapper for the gdk2 library.
* `gdk2pixbuf <gdk2pixbuf.html>`_
Wrapper for the gdk2pixbuf library.
* `gdkglext <gdkglext.html>`_
Wrapper for the gdkglext library.
* `glib2 <glib2.html>`_
Wrapper for the glib2 library.
* `gtk2 <gtk2.html>`_
Wrapper for the gtk2 library.
* `gtkglext <gtkglext.html>`_
Wrapper for the gtkglext library.
* `gtkhtml <gtkhtml.html>`_
Wrapper for the gtkhtml library.
* `libglade2 <libglade2.html>`_
Wrapper for the libglade2 library.
* `pango <pango.html>`_
Wrapper for the pango library.
* `pangoutils <pangoutils.html>`_
Wrapper for the pangoutils library.

View file

@ -593,7 +593,7 @@ Structured types
~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~
A variable of a `structured type`:idx: can hold multiple values at the same A variable of a `structured type`:idx: can hold multiple values at the same
time. Stuctured types can be nested to unlimited levels. Arrays, sequences, time. Stuctured types can be nested to unlimited levels. Arrays, sequences,
records, objects and sets belong to the structured types. tuples, objects and sets belong to the structured types.
Array and sequence types Array and sequence types
~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~
@ -638,42 +638,47 @@ checks can be disabled via pragmas or invoking the compiler with the
``--bound_checks:off`` command line switch. ``--bound_checks:off`` command line switch.
Tuples, record and object types Tuples and object types
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~
A variable of a `record`:idx: or `object`:idx: type is a heterogenous storage A variable of a `tuple`:idx: or `object`:idx: type is a heterogenous storage
container. container.
A record or object defines various named *fields* of a type. The assignment A tuple or object defines various named *fields* of a type. A tuple defines an
operator for records and objects always copies the whole record/object. The *order* of the fields additionally. Tuples are meant for heterogenous storage
constructor ``()`` can be used to initialize records/objects. A field may types with no overhead and few abstraction possibilities. The constructor ``()``
be given a default value. Fields with default values do not have to be listed can be used to construct tuples. The order of the fields in the constructor
in a record construction, all other fields have to be listed. must match the order of the tuple's definition. Different tuple-types are
*equivalent* if they specify the same fields of the same type in the same
order.
The assignment operator for tuples copies each component.
The default assignment operator for objects is not defined. The programmer may
provide one, however.
.. code-block:: nimrod .. code-block:: nimrod
type type
TPerson = record # type representing a person TPerson = tuple[name: string, age: int] # type representing a person
name: string # a person consists of a name # a person consists of a name
age: int = 30 # and an age which default value is 30 # and an age
var var
person: TPerson person: TPerson
person = (name: "Peter") # person.age is its default value (30) person = (name: "Peter", age: 30)
# the same, but less readable:
person = ("Peter", 30)
The implementation aligns the fields for best access performance. The alignment The implementation aligns the fields for best access performance. The alignment
is done in a way that is compatible the way the C compiler does it. is done in a way that is compatible the way the C compiler does it.
The difference between records and objects is that objects allow inheritance. Objects provide many features that tuples do not. Object provide inheritance
Objects have access to their type at runtime, so that the ``is`` operator and information hiding. Objects have access to their type at runtime, so that
can be used to determine the object's type. Assignment from an object to its the ``is`` operator can be used to determine the object's type.
parents' object leads to a static or runtime error (the
`EInvalidObjectAssignment`:idx: exception is raised).
.. code-block:: nimrod .. code-block:: nimrod
type type
TPerson = object TPerson = object
name: string name*: string # the * means that `name` is accessible from the outside
age: int age: int # no * means that the field is hidden
TStudent = object of TPerson # a student is a person TStudent = object of TPerson # a student is a person
id: int # with an id field id: int # with an id field
@ -681,10 +686,11 @@ parents' object leads to a static or runtime error (the
var var
student: TStudent student: TStudent
person: TPerson person: TPerson
student = (name: "Peter", age: 89, id: 3)
person = (name: "Mary", age: 17)
assert(student is TStudent) # is true assert(student is TStudent) # is true
person = student # this is an error; person has no storage for id.
Object fields that should be visible outside from the defining module, have to
marked by ``*``. In contrast to tuples, different object types are
never *equivalent*.
Set type Set type
@ -743,15 +749,15 @@ The ``^`` operator can be used to derefer a reference, the ``addr`` procedure
returns the address of an item. An address is always an untraced reference. returns the address of an item. An address is always an untraced reference.
Thus the usage of ``addr`` is an *unsafe* feature. Thus the usage of ``addr`` is an *unsafe* feature.
The ``.`` (access a record field operator) and ``[]`` (array/string/sequence The ``.`` (access a tuple/object field operator)
index operator) operators perform implicit dereferencing operations for and ``[]`` (array/string/sequence index operator) operators perform implicit
reference types: dereferencing operations for reference types:
.. code-block:: nimrod .. code-block:: nimrod
type type
PNode = ref TNode PNode = ref TNode
TNode = record TNode = object
le, ri: PNode le, ri: PNode
data: int data: int
@ -938,8 +944,8 @@ ref or pointer type nil
procedural type nil procedural type nil
sequence nil sequence nil
string nil (**not** "") string nil (**not** "")
tuple[A, B, ...] (default(A), default(B), ...) tuple[x: A, y: B, ...] (default(A), default(B), ...)
(analogous for objects and records) (analogous for objects)
array[0..., T] [default(T), ...] array[0..., T] [default(T), ...]
range[T] default(T); this may be out of the valid range range[T] default(T); this may be out of the valid range
T = enum cast[T](0); this may be an invalid value T = enum cast[T](0); this may be an invalid value
@ -1065,7 +1071,7 @@ exceptions:
The ``when`` statement enables conditional compilation techniques. As The ``when`` statement enables conditional compilation techniques. As
a special syntatic extension, the ``when`` construct is also available a special syntatic extension, the ``when`` construct is also available
within ``record`` or ``object`` definitions. within ``object`` definitions.
Raise statement Raise statement
@ -1117,7 +1123,7 @@ Example:
echo("sum: " & $(parseInt(a) + parseInt(b))) echo("sum: " & $(parseInt(a) + parseInt(b)))
except EOverflow: except EOverflow:
echo("overflow!") echo("overflow!")
except EValue: except EInvalidValue:
echo("could not convert string to integer") echo("could not convert string to integer")
except EIO: except EIO:
echo("IO error!") echo("IO error!")
@ -1411,7 +1417,7 @@ Type sections
Syntax:: Syntax::
typeDef ::= typeDesc | recordDef | objectDef | enumDef typeDef ::= typeDesc | objectDef | enumDef
genericParams ::= BRACKET_LE (symbol [EQUALS typeDesc] )* BRACKET_RI genericParams ::= BRACKET_LE (symbol [EQUALS typeDesc] )* BRACKET_RI
typeDecl ::= TYPE typeDecl ::= TYPE
@ -1425,11 +1431,11 @@ Example:
.. code-block:: nimrod .. code-block:: nimrod
type # example demonstrates mutually recursive types type # example demonstrates mutually recursive types
PNode = ref TNode # a traced pointer to a TNode PNode = ref TNode # a traced pointer to a TNode
TNode = record TNode = object
le, ri: PNode # left and right subtrees le, ri: PNode # left and right subtrees
sym: ref TSym # leaves contain a reference to a TSym sym: ref TSym # leaves contain a reference to a TSym
TSym = record # a symbol TSym = object # a symbol
name: string # the symbol's name name: string # the symbol's name
line: int # the line the symbol was declared in line: int # the line the symbol was declared in
code: PNode # the symbol's abstract syntax tree code: PNode # the symbol's abstract syntax tree
@ -1447,7 +1453,7 @@ Example:
.. code-block:: nimrod .. code-block:: nimrod
type type
TBinaryTree[T] = record # TBinaryTree is a generic type with TBinaryTree[T] = object # TBinaryTree is a generic type with
# with generic param ``T`` # with generic param ``T``
le, ri: ref TBinaryTree[T] # left and right subtrees; may be nil le, ri: ref TBinaryTree[T] # left and right subtrees; may be nil
data: T # the data stored in a node data: T # the data stored in a node
@ -1537,7 +1543,8 @@ Modules make separate compilation possible. Each module needs to be in its
own file. Modules enable `information hiding`:idx: and own file. Modules enable `information hiding`:idx: and
`separate compilation`:idx:. A module may gain access to symbols of another `separate compilation`:idx:. A module may gain access to symbols of another
module by the `import`:idx: statement. `Recursive module dependancies`:idx: are module by the `import`:idx: statement. `Recursive module dependancies`:idx: are
allowed, but slightly subtle. allowed, but slightly subtle. Only top-level symbols that are marked with an
asterisk (``*``) are exported.
The algorithm for compiling modules is: The algorithm for compiling modules is:
@ -1587,13 +1594,13 @@ identifier cannot be redefined in the same block, except if valid for
procedure or iterator overloading purposes. procedure or iterator overloading purposes.
Record or object scope Tuple or object scope
~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~
The field identifiers inside a record or object definition are valid in the The field identifiers inside a tuple or object definition are valid in the
following places: following places:
* To the end of the record definition * To the end of the tuple/object definition
* Field designators of a variable of the given record type. * Field designators of a variable of the given tuple/object type.
* In all descendent types of the object type. * In all descendent types of the object type.
Module scope Module scope

View file

@ -86,7 +86,7 @@ the C code. Thus it makes the following possible, for example:
.. code-block:: Nimrod .. code-block:: Nimrod
var var
EOF {.import: "EOF", no_decl.}: cint # pretend EOF was a variable, as EOF {.importc: "EOF", no_decl.}: cint # pretend EOF was a variable, as
# Nimrod does not know its value # Nimrod does not know its value
Varargs Pragma Varargs Pragma
@ -110,7 +110,7 @@ declared but also that it leads to the inclusion of a given header file:
.. code-block:: Nimrod .. code-block:: Nimrod
type type
PFile {.import: "FILE*", header: "<stdio.h>".} = pointer PFile {.importc: "FILE*", header: "<stdio.h>".} = pointer
# import C's FILE* type; Nimrod will treat it as a new pointer type # import C's FILE* type; Nimrod will treat it as a new pointer type
The ``header`` pragma expects always a string constant. The string contant The ``header`` pragma expects always a string constant. The string contant
@ -239,3 +239,28 @@ However it is not efficient to do:
String case statements are optimized too. A hashing scheme is used for them String case statements are optimized too. A hashing scheme is used for them
if several different string constants are used. This is likely to be more if several different string constants are used. This is likely to be more
efficient than any hand-coded scheme. efficient than any hand-coded scheme.
The ECMAScript code generator
=============================
Note: I use the term `ECMAScript`:idx: here instead of `JavaScript`:idx:, since
it is the proper term.
Nimrod targets ECMAScript 1.5 which is supported by any widely used browser.
Since ECMAScript does not have a portable means to include another module,
Nimrod just generate a long ``.js`` file.
Features or modules that the ECMAScript platform does not support are not
available. This includes:
* manual memory management (``alloc``, etc.)
* casting and other unsafe operations (``cast`` operator, ``zeroMem``, etc.)
* file management (``openfile``, etc.)
* most modules of the Standard library
* proper 64 bit integer arithmetic
* proper unsigned integer arithmetic
However, the modules `strutils`:idx:, `math`:idx:, and `times`:idx: are
available! To access the DOM, use the `dom`:idx: module that is only available
for the ECMAScript platform.

View file

@ -1,220 +0,0 @@
Function POSIX Description
access Tests for file accessibility
alarm Schedules an alarm
asctime Converts a time structure to a string
cfgetispeed Reads terminal input baud rate
cfgetospeed Reads terminal output baud rate
cfsetispeed Sets terminal input baud rate
cfsetospeed Sets terminal output baud rate
chdir Changes current working directory
chmod Changes file mode
chown Changes owner and/or group of a file
close Closes a file
closedir Ends directory read operation
creat Creates a new file or rewrites an existing one
ctermid Generates terminal pathname
cuserid Gets user name
dup Duplicates an open file descriptor
dup2 Duplicates an open file descriptor
execl Executes a file
execle Executes a file
execlp Executes a file
execv Executes a file
execve Executes a file
execvp Executes a file
_exit Terminates a process
fcntl Manipulates an open file descriptor
fdopen Opens a stream on a file descriptor
fork Creates a process
fpathconf Gets configuration variable for an open file
fstat Gets file status
getcwd Gets current working directory
getegid Gets effective group ID
getenv Gets environment variable
geteuid Gets effective user ID
getgid Gets real group ID
getgrgid Reads groups database based on group ID
getgrnam Reads groups database based on group name
getgroups Gets supplementary group IDs
getlogin Gets user name
getpgrp Gets process group ID
getpid Gets process ID
getppid Gets parent process ID
getpwnam Reads user database based on user name
getpwuid Reads user database based on user ID
getuid Gets real user ID
isatty Determines if a file descriptor is associated with a terminal
kill Sends a kill signal to a process
link Creates a link to a file
longjmp Restores the calling environment
lseek Repositions read/write file offset
mkdir Makes a directory
mkfifo Makes a FIFO special file
open Opens a file
opendir Opens a directory
pathconf Gets configuration variables for a path
pause Suspends a process execution
pipe Creates an interprocess channel
read Reads from a file
readdir Reads a directory
rename Renames a file
rewinddir Resets the readdir() pointer
rmdir Removes a directory
setgid Sets group ID
setjmp Saves the calling environment for use by longjmp()
setlocale Sets or queries a program's locale
setpgid Sets a process group ID for job control
setuid Sets the user ID
sigaction Examines and changes signal action
sigaddset Adds a signal to a signal set
sigdelset Removes a signal to a signal set
sigemptyset Creates an empty signal set
sigfillset Creates a full set of signals
sigismember Tests a signal for a selected member
siglongjmp Goes to and restores signal mask
sigpending Examines pending signals
sigprocmask Examines and changes blocked signals
sigsetjmp Saves state for siglongjmp()
sigsuspend Waits for a signal
sleep Delays process execution
stat Gets information about a file
sysconf Gets system configuration information
tcdrain Waits for all output to be transmitted to the terminal
tcflow Suspends/restarts terminal output
tcflush Discards terminal data
tcgetattr Gets terminal attributes
tcgetpgrp Gets foreground process group ID
tcsendbreak Sends a break to a terminal
tcsetattr Sets terminal attributes
tcsetpgrp Sets foreground process group ID
time Determines the current calendar time
times Gets process times
ttyname Determines a terminal pathname
tzset Sets the timezone from environment variables
umask Sets the file creation mask
uname Gets system name
unlink Removes a directory entry
utime Sets file access and modification times
waitpid Waits for process termination
write Writes to a file
POSIX.1b function calls Function POSIX Description
aio_cancel Tries to cancel an asynchronous operation
aio_error Retrieves the error status for an asynchronous operation
aio_read Asynchronously reads from a file
aio_return Retrieves the return status for an asynchronous operation
aio_suspend Waits for an asynchronous operation to complete
aio_write Asynchronously writes to a file
clock_getres Gets resolution of a POSIX.1b clock
clock_gettime Gets the time according to a particular POSIX.1b clock
clock_settime Sets the time according to a particular POSIX.1b clock
fdatasync Synchronizes at least the data part of a file with the underlying media
fsync Synchronizes a file with the underlying media
kill, sigqueue Sends signals to a process
lio_listio Performs a list of I/O operations, synchronously or asynchronously
mlock Locks a range of memory
mlockall Locks the entire memory space down
mmap Maps a shared memory object (or possibly another file) into process's address space
mprotect Changes memory protection on a mapped area
mq_close Terminates access to a POSIX.1b message queue
mq_getattr Gets POSIX.1b message queue attributes
mq_notify Registers a request to be notified when a message arrives on an empty message queue
mq_open Creates/accesses a POSIX.1b message queue
mq_receive Receives a message from a POSIX.1b message queue
mq_send Sends a message on a POSIX.1b message queue
mq_setattr Sets a subset of POSIX.1b message queue attributes
msync Makes a mapping consistent with the underlying object
munlock Unlocks a range of memory
munlockall Unlocks the entire address space
munmap Undo mapping established by mmap
nanosleep Pauses execution for a number of nanoseconds
sched_get_priority_max Gets maximum priority value for a scheduler
sched_get_priority_min Gets minimum priority value for a scheduler
sched_getparam Retrieves scheduling parameters for a particular process
sched_getscheduler Retrieves scheduling algorithm for a particular purpose
sched_rr_get_interval Gets the SCHED_RR interval for the named process
sched_setparam Sets scheduling parameters for a process
sched_setscheduler Sets scheduling algorithm/parameters for a process
sched_yield Yields the processor
sem_close Terminates access to a POSIX.1b semaphore
sem_destroy De-initializes a POSIX.1b unnamed semaphore
sem_getvalue Gets the value of a POSIX.1b semaphore
sem_open Creates/accesses a POSIX.1b named semaphore
sem_post Posts (signal) a POSIX.1b named or unnamed semaphore
sem_unlink Destroys a POSIX.1b named semaphore
sem_wait, sem_trywait Waits on a POSIX.1b named or unnamed semaphore
shm_open Creates/accesses a POSIX.1b shared memory object
shm_unlink Destroys a POSIX.1b shared memory object
sigwaitinfosigtimedwait Synchronously awaits signal arrival; avoid calling handler
timer_create Creates a POSIX.1b timer based on a particular clock
timer_delete Deletes a POSIX.1b timer
timer_gettime Time remaining on a POSIX.1b timer before expiration
timer_settime Sets expiration time/interval for a POSIX.1b timer
wait, waitpid Retrieves status of a terminated process and clean up corpse
POSIX.1c function calls Function POSIX Description
pthread_atfork Declares procedures to be called before and after a fork
pthread_attr_destroy Destroys a thread attribute object
pthread_attr_getdetachstate Obtains the setting of the detached state of a thread
pthread_attr_getinheritsched Obtains the setting of the scheduling inheritance of a thread
pthread_attr_getschedparam Obtains the parameters associated with the scheduling policy attribute of a thread
pthread_attr_getschedpolicy Obtains the setting of the scheduling policy of a thread
pthread_attr_getscope Obtains the setting of the scheduling scope of a thread
pthread_attr_getstackaddr Obtains the stack address of a thread
pthread_attr_getstacksize Obtains the stack size of a thread
pthread_attr_init Initializes a thread attribute object
pthread_attr_setdetachstate Adjusts the detached state of a thread
pthread_attr_setinheritsched Adjusts the scheduling inheritance of a thread
pthread_attr_setschedparam Adjusts the parameters associated with the scheduling policy of a thread
pthread_attr_setschedpolicy Adjusts the scheduling policy of a thread
pthread_attr_setscope Adjusts the scheduling scope of a thread
pthread_attr_setstackaddr Adjusts the stack address of a thread
pthread_attr_setstacksize Adjusts the stack size of a thread
pthread_cancel Cancels the specific thread
pthread_cleanup_pop Removes the routine from the top of a thread's cleanup stack, and if execute is nonzero, runs it
pthread_cleanup_push Places a routine on the top of a thread's cleanup stack
pthread_condattr_destroy Destroys a condition variable attribute object
pthread_condattr_getpshared Obtains the process-shared setting of a condition variable attribute object
pthread_condattr_init Initializes a condition variable attribute object
pthread_condattr_setpshared Sets the process-shared attribute in a condition variable attribute object to either PTHREAD_PROCESS_SHARED or PTHREAD_PROCESS_PRIVATE
pthread_cond_broadcast Unblocks all threads that are waiting on a condition variable
pthread_cond_destroy Destroys a condition variable
pthread_cond_init Initializes a condition variable with the attributes specified in the specified condition variable attribute object
pthread_cond_signal Unblocks at least one thread waiting on a condition variable
pthread_cond_timedwait Automatically unlocks the specified mutex, and places the calling thread into a wait state
pthread_cond_wait Automatically unlocks the specified mutex, and places the calling thread into a wait state
pthread_create Creates a thread with the attributes specified in attr
pthread_detach Marks a threads internal data structures for deletion
pthread_equal Compares one thread handle to another thread handle
pthread_exit Terminates the calling thread
pthread_getschedparam Obtains both scheduling policy and scheduling parameters of an existing thread
pthread_getspecific Obtains the thread specific data value associated with the specific key in the calling thread
pthread_join Causes the calling thread to wait for the specific thread’s termination
pthread_key_create Generates a unique thread-specific key that's visible to all threads in a process
pthread_key_delete Deletes a thread specific key
pthread_kill Delivers a signal to the specified thread
pthread_mutexattr_destroy Destroys a mutex attribute object
pthread_mutexattr_getprioceiling Obtains the priority ceiling of a mutex attribute object
pthread_mutexattr_getprotocol Obtains protocol of a mutex attribute object
pthread_mutexattr_getpshared Obtains a process-shared setting of a mutex attribute object
pthread_mutexattr_init Initializes a mutex attribute object
pthread_mutexattr_setprioceiling Sets the priority ceiling attribute of a mutex attribute object
pthread_mutexattr_setprotocol Sets the protocol attribute of a mutex attribute object
pthread_mutexattr_setpshared Sets the process-shared attribute of a mutex attribute object to either PTHREAD_PROCESS_SHARED or PTHREAD_PROCESS_PRIVATE
pthread_mutex_destroy Destroys a mutex
pthread_mutex_init Initializes a mutex with the attributes specified in the specified mutex attribute object
pthread_mutex_lock Locks an unlocked mutex
pthread_mutex_trylock Tries to lock a not tested
pthread_mutex_unlock Unlocks a mutex
pthread_once Ensures that init_routine will run just once regardless of how many threads in the process call it
pthread_self Obtains a thread handle of a calling thread
pthread_setcancelstate Sets a thread's cancelability state
pthread_setcanceltype Sets a thread's cancelability type
pthread_setschedparam Adjusts the scheduling policy and scheduling parameters of an existing thread
pthread_setspecific Sets the thread-specific data value associated with the specific key in the calling thread
pthread_sigmask Examines or changes the calling thread's signal mask
pthread_testcancel Requests that any pending cancellation request be delivered to the calling thread

View file

@ -4,8 +4,4 @@ Nimrod's documenation system
This folder contains Nimrod's documentation. The documentation This folder contains Nimrod's documentation. The documentation
is written in a format called *reStructuredText*, a markup language that reads is written in a format called *reStructuredText*, a markup language that reads
like ASCII and can be converted to HTML, Tex and other formats automatically! like ASCII and can be converted to HTML automatically!
Unfortunately reStructuredText does not allow to colorize source code in the
HTML page. Therefore a postprocessor runs over the generated HTML code, looking
for Nimrod code fragments and colorizing them.

View file

@ -272,25 +272,3 @@ end of the subject string, whatever options are set.
The difference between ``\Z`` and ``\z`` is that ``\Z`` matches before The difference between ``\Z`` and ``\z`` is that ``\Z`` matches before
a newline that is the last character of the string as well as at the end a newline that is the last character of the string as well as at the end
of the string, whereas ``\z`` matches only at the end. of the string, whereas ``\z`` matches only at the end.
..
Regular expressions in Nimrod itself!
-------------------------------------
'a' -- matches the character a
'a'-'z' -- range operator '-'
'A' | 'B' -- alternative operator |
* 'a' -- prefix * is needed
+ 'a' -- prefix + is needed
? 'a' -- prefix ? is needed
letter -- character classes with real names!
letters
white
whites
any -- any character
() -- are Nimrod syntax
! 'a'-'z'
-- concatentation via proc call:
re('A' 'Z' word * )

File diff suppressed because it is too large Load diff

View file

@ -85,13 +85,13 @@ We start the tour with a modified "hallo world" program:
Save this code to the file "greeting.nim". Now compile and run it:: Save this code to the file "greeting.nim". Now compile and run it::
nimrod run greeting.nim nimrod compile --run greeting.nim
As you see, with the ``run`` command Nimrod executes the file automatically As you see, with the ``--run`` switch Nimrod executes the file automatically
after compilation. You can even give your program command line arguments by after compilation. You can even give your program command line arguments by
appending them after the filename that is to be compiled and run:: appending them after the filename that is to be compiled and run::
nimrod run greeting.nim arg1 arg2 nimrod compile --run greeting.nim arg1 arg2
Though it should be pretty obvious what the program does, I will explain the Though it should be pretty obvious what the program does, I will explain the
syntax: Statements which are not indented are executed when the program syntax: Statements which are not indented are executed when the program
@ -198,7 +198,7 @@ An example showing the most common statement types:
.. code-block:: Nimrod .. code-block:: Nimrod
type type
TMyRecord = record TMyRecord = object
x, y: int x, y: int

View file

@ -1,60 +1,35 @@
import glib2, gtk2, libglade2 import glib2, gtk2, libglade2, dialogs
proc on_window_destroy(obj: PGtkObject, data: pointer) {.exportc, cdecl.} = proc on_window_destroy(obj: PGtkObject, data: pointer) {.cdecl.} =
gtk_main_quit() gtk_main_quit()
const const
GuiTemplate = "/media/hda4/nimrod/ide/nimide.glade" GuiTemplate = "/media/hda4/nimrod/ide/nimide.glade"
type type
TMyTextEditor = record TTab = object of TObject
textview: PGtkTextView
filename: string
untitled: bool
TMyTextEditor = object of TObject
window: PGtkWindow window: PGtkWindow
statusbar: PGtkStatusBar statusbar: PGtkStatusBar
textview: PGtkTextview textview: PGtkTextview
statusbarContextId: int statusbarContextId: int
filename: string
proc error_message(msg: string) =
var
dialog: PGtkDialog
dialog = GTK_DIALOG(gtk_message_dialog_new(nil,
GTK_DIALOG_MODAL or GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, msg))
gtk_window_set_title(dialog, "Error!")
gtk_dialog_run(dialog)
gtk_widget_destroy(dialog)
proc get_open_filename(e: TMyTextEditor): string =
var
chooser: PGtkDialog
chooser = gtk_file_chooser_dialog_new("Open File...", e.window,
GTK_FILE_CHOOSER_ACTION_OPEN,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_OPEN, GTK_RESPONSE_OK, nil)
if gtk_dialog_run(chooser) == GTK_RESPONSE_OK: proc on_about_menu_item_activate(menuItem: PGtkMenuItem,
result = $gtk_file_chooser_get_filename(chooser) e: var TMyTextEditor) {.cdecl.} =
else: gtk_show_about_dialog(e.window,
result = "" "comments", "A fast and leight-weight IDE for Nimrod",
gtk_widget_destroy(chooser) "copyright", "Copyright \xc2\xa9 2008 Andreas Rumpf",
"version", "0.1",
"website", "http://nimrod.ethexor.com",
proc get_save_filename(e: TMyTextEditor): string = "program-name", "Nimrod IDE",
var nil)
chooser: PGtkDialog
chooser = gtk_file_chooser_dialog_new("Save File...", e.window,
GTK_FILE_CHOOSER_ACTION_SAVE,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_OPEN, GTK_RESPONSE_OK, nil)
if gtk_dialog_run(chooser) == GTK_RESPONSE_OK:
result = $gtk_file_chooser_get_filename(chooser)
else:
result = ""
gtk_widget_destroy(chooser)
proc load_file(e: var TMyTextEditor, filename: string) = proc load_file(e: var TMyTextEditor, filename: string) =
var var
@ -119,6 +94,21 @@ proc write_file(e: var TMyTextEditor, filename: string) =
reset_default_status(editor) reset_default_status(editor)
proc check_for_save(e: var TMyTextEditor): bool =
GtkTextBuffer *buffer;
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (editor->text_view));
if gtk_text_buffer_get_modified(buffer):
GtkWidget *dialog;
const gchar *msg = "Do you want to save the changes you have made?";
dialog = gtk_message_dialog_new (nil,
GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_QUESTION,
GTK_BUTTONS_YES_NO,
msg);
gtk_window_set_title (GTK_WINDOW (dialog), "Save?");
result = gtk_dialog_run(dialog) != GTK_RESPONSE_NO
gtk_widget_destroy(dialog)
proc initApp(e: var TMyTextEditor) = proc initApp(e: var TMyTextEditor) =
var var
builder: PGladeXML builder: PGladeXML
@ -136,7 +126,7 @@ proc initApp(e: var TMyTextEditor) =
# connect the signal handlers: # connect the signal handlers:
glade_xml_signal_connect(builder, "on_window_destroy", glade_xml_signal_connect(builder, "on_window_destroy",
cast[TGCallback](on_window_destroy)) GCallback(on_window_destroy))
font_desc = pango_font_description_from_string("monospace 10") font_desc = pango_font_description_from_string("monospace 10")
gtk_widget_modify_font(e.textview, font_desc) gtk_widget_modify_font(e.textview, font_desc)
@ -162,208 +152,82 @@ proc main() =
main() main()
proc reset_default_status(e: var TMyTextEditor)
gchar *file;
gchar *status;
if e.filename == "": proc on_window_delete_event(widget: PGtkWidget, event: PGdkEvent,
file = g_strdup("(UNTITLED)") e: TMyTextEditor): bool {.cdecl.} =
else: if check_for_save(editor):
file = g_path_get_basename(editor->filename) on_save_menu_item_activate(nil, editor)
result = false
status = g_strdup_printf("File: %s", file) proc on_new_menu_item_activate(GtkMenuItem *menuitem, TutorialTextEditor *editor)
gtk_statusbar_pop(e.statusbar,
e.statusbar_context_id)
gtk_statusbar_push(e.statusbar,
e.statusbar_context_id, status)
g_free(status)
g_free(file)
gboolean
check_for_save(e: var TMyTextEditor)
gboolean ret = FALSE;
GtkTextBuffer *buffer;
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (editor->text_view));
if (gtk_text_buffer_get_modified (buffer) == TRUE)
{
GtkWidget *dialog;
const gchar *msg = "Do you want to save the changes you have made?";
dialog = gtk_message_dialog_new (NULL,
GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_QUESTION,
GTK_BUTTONS_YES_NO,
msg);
gtk_window_set_title (GTK_WINDOW (dialog), "Save?");
if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_NO)
{
ret = FALSE;
} else ret = TRUE;
gtk_widget_destroy (dialog);
}
return ret;
/*
When the window is requested to be closed, we need to check if they have
unsaved work. We use this callback to prompt the user to save their work before
they exit the application. From the "delete-event" signal, we can choose to
effectively cancel the close based on the value we return.
*/
gboolean
on_window_delete_event(GtkWidget *widget, GdkEvent *event,
TutorialTextEditor *editor)
{
if (check_for_save (editor) == TRUE)
on_save_menu_item_activate (NULL, editor);
return FALSE; /* propogate event */
}
/*
Called when the user clicks the 'New' menu. We need to prompt for save if the
file has been modified, and then delete the buffer and clear the modified flag.
*/
void on_new_menu_item_activate (GtkMenuItem *menuitem, TutorialTextEditor *editor)
{
GtkTextBuffer *buffer; GtkTextBuffer *buffer;
if (check_for_save (editor) == TRUE) if check_for_save(editor):
{ on_save_menu_item_activate(nil, editor)
on_save_menu_item_activate (NULL, editor);
}
/* clear editor for a new file */ /* clear editor for a new file */
editor->filename = NULL; editor->filename = nil;
buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW (editor->text_view)); buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW (editor->text_view));
gtk_text_buffer_set_text(buffer, "", -1); gtk_text_buffer_set_text(buffer, "", -1);
gtk_text_buffer_set_modified(buffer, FALSE); gtk_text_buffer_set_modified(buffer, FALSE);
reset_default_status(editor); reset_default_status(editor);
}
/*
Called when the user clicks the 'Open' menu. We need to prompt for save if the proc on_open_menu_item_activate(menuItem: PGtkMenuItem,
file has been modified, allow the user to choose a file to open, and then call TutorialTextEditor *editor) =
load_file() on that file.
*/
void on_open_menu_item_activate (GtkMenuItem *menuitem, TutorialTextEditor *editor)
{
gchar *filename; gchar *filename;
if (check_for_save (editor) == TRUE) if check_for_save(editor):
{ on_save_menu_item_activate(nil, editor)
on_save_menu_item_activate (NULL, editor); filename = get_open_filename(editor)
} if filename != nil: load_file(editor, filename)
filename = get_open_filename (editor); proc on_save_menu_item_activate(menuItem: PGtkMenuItem, TutorialTextEditor *editor) =
if (filename != NULL) load_file (editor, filename);
}
/*
Called when the user clicks the 'Save' menu. We need to allow the user to choose
a file to save if it's an untitled document, and then call write_file() on that
file.
*/
void on_save_menu_item_activate (GtkMenuItem *menuitem, TutorialTextEditor *editor)
{
gchar *filename; gchar *filename;
if (editor->filename == nil)
if (editor->filename == NULL)
{ {
filename = get_save_filename(editor); filename = get_save_filename(editor);
if (filename != NULL) write_file (editor, filename); if (filename != nil) write_file(editor, filename);
} }
else write_file (editor, NULL); else write_file(editor, nil);
} proc on_save_as_menu_item_activate(GtkMenuItem *menuitem,
TutorialTextEditor *editor) =
/*
Called when the user clicks the 'Save As' menu. We need to allow the user to
choose a file to save and then call write_file() on that file.
*/
void on_save_as_menu_item_activate (GtkMenuItem *menuitem, TutorialTextEditor *editor)
{
gchar *filename; gchar *filename;
filename = get_save_filename (editor); filename = get_save_filename(editor)
if (filename != NULL) write_file (editor, filename); if filename != nil: write_file(editor, filename)
}
/* proc on_quit_menu_item_activate(GtkMenuItem *menuitem, TutorialTextEditor *editor)
Called when the user clicks the 'Quit' menu. We need to prompt for save if the if check_for_save(editor):
file has been modified and then break out of the GTK+ main loop. on_save_menu_item_activate(nil, editor)
*/ gtk_main_quit()
void on_quit_menu_item_activate (GtkMenuItem *menuitem, TutorialTextEditor *editor)
{
if (check_for_save (editor) == TRUE)
{
on_save_menu_item_activate (NULL, editor);
}
gtk_main_quit();
}
/* proc on_cut_menu_item_activate(GtkMenuItem *menuitem, TutorialTextEditor *editor) =
Called when the user clicks the 'Cut' menu.
*/
void on_cut_menu_item_activate (GtkMenuItem *menuitem, TutorialTextEditor *editor)
{
GtkTextBuffer *buffer; GtkTextBuffer *buffer;
GtkClipboard *clipboard; GtkClipboard *clipboard;
clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD); clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (editor->text_view)); buffer = gtk_text_view_get_buffer(editor->text_view)
gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE); gtk_text_buffer_cut_clipboard(buffer, clipboard, TRUE)
}
/* proc on_copy_menu_item_activate(GtkMenuItem *menuitem, TutorialTextEditor *editor) =
Called when the user clicks the 'Copy' menu.
*/
void on_copy_menu_item_activate (GtkMenuItem *menuitem, TutorialTextEditor *editor)
{
GtkTextBuffer *buffer; GtkTextBuffer *buffer;
GtkClipboard *clipboard; GtkClipboard *clipboard;
clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD)
buffer = gtk_text_view_get_buffer(editor->text_view)
gtk_text_buffer_copy_clipboard(buffer, clipboard)
clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (editor->text_view));
gtk_text_buffer_copy_clipboard (buffer, clipboard);
}
/* proc on_paste_menu_item_activate(GtkMenuItem *menuitem, TutorialTextEditor *editor)
Called when the user clicks the 'Paste' menu.
*/
void on_paste_menu_item_activate (GtkMenuItem *menuitem, TutorialTextEditor *editor)
{
GtkTextBuffer *buffer; GtkTextBuffer *buffer;
GtkClipboard *clipboard; GtkClipboard *clipboard;
clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD); clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD)
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (editor->text_view)); buffer = gtk_text_view_get_buffer(editor->text_view)
gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE); gtk_text_buffer_paste_clipboard(buffer, clipboard, nil, TRUE)
}
/* proc on_delete_menu_item_activate(GtkMenuItem *menuitem, TutorialTextEditor *editor)
Called when the user clicks the 'Delete' menu.
*/
void on_delete_menu_item_activate (GtkMenuItem *menuitem, TutorialTextEditor *editor)
{
GtkTextBuffer *buffer; GtkTextBuffer *buffer;
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (editor->text_view)); buffer = gtk_text_view_get_buffer(editor->text_view);
gtk_text_buffer_delete_selection(buffer, FALSE, TRUE); gtk_text_buffer_delete_selection(buffer, FALSE, TRUE);
}
void on_about_menu_item_activate (GtkMenuItem *menuitem, TutorialTextEditor *editor)
{
static const gchar * const authors[] = {
"Micah Carrick <email@micahcarrick.com>",
NULL
};
static const gchar copyright[] = "Copyright \xc2\xa9 2008 Andreas Rumpf";
static const gchar comments[] = "GTK+ and Glade3 GUI Programming Tutorial";
gtk_show_about_dialog (e.window,
"authors", authors,
"comments", comments,
"copyright", copyright,
"version", "0.1",
"website", "http://www.micahcarrick.com",
"program-name", "GTK+ Text Editor",
"logo-icon-name", GTK_STOCK_EDIT, nil)
}

View file

@ -1,66 +1,91 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd"> <!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">
<!--Generated with glade3 3.4.2 on Sat Jun 21 14:12:42 2008 -->
<glade-interface> <glade-interface>
<widget class="GtkWindow" id="window"> <widget class="GtkWindow" id="window">
<property name="extension_events">GDK_EXTENSION_EVENTS_ALL</property> <property name="extension_events">GDK_EXTENSION_EVENTS_ALL</property>
<property name="title" translatable="yes"></property>
<property name="type">GTK_WINDOW_TOPLEVEL</property>
<property name="window_position">GTK_WIN_POS_NONE</property>
<property name="modal">False</property>
<property name="resizable">True</property>
<property name="destroy_with_parent">False</property>
<property name="decorated">True</property>
<property name="skip_taskbar_hint">False</property>
<property name="skip_pager_hint">False</property>
<property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
<property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
<property name="focus_on_map">True</property>
<property name="urgency_hint">False</property>
<signal name="destroy" handler="on_window_destroy" object="destroy"/> <signal name="destroy" handler="on_window_destroy" object="destroy"/>
<child> <child>
<widget class="GtkVBox" id="mainvbox"> <widget class="GtkVBox" id="mainvbox">
<property name="width_request">600</property>
<property name="height_request">400</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">0</property>
<child> <child>
<widget class="GtkMenuBar" id="menubar"> <widget class="GtkMenuBar" id="menubar">
<property name="visible">True</property> <property name="visible">True</property>
<property name="pack_direction">GTK_PACK_DIRECTION_LTR</property>
<property name="child_pack_direction">GTK_PACK_DIRECTION_LTR</property>
<child> <child>
<widget class="GtkMenuItem" id="menuitem1"> <widget class="GtkMenuItem" id="menuitem1">
<property name="visible">True</property> <property name="visible">True</property>
<property name="label" translatable="yes">_Datei</property> <property name="label" translatable="yes">_Datei</property>
<property name="use_underline">True</property> <property name="use_underline">True</property>
<child> <child>
<widget class="GtkMenu" id="menu1"> <widget class="GtkMenu" id="menu1">
<property name="visible">True</property> <property name="visible">True</property>
<child> <child>
<widget class="GtkImageMenuItem" id="new_menu_item"> <widget class="GtkImageMenuItem" id="new_menu_item">
<property name="visible">True</property> <property name="visible">True</property>
<property name="label" translatable="yes">gtk-new</property> <property name="label">gtk-new</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property> <property name="use_stock">True</property>
</widget> </widget>
</child> </child>
<child> <child>
<widget class="GtkImageMenuItem" id="open_menu_item"> <widget class="GtkImageMenuItem" id="open_menu_item">
<property name="visible">True</property> <property name="visible">True</property>
<property name="label" translatable="yes">gtk-open</property> <property name="label">gtk-open</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property> <property name="use_stock">True</property>
</widget> </widget>
</child> </child>
<child> <child>
<widget class="GtkImageMenuItem" id="save_menu_item"> <widget class="GtkImageMenuItem" id="save_menu_item">
<property name="visible">True</property> <property name="visible">True</property>
<property name="label" translatable="yes">gtk-save</property> <property name="label">gtk-save</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property> <property name="use_stock">True</property>
</widget> </widget>
</child> </child>
<child> <child>
<widget class="GtkImageMenuItem" id="save_as_menu_item"> <widget class="GtkImageMenuItem" id="save_as_menu_item">
<property name="visible">True</property> <property name="visible">True</property>
<property name="label" translatable="yes">gtk-save-as</property> <property name="label">gtk-save-as</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property> <property name="use_stock">True</property>
</widget> </widget>
</child> </child>
<child> <child>
<widget class="GtkSeparatorMenuItem" id="separatormenuitem1"> <widget class="GtkSeparatorMenuItem" id="separatormenuitem1">
<property name="visible">True</property> <property name="visible">True</property>
</widget> </widget>
</child> </child>
<child> <child>
<widget class="GtkImageMenuItem" id="quit_menu_item"> <widget class="GtkImageMenuItem" id="quit_menu_item">
<property name="visible">True</property> <property name="visible">True</property>
<property name="label" translatable="yes">gtk-quit</property> <property name="label">gtk-quit</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property> <property name="use_stock">True</property>
</widget> </widget>
</child> </child>
@ -68,43 +93,45 @@
</child> </child>
</widget> </widget>
</child> </child>
<child> <child>
<widget class="GtkMenuItem" id="menuitem2"> <widget class="GtkMenuItem" id="menuitem2">
<property name="visible">True</property> <property name="visible">True</property>
<property name="label" translatable="yes">_Bearbeiten</property> <property name="label" translatable="yes">_Bearbeiten</property>
<property name="use_underline">True</property> <property name="use_underline">True</property>
<child> <child>
<widget class="GtkMenu" id="menu2"> <widget class="GtkMenu" id="menu2">
<property name="visible">True</property> <property name="visible">True</property>
<child> <child>
<widget class="GtkImageMenuItem" id="cut_menu_item"> <widget class="GtkImageMenuItem" id="cut_menu_item">
<property name="visible">True</property> <property name="visible">True</property>
<property name="label" translatable="yes">gtk-cut</property> <property name="label">gtk-cut</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property> <property name="use_stock">True</property>
</widget> </widget>
</child> </child>
<child> <child>
<widget class="GtkImageMenuItem" id="copy_menu_item"> <widget class="GtkImageMenuItem" id="copy_menu_item">
<property name="visible">True</property> <property name="visible">True</property>
<property name="label" translatable="yes">gtk-copy</property> <property name="label">gtk-copy</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property> <property name="use_stock">True</property>
</widget> </widget>
</child> </child>
<child> <child>
<widget class="GtkImageMenuItem" id="paste_menu_item"> <widget class="GtkImageMenuItem" id="paste_menu_item">
<property name="visible">True</property> <property name="visible">True</property>
<property name="label" translatable="yes">gtk-paste</property> <property name="label">gtk-paste</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property> <property name="use_stock">True</property>
</widget> </widget>
</child> </child>
<child> <child>
<widget class="GtkImageMenuItem" id="delete_menu_item"> <widget class="GtkImageMenuItem" id="delete_menu_item">
<property name="visible">True</property> <property name="visible">True</property>
<property name="label" translatable="yes">gtk-delete</property> <property name="label">gtk-delete</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property> <property name="use_stock">True</property>
</widget> </widget>
</child> </child>
@ -112,19 +139,21 @@
</child> </child>
</widget> </widget>
</child> </child>
<child> <child>
<widget class="GtkMenuItem" id="menuitem4"> <widget class="GtkMenuItem" id="menuitem4">
<property name="visible">True</property> <property name="visible">True</property>
<property name="label" translatable="yes">_Hilfe</property> <property name="label" translatable="yes">_Hilfe</property>
<property name="use_underline">True</property> <property name="use_underline">True</property>
<child> <child>
<widget class="GtkMenu" id="menu3"> <widget class="GtkMenu" id="menu3">
<property name="visible">True</property> <property name="visible">True</property>
<child> <child>
<widget class="GtkImageMenuItem" id="about_menu_item"> <widget class="GtkImageMenuItem" id="about_menu_item">
<property name="visible">True</property> <property name="visible">True</property>
<property name="label" translatable="yes">gtk-about</property> <property name="label">gtk-about</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property> <property name="use_stock">True</property>
</widget> </widget>
</child> </child>
@ -134,42 +163,62 @@
</child> </child>
</widget> </widget>
<packing> <packing>
<property name="padding">0</property>
<property name="expand">False</property> <property name="expand">False</property>
<property name="fill">True</property>
</packing> </packing>
</child> </child>
<child> <child>
<widget class="GtkScrolledWindow" id="scrolledwindow"> <widget class="GtkScrolledWindow" id="scrolledwindow">
<property name="border_width">1</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can_focus">True</property>
<property name="extension_events">GDK_EXTENSION_EVENTS_ALL</property>
<property name="border_width">1</property>
<property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property> <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="shadow_type">GTK_SHADOW_ETCHED_IN</property> <property name="shadow_type">GTK_SHADOW_ETCHED_IN</property>
<property name="window_placement">GTK_CORNER_TOP_LEFT</property>
<child> <child>
<widget class="GtkTextView" id="textview"> <widget class="GtkTextView" id="textview">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can_focus">True</property>
<property name="editable">True</property>
<property name="overwrite">False</property>
<property name="accepts_tab">True</property>
<property name="justification">GTK_JUSTIFY_LEFT</property>
<property name="wrap_mode">GTK_WRAP_NONE</property>
<property name="cursor_visible">True</property>
<property name="pixels_above_lines">0</property>
<property name="pixels_below_lines">0</property>
<property name="pixels_inside_wrap">0</property>
<property name="left_margin">2</property> <property name="left_margin">2</property>
<property name="right_margin">2</property> <property name="right_margin">2</property>
<property name="indent">0</property>
<property name="text" translatable="yes"></property>
</widget> </widget>
</child> </child>
</widget> </widget>
<packing> <packing>
<property name="position">1</property> <property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing> </packing>
</child> </child>
<child> <child>
<widget class="GtkStatusbar" id="statusbar"> <widget class="GtkStatusbar" id="statusbar">
<property name="visible">True</property> <property name="visible">True</property>
<property name="spacing">2</property> <property name="has_resize_grip">True</property>
</widget> </widget>
<packing> <packing>
<property name="padding">0</property>
<property name="expand">False</property> <property name="expand">False</property>
<property name="position">2</property> <property name="fill">True</property>
</packing> </packing>
</child> </child>
</widget> </widget>
</child> </child>
</widget> </widget>
</glade-interface> </glade-interface>

View file

@ -1,38 +1,17 @@
Installation Installation
============ ============
Installation on Windows - the easy way
--------------------------------------
Install Nimrod by downloading the appropriate .zip file and extracting it to a Installation on Linux/UNIX
directory of your choice. The Nimrod Compiler will stay in this directory; --------------------------
do not use a temporary one! You should add the ``bin`` directory of Nimrod to
your ``$PATH`` environment variable.
Installation on UNIX
--------------------
Note: Note:
A C compiler is required - knowledge of C is not! A C compiler is required - knowledge of C is not!
**Note: Installation under UNIX does not work yet** - you have to bootstrap.
Play with the ``koch.py`` script to compile the compiler. Under Windows the
``nim.exe`` is provided, so you don't need to do anything. Under UNIX you need
to install the `FreePascal <www.freepascal.org>`_ compiler.
Compile the compiler::
python koch.py nim
To bootstrap (does not work yet)::
python koch.py boot
The GNU C Compiler is fully supported, other compilers may work. The C compiler The GNU C Compiler is fully supported, other compilers may work. The C compiler
should be in your ``$PATH`` (most likely the case). Note that some Linux should be in your ``$PATH`` (most likely the case). Note that some Linux
distributions do not ship with a C compiler preinstalled - then you have to distributions do not ship with a GCC compiler preinstalled - then you have to
install one. install it.
After you have made sure that a C compiler is available, install Nimrod After you have made sure that a C compiler is available, install Nimrod
by downloading the appropriate ``.zip`` file and extracting it to a by downloading the appropriate ``.zip`` file and extracting it to a
@ -46,7 +25,7 @@ Then run the following command::
Unlike other software, Nimrod does not distribute its files over the whole file Unlike other software, Nimrod does not distribute its files over the whole file
hierarchy. This has the advantage that you can deinstall it by just deleting hierarchy. This has the advantage that you can deinstall it by just deleting
its folder. The disadvantage is that you have to add it to your ``PATH`` its folder. The disadvantage is that you have to add it to your ``PATH``
manually. The alternative is to create a symbolic link in ``/usr/bin``:: manually. An alternative is to create a symbolic link in ``/usr/bin``::
[sudo] ln -s $your_install_dir/bin/nimrod /usr/bin/nimrod [sudo] ln -s $your_install_dir/bin/nimrod /usr/bin/nimrod
@ -55,35 +34,43 @@ Installation on the Macintosh
----------------------------- -----------------------------
Only MacOS X is supported. Only MacOS X is supported.
Since MacOS X is UNIX based too, it works like the installation on UNIX. You Since MacOS X is UNIX based too, it works like the installation on Linux. You
need to install Apple's developer's tools for the GNU Compiler Collection need to install Apple's developer's tools for the GNU Compiler Collection
though. though.
Installation on Windows - the easy way
--------------------------------------
Install Nimrod by downloading and running
the ``nimrod_windows_$version.exe`` file. The installation procedure detects
which C compilers are installed and writes the ``config/nimrod.cfg`` file
for you. If no installed C compiler is found, the ``LLVM-GCC`` compiler is
used that is bundled with this installer. So it should just work.
Installation on Windows - the hard way Installation on Windows - the hard way
-------------------------------------- --------------------------------------
Windows does not ship with a C compiler; you have to install one. The Windows does not ship with a C compiler; you have to install one. The
following C compilers are supported under Windows: following C compilers are supported under Windows:
- | Digital Mars C++
| http://www.digitalmars.com/download/freecompiler.html
- | Watcom C++
| http://www.openwatcom.org/ftp/
- | Borland C++ (5.5 or above; including Borland C++Builder)
| http://www.borland.com/downloads/download_cbuilder.html
| (Download the package under "compiler" - this requires registration though.)
- | Microsoft's Visual C++ - | Microsoft's Visual C++
| http://msdn.microsoft.com/visualc | http://msdn.microsoft.com/visualc
| (You may need the SDK too - but not the full one: Essential are only | (You may need the SDK too - but not the full one: Essential are only
the win32api header files and import libraries.) the win32api header files and import libraries.)
- | Borland C++ (5.5 or above; including Borland C++Builder)
| http://www.borland.com/downloads/download_cbuilder.html
| (Download the package under "compiler" - this requires registration though.)
- | Gnu C Compiler (the mingw version; the cygwin version has not been tested!) - | Gnu C Compiler (the mingw version; the cygwin version has not been tested!)
| http://www.mingw.org/download.shtml | http://www.mingw.org/download.shtml
- | LLVM with GNU C/C++ frontend - | LLVM with GNU C/C++ frontend
| http://llvm.org/releases/download.html#2.2 | http://llvm.org/releases/download.html#2.2
- | Pelles C Compiler - | Digital Mars C++
| http://www.digitalmars.com/download/freecompiler.html
- | Pelles C Compiler (bootstrapping does not work with PCC!)
| http://www.smorgasbordet.com/pellesc | http://www.smorgasbordet.com/pellesc
- | Lcc-win32 - | Lcc-win32 (bootstrapping does not work with LCC!)
| http://www.cs.virginia.edu/~lcc-win32 | http://www.cs.virginia.edu/~lcc-win32
All of the above compilers are available for free! All of the above compilers are available for free!
@ -96,10 +83,4 @@ After you have made sure that a C compiler is available, install
Nimrod by downloading the appropriate .zip file and extracting it to a Nimrod by downloading the appropriate .zip file and extracting it to a
directory of your choice. The Nimrod Compiler will stay in this directory of your choice. The Nimrod Compiler will stay in this
directory; do not use a temporary one! Then adapt the ``config/nimrod.cfg`` directory; do not use a temporary one! Then adapt the ``config/nimrod.cfg``
file appropriately. Choose your C compiler and press ``OK``. You should file appropriately. You should add Nimrod to your ``$PATH``.
add Nimrod to your ``$PATH``.
Alternatively, you can install Nimrod with the ``koch.py`` script just like
in the UNIX installation instructions.
Nimrod does not use the Registry and can be removed by just deleting its folder.

1099
koch.py

File diff suppressed because it is too large Load diff

View file

@ -2,7 +2,7 @@
# For further documentation see koch.txt or koch.html. # For further documentation see koch.txt or koch.html.
# (c) 2007 Andreas Rumpf # (c) 2007 Andreas Rumpf
VERSION = "1.0.3" VERSION = "1.0.4"
import os, os.path, inspect, re, shutil, glob, cPickle, zlib, string, \ import os, os.path, inspect, re, shutil, glob, cPickle, zlib, string, \
getopt, sys getopt, sys
@ -18,6 +18,25 @@ _FINGERPRINTS_FILE = "koch.dat"
# has changed. This works reliably, which cannot be said from just taking # has changed. This works reliably, which cannot be said from just taking
# filetime-stamps. # filetime-stamps.
# -----------------------------------------------------------------------------
def FileCmp(filenameA, filenameB):
SIZE = 4096*2
result = True
a = file(filenameA, "rb")
b = file(filenameB, "rb")
while True:
x = a.read(SIZE)
y = b.read(SIZE)
if x != y:
result = False
break
elif len(x) < SIZE: # EOF?
break
a.close()
b.close()
return result
# ---------------- C Compilers ------------------------------------------------ # ---------------- C Compilers ------------------------------------------------
# We support the following C compilers: # We support the following C compilers:
@ -185,6 +204,9 @@ def Subs(frmt, **substitution):
else: else:
return tuple([string.Template(x).substitute(substitution) for x in frmt]) return tuple([string.Template(x).substitute(substitution) for x in frmt])
def SafeSubs(frmt, **substitution):
return string.Template(frmt).safe_substitute(substitution)
_baseDir = os.getcwd() _baseDir = os.getcwd()
BaseDir = _baseDir BaseDir = _baseDir

View file

@ -17,9 +17,9 @@ proc c_memcpy(a, b: CString, size: cint) {.nodecl, importc: "memcpy".}
proc c_strlen(a: CString): cint {.nodecl, importc: "strlen".} proc c_strlen(a: CString): cint {.nodecl, importc: "strlen".}
type type
C_TextFile {.importc: "FILE", nodecl.} = record # empty record for C_TextFile {.importc: "FILE", nodecl, final.} = object # empty record for
# data hiding # data hiding
C_BinaryFile {.importc: "FILE", nodecl.} = record C_BinaryFile {.importc: "FILE", nodecl, final.} = object
C_TextFileStar = ptr CTextFile C_TextFileStar = ptr CTextFile
C_BinaryFileStar = ptr CBinaryFile C_BinaryFileStar = ptr CBinaryFile

View file

@ -18,13 +18,13 @@ proc raiseDivByZero {.exportc: "raiseDivByZero".} =
raise newException(EDivByZero, "divison by zero") raise newException(EDivByZero, "divison by zero")
proc addInt64(a, b: int64): int64 {.compilerProc, inline.} = proc addInt64(a, b: int64): int64 {.compilerProc, inline.} =
result = a + b result = a +% b
if (result xor a) >= int64(0) or (result xor b) >= int64(0): if (result xor a) >= int64(0) or (result xor b) >= int64(0):
return result return result
raiseOverflow() raiseOverflow()
proc subInt64(a, b: int64): int64 {.compilerProc, inline.} = proc subInt64(a, b: int64): int64 {.compilerProc, inline.} =
result = a - b result = a -% b
if (result xor a) >= int64(0) or (result xor not b) >= int64(0): if (result xor a) >= int64(0) or (result xor not b) >= int64(0):
return result return result
raiseOverflow() raiseOverflow()
@ -74,7 +74,7 @@ proc modInt64(a, b: int64): int64 {.compilerProc, inline.} =
proc mulInt64(a, b: int64): int64 {.compilerproc.} = proc mulInt64(a, b: int64): int64 {.compilerproc.} =
var var
resAsFloat, floatProd: float64 resAsFloat, floatProd: float64
result = a * b result = a *% b
floatProd = float64(a) # conversion floatProd = float64(a) # conversion
floatProd = floatProd * float64(b) floatProd = floatProd * float64(b)
resAsFloat = float64(result) resAsFloat = float64(result)
@ -276,13 +276,13 @@ else:
# Platform independant versions of the above (slower!) # Platform independant versions of the above (slower!)
proc addInt(a, b: int): int = proc addInt(a, b: int): int =
result = a + b result = a +% b
if (result xor a) >= 0 or (result xor b) >= 0: if (result xor a) >= 0 or (result xor b) >= 0:
return result return result
raiseOverflow() raiseOverflow()
proc subInt(a, b: int): int = proc subInt(a, b: int): int =
result = a - b result = a -% b
if (result xor a) >= 0 or (result xor not b) >= 0: if (result xor a) >= 0 or (result xor not b) >= 0:
return result return result
raiseOverflow() raiseOverflow()
@ -327,7 +327,7 @@ else:
var var
resAsFloat, floatProd: float resAsFloat, floatProd: float
result = a * b result = a *% b
floatProd = toFloat(a) * toFloat(b) floatProd = toFloat(a) * toFloat(b)
resAsFloat = toFloat(result) resAsFloat = toFloat(result)

View file

@ -55,7 +55,8 @@ proc genericAssign(dest, src: Pointer, mt: PNimType) =
var dstseq = cast[PGenericSeq](dst) var dstseq = cast[PGenericSeq](dst)
dstseq.len = seq.len dstseq.len = seq.len
dstseq.space = seq.len dstseq.space = seq.len
of tyRecord, tyObject, tyTuple: of tyObject, tyTuple, tyPureObject:
# we don't need to copy m_type field for tyObject, as they are equal anyway
genericAssignAux(dest, src, mt.node) genericAssignAux(dest, src, mt.node)
of tyArray, tyArrayConstr: of tyArray, tyArrayConstr:
for i in 0..(mt.size div mt.base.size)-1: for i in 0..(mt.size div mt.base.size)-1:
@ -75,6 +76,7 @@ proc genericAssign(dest, src: Pointer, mt: PNimType) =
copyMem(dest, src, mt.size) # copy raw bits copyMem(dest, src, mt.size) # copy raw bits
proc genericSeqAssign(dest, src: Pointer, mt: PNimType) {.compilerProc.} = proc genericSeqAssign(dest, src: Pointer, mt: PNimType) {.compilerProc.} =
var src = src # ugly, but I like to stress the parser sometimes :-)
genericAssign(dest, addr(src), mt) genericAssign(dest, addr(src), mt)
proc genericAssignOpenArray(dest, src: pointer, len: int, proc genericAssignOpenArray(dest, src: pointer, len: int,
@ -110,7 +112,7 @@ proc objectInit(dest: Pointer, typ: PNimType) =
var pint = cast[ptr PNimType](dest) var pint = cast[ptr PNimType](dest)
pint^ = typ pint^ = typ
objectInitAux(dest, typ.node) objectInitAux(dest, typ.node)
of tyRecord: of tyTuple, tyPureObject:
objectInitAux(dest, typ.node) objectInitAux(dest, typ.node)
of tyArray, tyArrayConstr: of tyArray, tyArrayConstr:
for i in 0..(typ.size div typ.base.size)-1: for i in 0..(typ.size div typ.base.size)-1:

View file

@ -149,13 +149,13 @@ type
cdecl.} cdecl.}
cairo_read_func_t* = proc (closure: Pointer, data: PByte, len: int32): cairo_status_t{. cairo_read_func_t* = proc (closure: Pointer, data: PByte, len: int32): cairo_status_t{.
cdecl.} cdecl.}
cairo_t* = record #OPAQUE cairo_t* {.final.} = object #OPAQUE
cairo_surface_t* = record #OPAQUE cairo_surface_t* {.final.} = object #OPAQUE
cairo_pattern_t* = record #OPAQUE cairo_pattern_t* {.final.} = object #OPAQUE
cairo_scaled_font_t* = record #OPAQUE cairo_scaled_font_t* {.final.} = object #OPAQUE
cairo_font_face_t* = record #OPAQUE cairo_font_face_t* {.final.} = object #OPAQUE
cairo_font_options_t* = record #OPAQUE cairo_font_options_t* {.final.} = object #OPAQUE
cairo_matrix_t* = record cairo_matrix_t* {.final.} = object
xx: float64 xx: float64
yx: float64 yx: float64
xy: float64 xy: float64
@ -163,15 +163,15 @@ type
x0: float64 x0: float64
y0: float64 y0: float64
cairo_user_data_key_t* = record cairo_user_data_key_t* {.final.} = object
unused: int32 unused: int32
cairo_glyph_t* = record cairo_glyph_t* {.final.} = object
index: int32 index: int32
x: float64 x: float64
y: float64 y: float64
cairo_text_extents_t* = record cairo_text_extents_t* {.final.} = object
x_bearing: float64 x_bearing: float64
y_bearing: float64 y_bearing: float64
width: float64 width: float64
@ -179,28 +179,28 @@ type
x_advance: float64 x_advance: float64
y_advance: float64 y_advance: float64
cairo_font_extents_t* = record cairo_font_extents_t* {.final.} = object
ascent: float64 ascent: float64
descent: float64 descent: float64
height: float64 height: float64
max_x_advance: float64 max_x_advance: float64
max_y_advance: float64 max_y_advance: float64
cairo_path_data_t* = record #* _type : cairo_path_data_type_t; cairo_path_data_t* {.final.} = object #* _type : cairo_path_data_type_t;
# length : LongInt; # length : LongInt;
# end # end
x: float64 x: float64
y: float64 y: float64
cairo_path_t* = record cairo_path_t* {.final.} = object
status: cairo_status_t status: cairo_status_t
data: Pcairo_path_data_t data: Pcairo_path_data_t
num_data: int32 num_data: int32
cairo_rectangle_t* = record cairo_rectangle_t* {.final.} = object
x, y, width, height: float64 x, y, width, height: float64
cairo_rectangle_list_t* = record cairo_rectangle_list_t* {.final.} = object
status: cairo_status_t status: cairo_status_t
rectangles: Pcairo_rectangle_t rectangles: Pcairo_rectangle_t
num_rectangles: int32 num_rectangles: int32

View file

@ -56,7 +56,7 @@ type
ATK_LAYER_INVALID, ATK_LAYER_BACKGROUND, ATK_LAYER_CANVAS, ATK_LAYER_WIDGET, ATK_LAYER_INVALID, ATK_LAYER_BACKGROUND, ATK_LAYER_CANVAS, ATK_LAYER_WIDGET,
ATK_LAYER_MDI, ATK_LAYER_POPUP, ATK_LAYER_OVERLAY ATK_LAYER_MDI, ATK_LAYER_POPUP, ATK_LAYER_OVERLAY
PAtkPropertyValues* = ptr TAtkPropertyValues PAtkPropertyValues* = ptr TAtkPropertyValues
TAtkPropertyValues* = record TAtkPropertyValues* {.final.} = object
property_name*: cstring property_name*: cstring
old_value*: TGValue old_value*: TGValue
new_value*: TGValue new_value*: TGValue
@ -379,7 +379,7 @@ type
TAtkAttributeSet* = TGSList TAtkAttributeSet* = TGSList
PAtkAttribute* = ptr TAtkAttribute PAtkAttribute* = ptr TAtkAttribute
TAtkAttribute* = record TAtkAttribute* {.final.} = object
name*: cstring name*: cstring
value*: cstring value*: cstring
@ -453,7 +453,7 @@ type
TAtkEventListenerInitProc* = proc () TAtkEventListenerInitProc* = proc ()
TAtkEventListenerInit* = proc (para1: TAtkEventListenerInitProc){.cdecl.} TAtkEventListenerInit* = proc (para1: TAtkEventListenerInitProc){.cdecl.}
PAtkKeyEventStruct* = ptr TAtkKeyEventStruct PAtkKeyEventStruct* = ptr TAtkKeyEventStruct
TAtkKeyEventStruct* = record TAtkKeyEventStruct* {.final.} = object
`type`*: gint `type`*: gint
state*: guint state*: guint
keyval*: guint keyval*: guint

View file

@ -32,7 +32,7 @@ type
TGdkVisualClass* = object of TGObjectClass TGdkVisualClass* = object of TGObjectClass
PGdkColor* = ptr TGdkColor PGdkColor* = ptr TGdkColor
TGdkColor* = record TGdkColor* {.final.} = object
pixel*: guint32 pixel*: guint32
red*: guint16 red*: guint16
green*: guint16 green*: guint16
@ -52,7 +52,7 @@ type
TGdkFontType* = enum TGdkFontType* = enum
GDK_FONT_FONT, GDK_FONT_FONTSET GDK_FONT_FONT, GDK_FONT_FONTSET
PGdkFont* = ptr TGdkFont PGdkFont* = ptr TGdkFont
TGdkFont* = record TGdkFont* {.final.} = object
`type`*: TGdkFontType `type`*: TGdkFontType
ascent*: gint ascent*: gint
descent*: gint descent*: gint
@ -79,7 +79,7 @@ type
PGdkGCValuesMask* = ptr TGdkGCValuesMask PGdkGCValuesMask* = ptr TGdkGCValuesMask
TGdkGCValuesMask* = int32 TGdkGCValuesMask* = int32
PGdkGCValues* = ptr TGdkGCValues PGdkGCValues* = ptr TGdkGCValues
TGdkGCValues* = record TGdkGCValues* {.final.} = object
foreground*: TGdkColor foreground*: TGdkColor
background*: TGdkColor background*: TGdkColor
font*: PGdkFont font*: PGdkFont
@ -125,7 +125,7 @@ type
TGdkInputCondition* = int32 TGdkInputCondition* = int32
PGdkStatus* = ptr TGdkStatus PGdkStatus* = ptr TGdkStatus
TGdkStatus* = int32 TGdkStatus* = int32
TGdkPoint* = record TGdkPoint* {.final.} = object
x*: gint x*: gint
y*: gint y*: gint
@ -135,14 +135,14 @@ type
PGdkWChar* = ptr TGdkWChar PGdkWChar* = ptr TGdkWChar
TGdkWChar* = guint32 TGdkWChar* = guint32
PGdkSegment* = ptr TGdkSegment PGdkSegment* = ptr TGdkSegment
TGdkSegment* = record TGdkSegment* {.final.} = object
x1*: gint x1*: gint
y1*: gint y1*: gint
x2*: gint x2*: gint
y2*: gint y2*: gint
PGdkRectangle* = ptr TGdkRectangle PGdkRectangle* = ptr TGdkRectangle
TGdkRectangle* = record TGdkRectangle* {.final.} = object
x*: gint x*: gint
y*: gint y*: gint
width*: gint width*: gint
@ -190,7 +190,7 @@ type
PGdkCursorType* = ptr TGdkCursorType PGdkCursorType* = ptr TGdkCursorType
TGdkCursorType* = gint TGdkCursorType* = gint
PGdkCursor* = ptr TGdkCursor PGdkCursor* = ptr TGdkCursor
TGdkCursor* = record TGdkCursor* {.final.} = object
`type`*: TGdkCursorType `type`*: TGdkCursorType
ref_count*: guint ref_count*: guint
@ -220,14 +220,14 @@ type
PGdkRegionBox* = ptr TGdkRegionBox PGdkRegionBox* = ptr TGdkRegionBox
TGdkRegionBox* = TGdkSegment TGdkRegionBox* = TGdkSegment
PGdkRegion* = ptr TGdkRegion PGdkRegion* = ptr TGdkRegion
TGdkRegion* = record TGdkRegion* {.final.} = object
size*: int32 size*: int32
numRects*: int32 numRects*: int32
rects*: PGdkRegionBox rects*: PGdkRegionBox
extents*: TGdkRegionBox extents*: TGdkRegionBox
PPOINTBLOCK* = ptr TPOINTBLOCK PPOINTBLOCK* = ptr TPOINTBLOCK
TPOINTBLOCK* = record TPOINTBLOCK* {.final.} = object
pts*: array[0..(NUMPTSTOBUFFER) - 1, TGdkPoint] pts*: array[0..(NUMPTSTOBUFFER) - 1, TGdkPoint]
next*: PPOINTBLOCK next*: PPOINTBLOCK
@ -336,13 +336,13 @@ type
GDK_SETTING_ACTION_NEW, GDK_SETTING_ACTION_CHANGED, GDK_SETTING_ACTION_NEW, GDK_SETTING_ACTION_CHANGED,
GDK_SETTING_ACTION_DELETED GDK_SETTING_ACTION_DELETED
PGdkEventAny* = ptr TGdkEventAny PGdkEventAny* = ptr TGdkEventAny
TGdkEventAny* = record TGdkEventAny* {.final.} = object
`type`*: TGdkEventType `type`*: TGdkEventType
window*: PGdkWindow window*: PGdkWindow
send_event*: gint8 send_event*: gint8
PGdkEventExpose* = ptr TGdkEventExpose PGdkEventExpose* = ptr TGdkEventExpose
TGdkEventExpose* = record TGdkEventExpose* {.final.} = object
`type`*: TGdkEventType `type`*: TGdkEventType
window*: PGdkWindow window*: PGdkWindow
send_event*: gint8 send_event*: gint8
@ -351,20 +351,20 @@ type
count*: gint count*: gint
PGdkEventNoExpose* = ptr TGdkEventNoExpose PGdkEventNoExpose* = ptr TGdkEventNoExpose
TGdkEventNoExpose* = record TGdkEventNoExpose* {.final.} = object
`type`*: TGdkEventType `type`*: TGdkEventType
window*: PGdkWindow window*: PGdkWindow
send_event*: gint8 send_event*: gint8
PGdkEventVisibility* = ptr TGdkEventVisibility PGdkEventVisibility* = ptr TGdkEventVisibility
TGdkEventVisibility* = record TGdkEventVisibility* {.final.} = object
`type`*: TGdkEventType `type`*: TGdkEventType
window*: PGdkWindow window*: PGdkWindow
send_event*: gint8 send_event*: gint8
state*: TGdkVisibilityState state*: TGdkVisibilityState
PGdkEventMotion* = ptr TGdkEventMotion PGdkEventMotion* = ptr TGdkEventMotion
TGdkEventMotion* = record TGdkEventMotion* {.final.} = object
`type`*: TGdkEventType `type`*: TGdkEventType
window*: PGdkWindow window*: PGdkWindow
send_event*: gint8 send_event*: gint8
@ -379,7 +379,7 @@ type
y_root*: gdouble y_root*: gdouble
PGdkEventButton* = ptr TGdkEventButton PGdkEventButton* = ptr TGdkEventButton
TGdkEventButton* = record TGdkEventButton* {.final.} = object
`type`*: TGdkEventType `type`*: TGdkEventType
window*: PGdkWindow window*: PGdkWindow
send_event*: gint8 send_event*: gint8
@ -394,7 +394,7 @@ type
y_root*: gdouble y_root*: gdouble
PGdkEventScroll* = ptr TGdkEventScroll PGdkEventScroll* = ptr TGdkEventScroll
TGdkEventScroll* = record TGdkEventScroll* {.final.} = object
`type`*: TGdkEventType `type`*: TGdkEventType
window*: PGdkWindow window*: PGdkWindow
send_event*: gint8 send_event*: gint8
@ -408,7 +408,7 @@ type
y_root*: gdouble y_root*: gdouble
PGdkEventKey* = ptr TGdkEventKey PGdkEventKey* = ptr TGdkEventKey
TGdkEventKey* = record TGdkEventKey* {.final.} = object
`type`*: TGdkEventType `type`*: TGdkEventType
window*: PGdkWindow window*: PGdkWindow
send_event*: gint8 send_event*: gint8
@ -421,7 +421,7 @@ type
group*: guint8 group*: guint8
PGdkEventCrossing* = ptr TGdkEventCrossing PGdkEventCrossing* = ptr TGdkEventCrossing
TGdkEventCrossing* = record TGdkEventCrossing* {.final.} = object
`type`*: TGdkEventType `type`*: TGdkEventType
window*: PGdkWindow window*: PGdkWindow
send_event*: gint8 send_event*: gint8
@ -437,14 +437,14 @@ type
state*: guint state*: guint
PGdkEventFocus* = ptr TGdkEventFocus PGdkEventFocus* = ptr TGdkEventFocus
TGdkEventFocus* = record TGdkEventFocus* {.final.} = object
`type`*: TGdkEventType `type`*: TGdkEventType
window*: PGdkWindow window*: PGdkWindow
send_event*: gint8 send_event*: gint8
`in`*: gint16 `in`*: gint16
PGdkEventConfigure* = ptr TGdkEventConfigure PGdkEventConfigure* = ptr TGdkEventConfigure
TGdkEventConfigure* = record TGdkEventConfigure* {.final.} = object
`type`*: TGdkEventType `type`*: TGdkEventType
window*: PGdkWindow window*: PGdkWindow
send_event*: gint8 send_event*: gint8
@ -454,7 +454,7 @@ type
height*: gint height*: gint
PGdkEventProperty* = ptr TGdkEventProperty PGdkEventProperty* = ptr TGdkEventProperty
TGdkEventProperty* = record TGdkEventProperty* {.final.} = object
`type`*: TGdkEventType `type`*: TGdkEventType
window*: PGdkWindow window*: PGdkWindow
send_event*: gint8 send_event*: gint8
@ -464,7 +464,7 @@ type
TGdkNativeWindow* = pointer TGdkNativeWindow* = pointer
PGdkEventSelection* = ptr TGdkEventSelection PGdkEventSelection* = ptr TGdkEventSelection
TGdkEventSelection* = record TGdkEventSelection* {.final.} = object
`type`*: TGdkEventType `type`*: TGdkEventType
window*: PGdkWindow window*: PGdkWindow
send_event*: gint8 send_event*: gint8
@ -475,7 +475,7 @@ type
requestor*: TGdkNativeWindow requestor*: TGdkNativeWindow
PGdkEventProximity* = ptr TGdkEventProximity PGdkEventProximity* = ptr TGdkEventProximity
TGdkEventProximity* = record TGdkEventProximity* {.final.} = object
`type`*: TGdkEventType `type`*: TGdkEventType
window*: PGdkWindow window*: PGdkWindow
send_event*: gint8 send_event*: gint8
@ -483,11 +483,11 @@ type
device*: PGdkDevice device*: PGdkDevice
PmatDUMMY* = ptr TmatDUMMY PmatDUMMY* = ptr TmatDUMMY
TmatDUMMY* = record TmatDUMMY* {.final.} = object
b*: array[0..19, char] b*: array[0..19, char]
PGdkEventClient* = ptr TGdkEventClient PGdkEventClient* = ptr TGdkEventClient
TGdkEventClient* = record TGdkEventClient* {.final.} = object
`type`*: TGdkEventType `type`*: TGdkEventType
window*: PGdkWindow window*: PGdkWindow
send_event*: gint8 send_event*: gint8
@ -496,7 +496,7 @@ type
b*: array[0..19, char] b*: array[0..19, char]
PGdkEventSetting* = ptr TGdkEventSetting PGdkEventSetting* = ptr TGdkEventSetting
TGdkEventSetting* = record TGdkEventSetting* {.final.} = object
`type`*: TGdkEventType `type`*: TGdkEventType
window*: PGdkWindow window*: PGdkWindow
send_event*: gint8 send_event*: gint8
@ -504,7 +504,7 @@ type
name*: cstring name*: cstring
PGdkEventWindowState* = ptr TGdkEventWindowState PGdkEventWindowState* = ptr TGdkEventWindowState
TGdkEventWindowState* = record TGdkEventWindowState* {.final.} = object
`type`*: TGdkEventType `type`*: TGdkEventType
window*: PGdkWindow window*: PGdkWindow
send_event*: gint8 send_event*: gint8
@ -512,7 +512,7 @@ type
new_window_state*: TGdkWindowState new_window_state*: TGdkWindowState
PGdkEventDND* = ptr TGdkEventDND PGdkEventDND* = ptr TGdkEventDND
TGdkEventDND* = record TGdkEventDND* {.final.} = object
`type`*: TGdkEventType `type`*: TGdkEventType
window*: PGdkWindow window*: PGdkWindow
send_event*: gint8 send_event*: gint8
@ -521,7 +521,7 @@ type
x_root*: gshort x_root*: gshort
y_root*: gshort y_root*: gshort
TGdkEvent* = record TGdkEvent* {.final.} = object
data*: array[0..255, char] # union of data*: array[0..255, char] # union of
# `type`: TGdkEventType # `type`: TGdkEventType
# any: TGdkEventAny # any: TGdkEventAny
@ -585,12 +585,12 @@ type
PGdkAxisUse* = ptr TGdkAxisUse PGdkAxisUse* = ptr TGdkAxisUse
TGdkAxisUse* = int32 TGdkAxisUse* = int32
PGdkDeviceKey* = ptr TGdkDeviceKey PGdkDeviceKey* = ptr TGdkDeviceKey
TGdkDeviceKey* = record TGdkDeviceKey* {.final.} = object
keyval*: guint keyval*: guint
modifiers*: TGdkModifierType modifiers*: TGdkModifierType
PGdkDeviceAxis* = ptr TGdkDeviceAxis PGdkDeviceAxis* = ptr TGdkDeviceAxis
TGdkDeviceAxis* = record TGdkDeviceAxis* {.final.} = object
use*: TGdkAxisUse use*: TGdkAxisUse
min*: gdouble min*: gdouble
max*: gdouble max*: gdouble
@ -605,12 +605,12 @@ type
num_keys*: gint num_keys*: gint
keys*: PGdkDeviceKey keys*: PGdkDeviceKey
TGdkTimeCoord* = record TGdkTimeCoord* {.final.} = object
time*: guint32 time*: guint32
axes*: array[0..(GDK_MAX_TIMECOORD_AXES) - 1, gdouble] axes*: array[0..(GDK_MAX_TIMECOORD_AXES) - 1, gdouble]
PGdkKeymapKey* = ptr TGdkKeymapKey PGdkKeymapKey* = ptr TGdkKeymapKey
TGdkKeymapKey* = record TGdkKeymapKey* {.final.} = object
keycode*: guint keycode*: guint
group*: gint group*: gint
level*: gint level*: gint
@ -624,12 +624,12 @@ type
direction_changed*: proc (keymap: PGdkKeymap){.cdecl.} direction_changed*: proc (keymap: PGdkKeymap){.cdecl.}
PGdkPangoAttrStipple* = ptr TGdkPangoAttrStipple PGdkPangoAttrStipple* = ptr TGdkPangoAttrStipple
TGdkPangoAttrStipple* = record TGdkPangoAttrStipple* {.final.} = object
attr*: TPangoAttribute attr*: TPangoAttribute
stipple*: PGdkBitmap stipple*: PGdkBitmap
PGdkPangoAttrEmbossed* = ptr TGdkPangoAttrEmbossed PGdkPangoAttrEmbossed* = ptr TGdkPangoAttrEmbossed
TGdkPangoAttrEmbossed* = record TGdkPangoAttrEmbossed* {.final.} = object
attr*: TPangoAttribute attr*: TPangoAttribute
embossed*: gboolean embossed*: gboolean
@ -653,7 +653,7 @@ type
GDK_OVERLAP_RECTANGLE_PART GDK_OVERLAP_RECTANGLE_PART
TGdkSpanFunc* = proc (span: PGdkSpan, data: gpointer){.cdecl.} TGdkSpanFunc* = proc (span: PGdkSpan, data: gpointer){.cdecl.}
PGdkRgbCmap* = ptr TGdkRgbCmap PGdkRgbCmap* = ptr TGdkRgbCmap
TGdkRgbCmap* = record TGdkRgbCmap* {.final.} = object
colors*: array[0..255, guint32] colors*: array[0..255, guint32]
n_colors*: gint n_colors*: gint
info_list*: PGSList info_list*: PGSList
@ -698,7 +698,7 @@ type
TGdkInputFunction* = proc (data: gpointer, source: gint, TGdkInputFunction* = proc (data: gpointer, source: gint,
condition: TGdkInputCondition){.cdecl.} condition: TGdkInputCondition){.cdecl.}
TGdkDestroyNotify* = proc (data: gpointer){.cdecl.} TGdkDestroyNotify* = proc (data: gpointer){.cdecl.}
TGdkSpan* = record TGdkSpan* {.final.} = object
x*: gint x*: gint
y*: gint y*: gint
width*: gint width*: gint
@ -731,7 +731,7 @@ type
GDK_WINDOW_EDGE_SOUTH_WEST, GDK_WINDOW_EDGE_SOUTH, GDK_WINDOW_EDGE_SOUTH_WEST, GDK_WINDOW_EDGE_SOUTH,
GDK_WINDOW_EDGE_SOUTH_EAST GDK_WINDOW_EDGE_SOUTH_EAST
PGdkWindowAttr* = ptr TGdkWindowAttr PGdkWindowAttr* = ptr TGdkWindowAttr
TGdkWindowAttr* = record TGdkWindowAttr* {.final.} = object
title*: cstring title*: cstring
event_mask*: gint event_mask*: gint
x*: gint x*: gint
@ -748,7 +748,7 @@ type
override_redirect*: gboolean override_redirect*: gboolean
PGdkGeometry* = ptr TGdkGeometry PGdkGeometry* = ptr TGdkGeometry
TGdkGeometry* = record TGdkGeometry* {.final.} = object
min_width*: gint min_width*: gint
min_height*: gint min_height*: gint
max_width*: gint max_width*: gint
@ -762,7 +762,7 @@ type
win_gravity*: TGdkGravity win_gravity*: TGdkGravity
PGdkPointerHooks* = ptr TGdkPointerHooks PGdkPointerHooks* = ptr TGdkPointerHooks
TGdkPointerHooks* = record TGdkPointerHooks* {.final.} = object
get_pointer*: proc (window: PGdkWindow, x: Pgint, y: Pgint, get_pointer*: proc (window: PGdkWindow, x: Pgint, y: Pgint,
mask: PGdkModifierType): PGdkWindow{.cdecl.} mask: PGdkModifierType): PGdkWindow{.cdecl.}
window_at_pointer*: proc (screen: PGdkScreen, win_x: Pgint, win_y: Pgint): PGdkWindow{. window_at_pointer*: proc (screen: PGdkScreen, win_x: Pgint, win_y: Pgint): PGdkWindow{.

View file

@ -191,12 +191,12 @@ proc gdk_pixbuf_get_option*(pixbuf: PGdkPixbuf, key: cstring): cstring{.cdecl,
dynlib: gdkpixbuflib, importc: "gdk_pixbuf_get_option".} dynlib: gdkpixbuflib, importc: "gdk_pixbuf_get_option".}
type type
PGdkPixbufLoader* = ptr TGdkPixbufLoader PGdkPixbufLoader* = ptr TGdkPixbufLoader
TGdkPixbufLoader* = record TGdkPixbufLoader* {.final.} = object
parent_instance*: TGObject parent_instance*: TGObject
priv*: gpointer priv*: gpointer
PGdkPixbufLoaderClass* = ptr TGdkPixbufLoaderClass PGdkPixbufLoaderClass* = ptr TGdkPixbufLoaderClass
TGdkPixbufLoaderClass* = record TGdkPixbufLoaderClass* {.final.} = object
parent_class*: TGObjectClass parent_class*: TGObjectClass
area_prepared*: proc (loader: PGdkPixbufLoader){.cdecl.} area_prepared*: proc (loader: PGdkPixbufLoader){.cdecl.}
area_updated*: proc (loader: PGdkPixbufLoader, x: int32, y: int32, area_updated*: proc (loader: PGdkPixbufLoader, x: int32, y: int32,

View file

@ -61,7 +61,7 @@ type
TGHFunc* = proc (key, value, user_data: gpointer){.cdecl.} TGHFunc* = proc (key, value, user_data: gpointer){.cdecl.}
PGFreeFunc* = proc (data: gpointer){.cdecl.} PGFreeFunc* = proc (data: gpointer){.cdecl.}
PGTimeVal* = ptr TGTimeVal PGTimeVal* = ptr TGTimeVal
TGTimeVal* = record TGTimeVal* {.final.} = object
tv_sec*: glong tv_sec*: glong
tv_usec*: glong tv_usec*: glong
@ -88,17 +88,17 @@ type
TGQuark* = guint32 TGQuark* = guint32
PGQuark* = ptr TGQuark PGQuark* = ptr TGQuark
PGTypeCValue* = ptr TGTypeCValue PGTypeCValue* = ptr TGTypeCValue
TGTypeCValue* = record TGTypeCValue* {.final.} = object
v_double*: gdouble v_double*: gdouble
GType* = gulong GType* = gulong
PGType* = ptr GType PGType* = ptr GType
PGTypeClass* = ptr TGTypeClass PGTypeClass* = ptr TGTypeClass
TGTypeClass* = record TGTypeClass* {.final.} = object
g_type*: GType g_type*: GType
PGTypeInstance* = ptr TGTypeInstance PGTypeInstance* = ptr TGTypeInstance
TGTypeInstance* = record TGTypeInstance* {.final.} = object
g_class*: PGTypeClass g_class*: PGTypeClass
PGTypeInterface* = ptr TGTypeInterface PGTypeInterface* = ptr TGTypeInterface
@ -107,14 +107,14 @@ type
g_instance_type*: GType g_instance_type*: GType
PGTypeQuery* = ptr TGTypeQuery PGTypeQuery* = ptr TGTypeQuery
TGTypeQuery* = record TGTypeQuery* {.final.} = object
theType*: GType theType*: GType
type_name*: cstring type_name*: cstring
class_size*: guint class_size*: guint
instance_size*: guint instance_size*: guint
PGValue* = ptr TGValue PGValue* = ptr TGValue
TGValue* = record TGValue* {.final.} = object
g_type*: GType g_type*: GType
data*: array[0..1, gdouble] data*: array[0..1, gdouble]
@ -122,12 +122,12 @@ type
PGData* = pointer PGData* = pointer
PGSList* = ptr TGSList PGSList* = ptr TGSList
PPGSList* = ptr PGSList PPGSList* = ptr PGSList
TGSList* = record TGSList* {.final.} = object
data*: gpointer data*: gpointer
next*: PGSList next*: PGSList
PGList* = ptr TGList PGList* = ptr TGList
TGList* = record TGList* {.final.} = object
data*: gpointer data*: gpointer
next*: PGList next*: PGList
prev*: PGList prev*: PGList
@ -136,7 +136,7 @@ type
TGParamFlags* = int32 TGParamFlags* = int32
PGParamSpec* = ptr TGParamSpec PGParamSpec* = ptr TGParamSpec
PPGParamSpec* = ptr PGParamSpec PPGParamSpec* = ptr PGParamSpec
TGParamSpec* = record TGParamSpec* {.final.} = object
g_type_instance*: TGTypeInstance g_type_instance*: TGTypeInstance
name*: cstring name*: cstring
flags*: TGParamFlags flags*: TGParamFlags
@ -149,7 +149,7 @@ type
param_id*: guint param_id*: guint
PGParamSpecClass* = ptr TGParamSpecClass PGParamSpecClass* = ptr TGParamSpecClass
TGParamSpecClass* = record TGParamSpecClass* {.final.} = object
g_type_class*: TGTypeClass g_type_class*: TGTypeClass
value_type*: GType value_type*: GType
finalize*: proc (pspec: PGParamSpec){.cdecl.} finalize*: proc (pspec: PGParamSpec){.cdecl.}
@ -160,7 +160,7 @@ type
dummy*: array[0..3, gpointer] dummy*: array[0..3, gpointer]
PGParameter* = ptr TGParameter PGParameter* = ptr TGParameter
TGParameter* = record TGParameter* {.final.} = object
name*: cstring name*: cstring
value*: TGValue value*: TGValue
@ -305,7 +305,7 @@ const
type type
PGTypeValueTable* = ptr TGTypeValueTable PGTypeValueTable* = ptr TGTypeValueTable
TGTypeValueTable* = record TGTypeValueTable* {.final.} = object
value_init*: proc (value: PGValue){.cdecl.} value_init*: proc (value: PGValue){.cdecl.}
value_free*: proc (value: PGValue){.cdecl.} value_free*: proc (value: PGValue){.cdecl.}
value_copy*: proc (src_value: PGValue, dest_value: PGValue){.cdecl.} value_copy*: proc (src_value: PGValue, dest_value: PGValue){.cdecl.}
@ -320,7 +320,7 @@ type
cdecl.} cdecl.}
PGTypeInfo* = ptr TGTypeInfo PGTypeInfo* = ptr TGTypeInfo
TGTypeInfo* = record TGTypeInfo* {.final.} = object
class_size*: guint16 class_size*: guint16
base_init*: TGBaseInitFunc base_init*: TGBaseInitFunc
base_finalize*: TGBaseFinalizeFunc base_finalize*: TGBaseFinalizeFunc
@ -333,11 +333,11 @@ type
value_table*: PGTypeValueTable value_table*: PGTypeValueTable
PGTypeFundamentalInfo* = ptr TGTypeFundamentalInfo PGTypeFundamentalInfo* = ptr TGTypeFundamentalInfo
TGTypeFundamentalInfo* = record TGTypeFundamentalInfo* {.final.} = object
type_flags*: TGTypeFundamentalFlags type_flags*: TGTypeFundamentalFlags
PGInterfaceInfo* = ptr TGInterfaceInfo PGInterfaceInfo* = ptr TGInterfaceInfo
TGInterfaceInfo* = record TGInterfaceInfo* {.final.} = object
interface_init*: TGInterfaceInitFunc interface_init*: TGInterfaceInitFunc
interface_finalize*: TGInterfaceFinalizeFunc interface_finalize*: TGInterfaceFinalizeFunc
interface_data*: gpointer interface_data*: gpointer
@ -449,7 +449,7 @@ const
type type
PGValueArray* = ptr TGValueArray PGValueArray* = ptr TGValueArray
TGValueArray* = record TGValueArray* {.final.} = object
n_values*: guint n_values*: guint
values*: PGValue values*: PGValue
n_prealloced*: guint n_prealloced*: guint
@ -628,7 +628,7 @@ proc g_value_set_param_take_ownership*(value: PGValue, param: PGParamSpec){.
cdecl, dynlib: gliblib, importc: "g_value_set_param_take_ownership".} cdecl, dynlib: gliblib, importc: "g_value_set_param_take_ownership".}
type type
PGParamSpecTypeInfo* = ptr TGParamSpecTypeInfo PGParamSpecTypeInfo* = ptr TGParamSpecTypeInfo
TGParamSpecTypeInfo* = record TGParamSpecTypeInfo* {.final.} = object
instance_size*: guint16 instance_size*: guint16
n_preallocs*: guint16 n_preallocs*: guint16
instance_init*: proc (pspec: PGParamSpec){.cdecl.} instance_init*: proc (pspec: PGParamSpec){.cdecl.}
@ -668,7 +668,7 @@ type
PGClosure* = ptr TGClosure PGClosure* = ptr TGClosure
PGClosureNotifyData* = ptr TGClosureNotifyData PGClosureNotifyData* = ptr TGClosureNotifyData
TGClosureNotify* = proc (data: gpointer, closure: PGClosure){.cdecl.} TGClosureNotify* = proc (data: gpointer, closure: PGClosure){.cdecl.}
TGClosure* = record TGClosure* {.final.} = object
flag0*: int32 flag0*: int32
marshal*: proc (closure: PGClosure, return_value: PGValue, marshal*: proc (closure: PGClosure, return_value: PGValue,
n_param_values: guint, param_values: PGValue, n_param_values: guint, param_values: PGValue,
@ -682,7 +682,7 @@ type
n_param_values: guint, param_values: PGValue, n_param_values: guint, param_values: PGValue,
invocation_hint: gpointer, marshal_data: gpointer){. invocation_hint: gpointer, marshal_data: gpointer){.
cdecl.} cdecl.}
TGClosureNotifyData* = record TGClosureNotifyData* {.final.} = object
data*: gpointer data*: gpointer
notify*: TGClosureNotify notify*: TGClosureNotify
@ -734,7 +734,7 @@ proc is_invalid*(a: var TGClosure): guint
proc set_is_invalid*(a: var TGClosure, is_invalid: guint) proc set_is_invalid*(a: var TGClosure, is_invalid: guint)
type type
PGCClosure* = ptr TGCClosure PGCClosure* = ptr TGCClosure
TGCClosure* = record TGCClosure* {.final.} = object
closure*: TGClosure closure*: TGClosure
callback*: gpointer callback*: gpointer
@ -797,13 +797,13 @@ type
data: gpointer): gboolean{.cdecl.} data: gpointer): gboolean{.cdecl.}
PGSignalFlags* = ptr TGSignalFlags PGSignalFlags* = ptr TGSignalFlags
TGSignalFlags* = int32 TGSignalFlags* = int32
TGSignalInvocationHint* = record TGSignalInvocationHint* {.final.} = object
signal_id*: guint signal_id*: guint
detail*: TGQuark detail*: TGQuark
run_type*: TGSignalFlags run_type*: TGSignalFlags
PGSignalQuery* = ptr TGSignalQuery PGSignalQuery* = ptr TGSignalQuery
TGSignalQuery* = record TGSignalQuery* {.final.} = object
signal_id*: guint signal_id*: guint
signal_name*: cstring signal_name*: cstring
itype*: GType itype*: GType
@ -952,7 +952,7 @@ type
TGTypePluginCompleteInterfaceInfo* = proc (plugin: PGTypePlugin, TGTypePluginCompleteInterfaceInfo* = proc (plugin: PGTypePlugin,
instance_type: GType, interface_type: GType, info: PGInterfaceInfo){.cdecl.} instance_type: GType, interface_type: GType, info: PGInterfaceInfo){.cdecl.}
PGTypePluginClass* = ptr TGTypePluginClass PGTypePluginClass* = ptr TGTypePluginClass
TGTypePluginClass* = record TGTypePluginClass* {.final.} = object
base_iface*: TGTypeInterface base_iface*: TGTypeInterface
use_plugin*: TGTypePluginUse use_plugin*: TGTypePluginUse
unuse_plugin*: TGTypePluginUnuse unuse_plugin*: TGTypePluginUnuse
@ -1011,7 +1011,7 @@ type
notify*: proc (anObject: PGObject, pspec: PGParamSpec){.cdecl.} notify*: proc (anObject: PGObject, pspec: PGParamSpec){.cdecl.}
pdummy*: array[0..7, gpointer] pdummy*: array[0..7, gpointer]
TGObjectConstructParam* = record TGObjectConstructParam* {.final.} = object
pspec*: PGParamSpec pspec*: PGParamSpec
value*: PGValue value*: PGValue
@ -1125,27 +1125,27 @@ proc GUINT32_SWAP_LE_BE_CONSTANT*(val: guint32): guint32
type type
PGEnumClass* = ptr TGEnumClass PGEnumClass* = ptr TGEnumClass
PGEnumValue* = ptr TGEnumValue PGEnumValue* = ptr TGEnumValue
TGEnumClass* = record TGEnumClass* {.final.} = object
g_type_class*: TGTypeClass g_type_class*: TGTypeClass
minimum*: gint minimum*: gint
maximum*: gint maximum*: gint
n_values*: guint n_values*: guint
values*: PGEnumValue values*: PGEnumValue
TGEnumValue* = record TGEnumValue* {.final.} = object
value*: gint value*: gint
value_name*: cstring value_name*: cstring
value_nick*: cstring value_nick*: cstring
PGFlagsClass* = ptr TGFlagsClass PGFlagsClass* = ptr TGFlagsClass
PGFlagsValue* = ptr TGFlagsValue PGFlagsValue* = ptr TGFlagsValue
TGFlagsClass* = record TGFlagsClass* {.final.} = object
g_type_class*: TGTypeClass g_type_class*: TGTypeClass
mask*: guint mask*: guint
n_values*: guint n_values*: guint
values*: PGFlagsValue values*: PGFlagsValue
TGFlagsValue* = record TGFlagsValue* {.final.} = object
value*: guint value*: guint
value_name*: cstring value_name*: cstring
value_nick*: cstring value_nick*: cstring
@ -1203,7 +1203,7 @@ const
G_MAXUSHORT* = 2 * G_MAXSHORT + 1 G_MAXUSHORT* = 2 * G_MAXSHORT + 1
G_MAXINT* = 2147483647 G_MAXINT* = 2147483647
G_MININT* = - G_MAXINT - 1 G_MININT* = - G_MAXINT - 1
G_MAXUINT* = 4294967295 G_MAXUINT* = -1
G_MINLONG* = G_MININT G_MINLONG* = G_MININT
G_MAXLONG* = G_MAXINT G_MAXLONG* = G_MAXINT
G_MAXULONG* = G_MAXUINT G_MAXULONG* = G_MAXUINT
@ -1224,7 +1224,7 @@ const
type type
PGSystemThread* = ptr TGSystemThread PGSystemThread* = ptr TGSystemThread
TGSystemThread* = record TGSystemThread* {.final.} = object
data*: array[0..3, char] data*: array[0..3, char]
dummy_double*: float64 dummy_double*: float64
dummy_pointer*: pointer dummy_pointer*: pointer
@ -1350,7 +1350,7 @@ proc g_set_prgname*(prgname: cstring){.cdecl, dynlib: gliblib,
importc: "g_set_prgname".} importc: "g_set_prgname".}
type type
PGDebugKey* = ptr TGDebugKey PGDebugKey* = ptr TGDebugKey
TGDebugKey* = record TGDebugKey* {.final.} = object
key*: cstring key*: cstring
value*: guint value*: guint
@ -1390,7 +1390,7 @@ proc g_bit_storage*(number: gulong): guint{.cdecl, dynlib: gliblib,
type type
PPGTrashStack* = ptr PGTrashStack PPGTrashStack* = ptr PGTrashStack
PGTrashStack* = ptr TGTrashStack PGTrashStack* = ptr TGTrashStack
TGTrashStack* = record TGTrashStack* {.final.} = object
next*: PGTrashStack next*: PGTrashStack
@ -1466,7 +1466,7 @@ const
type type
PGMemVTable* = ptr TGMemVTable PGMemVTable* = ptr TGMemVTable
TGMemVTable* = record TGMemVTable* {.final.} = object
malloc*: proc (n_bytes: gsize): gpointer{.cdecl.} malloc*: proc (n_bytes: gsize): gpointer{.cdecl.}
realloc*: proc (mem: gpointer, n_bytes: gsize): gpointer{.cdecl.} realloc*: proc (mem: gpointer, n_bytes: gsize): gpointer{.cdecl.}
free*: proc (mem: gpointer){.cdecl.} free*: proc (mem: gpointer){.cdecl.}
@ -1679,7 +1679,7 @@ type
TGCompletionStrncmpFunc* = proc (s1: cstring, s2: cstring, n: gsize): gint{. TGCompletionStrncmpFunc* = proc (s1: cstring, s2: cstring, n: gsize): gint{.
cdecl.} cdecl.}
PGCompletion* = ptr TGCompletion PGCompletion* = ptr TGCompletion
TGCompletion* = record TGCompletion* {.final.} = object
items*: PGList items*: PGList
func*: TGCompletionFunc func*: TGCompletionFunc
prefix*: cstring prefix*: cstring
@ -1809,7 +1809,7 @@ type
PGDateDay* = ptr TGDateDay PGDateDay* = ptr TGDateDay
TGDateDay* = guint8 TGDateDay* = guint8
Ptm* = ptr Ttm Ptm* = ptr Ttm
Ttm* = record Ttm* {.final.} = object
tm_sec*: gint tm_sec*: gint
tm_min*: gint tm_min*: gint
tm_hour*: gint tm_hour*: gint
@ -1872,7 +1872,7 @@ const
type type
PGDate* = ptr TGDate PGDate* = ptr TGDate
TGDate* = record TGDate* {.final.} = object
flag0*: int32 flag0*: int32
flag1*: int32 flag1*: int32
@ -2028,7 +2028,7 @@ proc g_file_open_tmp*(tmpl: cstring, name_used: PPchar, error: pointer): int32{.
cdecl, dynlib: gliblib, importc: "g_file_open_tmp".} cdecl, dynlib: gliblib, importc: "g_file_open_tmp".}
type type
PGHook* = ptr TGHook PGHook* = ptr TGHook
TGHook* = record TGHook* {.final.} = object
data*: gpointer data*: gpointer
next*: PGHook next*: PGHook
prev*: PGHook prev*: PGHook
@ -2047,7 +2047,7 @@ type
TGHookFunc* = proc (data: gpointer){.cdecl.} TGHookFunc* = proc (data: gpointer){.cdecl.}
TGHookCheckFunc* = proc (data: gpointer): gboolean{.cdecl.} TGHookCheckFunc* = proc (data: gpointer): gboolean{.cdecl.}
TGHookFinalizeFunc* = proc (hook_list: PGHookList, hook: PGHook){.cdecl.} TGHookFinalizeFunc* = proc (hook_list: PGHookList, hook: PGHook){.cdecl.}
TGHookList* = record TGHookList* {.final.} = object
seq_id*: gulong seq_id*: gulong
flag0*: int32 flag0*: int32
hooks*: PGHook hooks*: PGHook
@ -2138,7 +2138,7 @@ proc g_hook_list_marshal_check*(hook_list: PGHookList, may_recurse: gboolean,
importc: "g_hook_list_marshal_check".} importc: "g_hook_list_marshal_check".}
type type
PGThreadPool* = ptr TGThreadPool PGThreadPool* = ptr TGThreadPool
TGThreadPool* = record TGThreadPool* {.final.} = object
func*: TGFunc func*: TGFunc
user_data*: gpointer user_data*: gpointer
exclusive*: gboolean exclusive*: gboolean
@ -2352,7 +2352,7 @@ proc g_utf8_collate_key*(str: cstring, len: gssize): cstring{.cdecl,
dynlib: gliblib, importc: "g_utf8_collate_key".} dynlib: gliblib, importc: "g_utf8_collate_key".}
type type
PGString* = ptr TGString PGString* = ptr TGString
TGString* = record TGString* {.final.} = object
str*: cstring str*: cstring
len*: gsize len*: gsize
allocated_len*: gsize allocated_len*: gsize
@ -2468,7 +2468,7 @@ type
TGIOFunc* = proc (source: PGIOChannel, condition: TGIOCondition, TGIOFunc* = proc (source: PGIOChannel, condition: TGIOCondition,
data: gpointer): gboolean{.cdecl.} data: gpointer): gboolean{.cdecl.}
PGIOFuncs* = ptr TGIOFuncs PGIOFuncs* = ptr TGIOFuncs
TGIOFuncs* = record TGIOFuncs* {.final.} = object
io_read*: proc (channel: PGIOChannel, buf: cstring, count: gsize, io_read*: proc (channel: PGIOChannel, buf: cstring, count: gsize,
bytes_read: Pgsize, err: pointer): TGIOStatus{.cdecl.} bytes_read: Pgsize, err: pointer): TGIOStatus{.cdecl.}
io_write*: proc (channel: PGIOChannel, buf: cstring, count: gsize, io_write*: proc (channel: PGIOChannel, buf: cstring, count: gsize,
@ -2483,7 +2483,7 @@ type
cdecl.} cdecl.}
io_get_flags*: proc (channel: PGIOChannel): TGIOFlags{.cdecl.} io_get_flags*: proc (channel: PGIOChannel): TGIOFlags{.cdecl.}
TGIOChannel* = record TGIOChannel* {.final.} = object
ref_count*: guint ref_count*: guint
funcs*: PGIOFuncs funcs*: PGIOFuncs
encoding*: cstring encoding*: cstring
@ -2699,7 +2699,7 @@ type
PGMarkupParseContext* = ptr TGMarkupParseContext PGMarkupParseContext* = ptr TGMarkupParseContext
TGMarkupParseContext* = pointer TGMarkupParseContext* = pointer
PGMarkupParser* = ptr TGMarkupParser PGMarkupParser* = ptr TGMarkupParser
TGMarkupParser* = record TGMarkupParser* {.final.} = object
start_element*: proc (context: PGMarkupParseContext, element_name: cstring, start_element*: proc (context: PGMarkupParseContext, element_name: cstring,
attribute_names: PPgchar, attribute_values: PPgchar, attribute_names: PPgchar, attribute_values: PPgchar,
user_data: gpointer, error: pointer){.cdecl.} user_data: gpointer, error: pointer){.cdecl.}
@ -2733,7 +2733,7 @@ proc g_markup_escape_text*(text: cstring, length: gssize): cstring{.cdecl,
dynlib: gliblib, importc: "g_markup_escape_text".} dynlib: gliblib, importc: "g_markup_escape_text".}
type type
PGNode* = ptr TGNode PGNode* = ptr TGNode
TGNode* = record TGNode* {.final.} = object
data*: gpointer data*: gpointer
next*: PGNode next*: PGNode
prev*: PGNode prev*: PGNode
@ -2886,7 +2886,7 @@ proc g_qsort_with_data*(pbase: gconstpointer, total_elems: gint, size: gsize,
cdecl, dynlib: gliblib, importc: "g_qsort_with_data".} cdecl, dynlib: gliblib, importc: "g_qsort_with_data".}
type type
PGQueue* = ptr TGQueue PGQueue* = ptr TGQueue
TGQueue* = record TGQueue* {.final.} = object
head*: PGList head*: PGList
tail*: PGList tail*: PGList
length*: guint length*: guint
@ -2947,7 +2947,7 @@ proc g_random_double_range*(`begin`: gdouble, `end`: gdouble): gdouble{.cdecl,
dynlib: gliblib, importc: "g_random_double_range".} dynlib: gliblib, importc: "g_random_double_range".}
type type
PGTuples* = ptr TGTuples PGTuples* = ptr TGTuples
TGTuples* = record TGTuples* {.final.} = object
len*: guint len*: guint
PGRelation* = pointer PGRelation* = pointer
@ -3003,12 +3003,12 @@ type
PGScanner* = ptr TGScanner PGScanner* = ptr TGScanner
PGScannerConfig* = ptr TGScannerConfig PGScannerConfig* = ptr TGScannerConfig
PGTokenValue* = ptr TGTokenValue PGTokenValue* = ptr TGTokenValue
TGTokenValue* = record TGTokenValue* {.final.} = object
v_float*: gdouble v_float*: gdouble
TGScannerMsgFunc* = proc (scanner: PGScanner, message: cstring, TGScannerMsgFunc* = proc (scanner: PGScanner, message: cstring,
error: gboolean){.cdecl.} error: gboolean){.cdecl.}
TGScanner* = record TGScanner* {.final.} = object
user_data*: gpointer user_data*: gpointer
max_parse_errors*: guint max_parse_errors*: guint
parse_errors*: guint parse_errors*: guint
@ -3031,7 +3031,7 @@ type
scope_id*: guint scope_id*: guint
msg_handler*: TGScannerMsgFunc msg_handler*: TGScannerMsgFunc
TGScannerConfig* = record TGScannerConfig* {.final.} = object
cset_skip_characters*: cstring cset_skip_characters*: cstring
cset_identifier_first*: cstring cset_identifier_first*: cstring
cset_identifier_nth*: cstring cset_identifier_nth*: cstring

View file

@ -155,17 +155,17 @@ type
TGtkSignalFunc* = proc (para1: TGtkSignalFuncProc){.cdecl.} TGtkSignalFunc* = proc (para1: TGtkSignalFuncProc){.cdecl.}
PGtkSignalMarshaller* = ptr TGtkSignalMarshaller PGtkSignalMarshaller* = ptr TGtkSignalMarshaller
TGtkSignalMarshaller* = TGSignalCMarshaller TGtkSignalMarshaller* = TGSignalCMarshaller
TGtkArgSignalData* = record TGtkArgSignalData* {.final.} = object
f*: TGtkSignalFunc f*: TGtkSignalFunc
d*: gpointer d*: gpointer
TGtkArg* = record TGtkArg* {.final.} = object
`type`*: TGtkType `type`*: TGtkType
name*: cstring name*: cstring
d*: gdouble # was a union type d*: gdouble # was a union type
PGtkTypeInfo* = ptr TGtkTypeInfo PGtkTypeInfo* = ptr TGtkTypeInfo
TGtkTypeInfo* = record TGtkTypeInfo* {.final.} = object
type_name*: cstring type_name*: cstring
object_size*: guint object_size*: guint
class_size*: guint class_size*: guint
@ -188,7 +188,7 @@ type
TGtkAllocation* = TGdkRectangle TGtkAllocation* = TGdkRectangle
TGtkCallback* = proc (widget: PGtkWidget, data: gpointer){.cdecl.} TGtkCallback* = proc (widget: PGtkWidget, data: gpointer){.cdecl.}
PGtkRequisition* = ptr TGtkRequisition PGtkRequisition* = ptr TGtkRequisition
TGtkRequisition* = record TGtkRequisition* {.final.} = object
width*: gint width*: gint
height*: gint height*: gint
@ -323,7 +323,7 @@ type
gtk_reserved8*: proc (){.cdecl.} gtk_reserved8*: proc (){.cdecl.}
PGtkWidgetAuxInfo* = ptr TGtkWidgetAuxInfo PGtkWidgetAuxInfo* = ptr TGtkWidgetAuxInfo
TGtkWidgetAuxInfo* = record TGtkWidgetAuxInfo* {.final.} = object
x*: gint x*: gint
y*: gint y*: gint
width*: gint width*: gint
@ -331,7 +331,7 @@ type
flag0*: guint16 flag0*: guint16
PGtkWidgetShapeInfo* = ptr TGtkWidgetShapeInfo PGtkWidgetShapeInfo* = ptr TGtkWidgetShapeInfo
TGtkWidgetShapeInfo* = record TGtkWidgetShapeInfo* {.final.} = object
offset_x*: gint16 offset_x*: gint16
offset_y*: gint16 offset_y*: gint16
shape_mask*: PGdkBitmap shape_mask*: PGdkBitmap
@ -370,12 +370,12 @@ type
gtk_reserved4: proc (){.cdecl.} gtk_reserved4: proc (){.cdecl.}
PGtkAccelKey* = ptr TGtkAccelKey PGtkAccelKey* = ptr TGtkAccelKey
TGtkAccelKey* = record TGtkAccelKey* {.final.} = object
accel_key*: guint accel_key*: guint
accel_mods*: TGdkModifierType accel_mods*: TGdkModifierType
flag0*: guint16 flag0*: guint16
TGtkAccelGroupEntry* = record TGtkAccelGroupEntry* {.final.} = object
key*: TGtkAccelKey key*: TGtkAccelKey
closure*: PGClosure closure*: PGClosure
accel_path_quark*: TGQuark accel_path_quark*: TGQuark
@ -595,7 +595,7 @@ type
PGtkBindingSignal* = ptr TGtkBindingSignal PGtkBindingSignal* = ptr TGtkBindingSignal
PGtkBindingArg* = ptr TGtkBindingArg PGtkBindingArg* = ptr TGtkBindingArg
PGtkBindingSet* = ptr TGtkBindingSet PGtkBindingSet* = ptr TGtkBindingSet
TGtkBindingSet* = record TGtkBindingSet* {.final.} = object
set_name*: cstring set_name*: cstring
priority*: gint priority*: gint
widget_path_pspecs*: PGSList widget_path_pspecs*: PGSList
@ -605,7 +605,7 @@ type
current*: PGtkBindingEntry current*: PGtkBindingEntry
flag0*: guint16 flag0*: guint16
TGtkBindingEntry* = record TGtkBindingEntry* {.final.} = object
keyval*: guint keyval*: guint
modifiers*: TGdkModifierType modifiers*: TGdkModifierType
binding_set*: PGtkBindingSet binding_set*: PGtkBindingSet
@ -614,13 +614,13 @@ type
hash_next*: PGtkBindingEntry hash_next*: PGtkBindingEntry
signals*: PGtkBindingSignal signals*: PGtkBindingSignal
TGtkBindingSignal* = record TGtkBindingSignal* {.final.} = object
next*: PGtkBindingSignal next*: PGtkBindingSignal
signal_name*: cstring signal_name*: cstring
n_args*: guint n_args*: guint
args*: PGtkBindingArg args*: PGtkBindingArg
TGtkBindingArg* = record TGtkBindingArg* {.final.} = object
arg_type*: TGtkType arg_type*: TGtkType
d*: gdouble d*: gdouble
@ -634,7 +634,7 @@ type
TGtkBoxClass* = object of TGtkContainerClass TGtkBoxClass* = object of TGtkContainerClass
PGtkBoxChild* = ptr TGtkBoxChild PGtkBoxChild* = ptr TGtkBoxChild
TGtkBoxChild* = record TGtkBoxChild* {.final.} = object
widget*: PGtkWidget widget*: PGtkWidget
padding*: guint16 padding*: guint16
flag0*: guint16 flag0*: guint16
@ -906,12 +906,12 @@ type
TGtkCListCompareFunc* = proc (clist: PGtkCList, ptr1: gconstpointer, TGtkCListCompareFunc* = proc (clist: PGtkCList, ptr1: gconstpointer,
ptr2: gconstpointer): gint{.cdecl.} ptr2: gconstpointer): gint{.cdecl.}
PGtkCListCellInfo* = ptr TGtkCListCellInfo PGtkCListCellInfo* = ptr TGtkCListCellInfo
TGtkCListCellInfo* = record TGtkCListCellInfo* {.final.} = object
row*: gint row*: gint
column*: gint column*: gint
PGtkCListDestInfo* = ptr TGtkCListDestInfo PGtkCListDestInfo* = ptr TGtkCListDestInfo
TGtkCListDestInfo* = record TGtkCListDestInfo* {.final.} = object
cell*: TGtkCListCellInfo cell*: TGtkCListCellInfo
insert_pos*: TGtkCListDragPos insert_pos*: TGtkCListDragPos
@ -1014,7 +1014,7 @@ type
PGPtrArray = pointer PGPtrArray = pointer
PGArray = pointer PGArray = pointer
TGtkCListColumn* = record TGtkCListColumn* {.final.} = object
title*: cstring title*: cstring
area*: TGdkRectangle area*: TGdkRectangle
button*: PGtkWidget button*: PGtkWidget
@ -1025,7 +1025,7 @@ type
justification*: TGtkJustification justification*: TGtkJustification
flag0*: guint16 flag0*: guint16
TGtkCListRow* = record TGtkCListRow* {.final.} = object
cell*: PGtkCell cell*: PGtkCell
state*: TGtkStateType state*: TGtkStateType
foreground*: TGdkColor foreground*: TGdkColor
@ -1036,7 +1036,7 @@ type
flag0*: guint16 flag0*: guint16
PGtkCellText* = ptr TGtkCellText PGtkCellText* = ptr TGtkCellText
TGtkCellText* = record TGtkCellText* {.final.} = object
`type`*: TGtkCellType `type`*: TGtkCellType
vertical*: gint16 vertical*: gint16
horizontal*: gint16 horizontal*: gint16
@ -1044,7 +1044,7 @@ type
text*: cstring text*: cstring
PGtkCellPixmap* = ptr TGtkCellPixmap PGtkCellPixmap* = ptr TGtkCellPixmap
TGtkCellPixmap* = record TGtkCellPixmap* {.final.} = object
`type`*: TGtkCellType `type`*: TGtkCellType
vertical*: gint16 vertical*: gint16
horizontal*: gint16 horizontal*: gint16
@ -1053,7 +1053,7 @@ type
mask*: PGdkBitmap mask*: PGdkBitmap
PGtkCellPixText* = ptr TGtkCellPixText PGtkCellPixText* = ptr TGtkCellPixText
TGtkCellPixText* = record TGtkCellPixText* {.final.} = object
`type`*: TGtkCellType `type`*: TGtkCellType
vertical*: gint16 vertical*: gint16
horizontal*: gint16 horizontal*: gint16
@ -1064,14 +1064,14 @@ type
mask*: PGdkBitmap mask*: PGdkBitmap
PGtkCellWidget* = ptr TGtkCellWidget PGtkCellWidget* = ptr TGtkCellWidget
TGtkCellWidget* = record TGtkCellWidget* {.final.} = object
`type`*: TGtkCellType `type`*: TGtkCellType
vertical*: gint16 vertical*: gint16
horizontal*: gint16 horizontal*: gint16
style*: PGtkStyle style*: PGtkStyle
widget*: PGtkWidget widget*: PGtkWidget
TGtkCell* = record TGtkCell* {.final.} = object
`type`*: TGtkCellType `type`*: TGtkCellType
vertical*: gint16 vertical*: gint16
horizontal*: gint16 horizontal*: gint16
@ -1212,7 +1212,7 @@ type
action: TGtkCTreeExpansionType){.cdecl.} action: TGtkCTreeExpansionType){.cdecl.}
PGtkCTreeRow* = ptr TGtkCTreeRow PGtkCTreeRow* = ptr TGtkCTreeRow
TGtkCTreeRow* = record TGtkCTreeRow* {.final.} = object
row*: TGtkCListRow row*: TGtkCListRow
parent*: PGtkCTreeNode parent*: PGtkCTreeNode
sibling*: PGtkCTreeNode sibling*: PGtkCTreeNode
@ -1224,7 +1224,7 @@ type
level*: guint16 level*: guint16
GtkCTreeRow_flag0*: guint16 GtkCTreeRow_flag0*: guint16
TGtkCTreeNode* = record TGtkCTreeNode* {.final.} = object
list*: TGList list*: TGList
PGtkDrawingArea* = ptr TGtkDrawingArea PGtkDrawingArea* = ptr TGtkDrawingArea
@ -1479,7 +1479,7 @@ type
TGtkFixedClass* = object of TGtkContainerClass TGtkFixedClass* = object of TGtkContainerClass
PGtkFixedChild* = ptr TGtkFixedChild PGtkFixedChild* = ptr TGtkFixedChild
TGtkFixedChild* = record TGtkFixedChild* {.final.} = object
widget*: PGtkWidget widget*: PGtkWidget
x*: gint x*: gint
y*: gint y*: gint
@ -1632,7 +1632,7 @@ type
gtk_reserved363: proc (){.cdecl.} gtk_reserved363: proc (){.cdecl.}
gtk_reserved364: proc (){.cdecl.} gtk_reserved364: proc (){.cdecl.}
TGtkRulerMetric* = record TGtkRulerMetric* {.final.} = object
metric_name*: cstring metric_name*: cstring
abbrev*: cstring abbrev*: cstring
pixels_per_unit*: gdouble pixels_per_unit*: gdouble
@ -1657,7 +1657,7 @@ type
TGtkSettingsClass* = object of TGObjectClass TGtkSettingsClass* = object of TGObjectClass
PGtkSettingsValue* = ptr TGtkSettingsValue PGtkSettingsValue* = ptr TGtkSettingsValue
TGtkSettingsValue* = record TGtkSettingsValue* {.final.} = object
origin*: cstring origin*: cstring
value*: TGValue value*: TGValue
@ -1708,7 +1708,7 @@ type
GTK_RC_TOKEN_IM_MODULE_FILE, GTK_RC_TOKEN_STOCK, GTK_RC_TOKEN_LTR, GTK_RC_TOKEN_IM_MODULE_FILE, GTK_RC_TOKEN_STOCK, GTK_RC_TOKEN_LTR,
GTK_RC_TOKEN_RTL, GTK_RC_TOKEN_LAST GTK_RC_TOKEN_RTL, GTK_RC_TOKEN_LAST
PGtkRcProperty* = ptr TGtkRcProperty PGtkRcProperty* = ptr TGtkRcProperty
TGtkRcProperty* = record TGtkRcProperty* {.final.} = object
type_name*: TGQuark type_name*: TGQuark
property_name*: TGQuark property_name*: TGQuark
origin*: cstring origin*: cstring
@ -1877,7 +1877,7 @@ type
gtk_reserved3812: proc (){.cdecl.} gtk_reserved3812: proc (){.cdecl.}
PGtkBorder* = ptr TGtkBorder PGtkBorder* = ptr TGtkBorder
TGtkBorder* = record TGtkBorder* {.final.} = object
left*: gint left*: gint
right*: gint right*: gint
top*: gint top*: gint
@ -1978,27 +1978,27 @@ type
PGtkIconSet* = pointer PGtkIconSet* = pointer
PGtkImagePixmapData* = ptr TGtkImagePixmapData PGtkImagePixmapData* = ptr TGtkImagePixmapData
TGtkImagePixmapData* = record TGtkImagePixmapData* {.final.} = object
pixmap*: PGdkPixmap pixmap*: PGdkPixmap
PGtkImageImageData* = ptr TGtkImageImageData PGtkImageImageData* = ptr TGtkImageImageData
TGtkImageImageData* = record TGtkImageImageData* {.final.} = object
image*: PGdkImage image*: PGdkImage
PGtkImagePixbufData* = ptr TGtkImagePixbufData PGtkImagePixbufData* = ptr TGtkImagePixbufData
TGtkImagePixbufData* = record TGtkImagePixbufData* {.final.} = object
pixbuf*: PGdkPixbuf pixbuf*: PGdkPixbuf
PGtkImageStockData* = ptr TGtkImageStockData PGtkImageStockData* = ptr TGtkImageStockData
TGtkImageStockData* = record TGtkImageStockData* {.final.} = object
stock_id*: cstring stock_id*: cstring
PGtkImageIconSetData* = ptr TGtkImageIconSetData PGtkImageIconSetData* = ptr TGtkImageIconSetData
TGtkImageIconSetData* = record TGtkImageIconSetData* {.final.} = object
icon_set*: PGtkIconSet icon_set*: PGtkIconSet
PGtkImageAnimationData* = ptr TGtkImageAnimationData PGtkImageAnimationData* = ptr TGtkImageAnimationData
TGtkImageAnimationData* = record TGtkImageAnimationData* {.final.} = object
anim*: PGdkPixbufAnimation anim*: PGdkPixbufAnimation
iter*: PGdkPixbufAnimationIter iter*: PGdkPixbufAnimationIter
frame_timeout*: guint frame_timeout*: guint
@ -2111,7 +2111,7 @@ type
gtk_reserved474: proc (){.cdecl.} gtk_reserved474: proc (){.cdecl.}
PGtkItemFactoryEntry* = ptr TGtkItemFactoryEntry PGtkItemFactoryEntry* = ptr TGtkItemFactoryEntry
TGtkItemFactoryEntry* = record TGtkItemFactoryEntry* {.final.} = object
path*: cstring path*: cstring
accelerator*: cstring accelerator*: cstring
callback*: TGtkItemFactoryCallback callback*: TGtkItemFactoryCallback
@ -2120,7 +2120,7 @@ type
extra_data*: gconstpointer extra_data*: gconstpointer
PGtkItemFactoryItem* = ptr TGtkItemFactoryItem PGtkItemFactoryItem* = ptr TGtkItemFactoryItem
TGtkItemFactoryItem* = record TGtkItemFactoryItem* {.final.} = object
path*: cstring path*: cstring
widgets*: PGSList widgets*: PGSList
@ -2173,7 +2173,7 @@ type
cdecl.} cdecl.}
PGtkTreeModelFlags* = ptr TGtkTreeModelFlags PGtkTreeModelFlags* = ptr TGtkTreeModelFlags
TGtkTreeModelFlags* = int32 TGtkTreeModelFlags* = int32
TGtkTreeIter* = record TGtkTreeIter* {.final.} = object
stamp*: gint stamp*: gint
user_data*: gpointer user_data*: gpointer
user_data2*: gpointer user_data2*: gpointer
@ -2435,12 +2435,12 @@ type
GtkPreview_flag0*: guint16 GtkPreview_flag0*: guint16
PGtkPreviewInfo* = ptr TGtkPreviewInfo PGtkPreviewInfo* = ptr TGtkPreviewInfo
TGtkPreviewInfo* = record TGtkPreviewInfo* {.final.} = object
lookup*: Pguchar lookup*: Pguchar
gamma*: gdouble gamma*: gdouble
PGtkDitherInfo* = ptr TGtkDitherInfo PGtkDitherInfo* = ptr TGtkDitherInfo
TGtkDitherInfo* = record TGtkDitherInfo* {.final.} = object
c*: array[0..3, guchar] c*: array[0..3, guchar]
PGtkPreviewClass* = ptr TGtkPreviewClass PGtkPreviewClass* = ptr TGtkPreviewClass
@ -2533,7 +2533,7 @@ type
gtk_reserved603: proc (){.cdecl.} gtk_reserved603: proc (){.cdecl.}
gtk_reserved604: proc (){.cdecl.} gtk_reserved604: proc (){.cdecl.}
TGtkSelectionData* = record TGtkSelectionData* {.final.} = object
selection*: TGdkAtom selection*: TGdkAtom
target*: TGdkAtom target*: TGdkAtom
thetype*: TGdkAtom thetype*: TGdkAtom
@ -2543,18 +2543,18 @@ type
display*: PGdkDisplay display*: PGdkDisplay
PGtkTargetEntry* = ptr TGtkTargetEntry PGtkTargetEntry* = ptr TGtkTargetEntry
TGtkTargetEntry* = record TGtkTargetEntry* {.final.} = object
target*: cstring target*: cstring
flags*: guint flags*: guint
info*: guint info*: guint
PGtkTargetList* = ptr TGtkTargetList PGtkTargetList* = ptr TGtkTargetList
TGtkTargetList* = record TGtkTargetList* {.final.} = object
list*: PGList list*: PGList
ref_count*: guint ref_count*: guint
PGtkTargetPair* = ptr TGtkTargetPair PGtkTargetPair* = ptr TGtkTargetPair
TGtkTargetPair* = record TGtkTargetPair* {.final.} = object
target*: TGdkAtom target*: TGdkAtom
flags*: guint flags*: guint
info*: guint info*: guint
@ -2635,7 +2635,7 @@ type
gtk_reserved634: proc (){.cdecl.} gtk_reserved634: proc (){.cdecl.}
PGtkStockItem* = ptr TGtkStockItem PGtkStockItem* = ptr TGtkStockItem
TGtkStockItem* = record TGtkStockItem* {.final.} = object
stock_id*: cstring stock_id*: cstring
label*: cstring label*: cstring
modifier*: TGdkModifierType modifier*: TGdkModifierType
@ -2681,7 +2681,7 @@ type
TGtkTableClass* = object of TGtkContainerClass TGtkTableClass* = object of TGtkContainerClass
PGtkTableChild* = ptr TGtkTableChild PGtkTableChild* = ptr TGtkTableChild
TGtkTableChild* = record TGtkTableChild* {.final.} = object
widget*: PGtkWidget widget*: PGtkWidget
left_attach*: guint16 left_attach*: guint16
right_attach*: guint16 right_attach*: guint16
@ -2691,7 +2691,7 @@ type
ypadding*: guint16 ypadding*: guint16
GtkTableChild_flag0*: guint16 GtkTableChild_flag0*: guint16
TGtkTableRowCol* = record TGtkTableRowCol* {.final.} = object
requisition*: guint16 requisition*: guint16
allocation*: guint16 allocation*: guint16
spacing*: guint16 spacing*: guint16
@ -2710,7 +2710,7 @@ type
PGtkTextFont* = pointer PGtkTextFont* = pointer
PGtkPropertyMark* = ptr TGtkPropertyMark PGtkPropertyMark* = ptr TGtkPropertyMark
TGtkPropertyMark* = record TGtkPropertyMark* {.final.} = object
`property`*: PGList `property`*: PGList
offset*: guint offset*: guint
index*: guint index*: guint
@ -2764,7 +2764,7 @@ type
PGtkTextSearchFlags* = ptr TGtkTextSearchFlags PGtkTextSearchFlags* = ptr TGtkTextSearchFlags
TGtkTextSearchFlags* = int32 TGtkTextSearchFlags* = int32
PGtkTextIter* = ptr TGtkTextIter PGtkTextIter* = ptr TGtkTextIter
TGtkTextIter* = record TGtkTextIter* {.final.} = object
dummy1*: gpointer dummy1*: gpointer
dummy2*: gpointer dummy2*: gpointer
dummy3*: gint dummy3*: gint
@ -2802,7 +2802,7 @@ type
gtk_reserved664: proc (){.cdecl.} gtk_reserved664: proc (){.cdecl.}
PGtkTextAppearance* = ptr TGtkTextAppearance PGtkTextAppearance* = ptr TGtkTextAppearance
TGtkTextAppearance* = record TGtkTextAppearance* {.final.} = object
bg_color*: TGdkColor bg_color*: TGdkColor
fg_color*: TGdkColor fg_color*: TGdkColor
bg_stipple*: PGdkBitmap bg_stipple*: PGdkBitmap
@ -2811,7 +2811,7 @@ type
padding1*: gpointer padding1*: gpointer
flag0*: guint16 flag0*: guint16
TGtkTextAttributes* = record TGtkTextAttributes* {.final.} = object
refcount*: guint refcount*: guint
appearance*: TGtkTextAppearance appearance*: TGtkTextAppearance
justification*: TGtkJustification justification*: TGtkJustification
@ -2860,7 +2860,7 @@ type
gtk_reserved4: proc (){.cdecl.} gtk_reserved4: proc (){.cdecl.}
PGtkTextMarkBody* = ptr TGtkTextMarkBody PGtkTextMarkBody* = ptr TGtkTextMarkBody
TGtkTextMarkBody* = record TGtkTextMarkBody* {.final.} = object
obj*: PGtkTextMark obj*: PGtkTextMark
name*: cstring name*: cstring
tree*: PGtkTextBTree tree*: PGtkTextBTree
@ -2879,11 +2879,11 @@ type
gtk_reserved4: proc (){.cdecl.} gtk_reserved4: proc (){.cdecl.}
PGtkTextPixbuf* = ptr TGtkTextPixbuf PGtkTextPixbuf* = ptr TGtkTextPixbuf
TGtkTextPixbuf* = record TGtkTextPixbuf* {.final.} = object
pixbuf*: PGdkPixbuf pixbuf*: PGdkPixbuf
PGtkTextChildBody* = ptr TGtkTextChildBody PGtkTextChildBody* = ptr TGtkTextChildBody
TGtkTextChildBody* = record TGtkTextChildBody* {.final.} = object
obj*: PGtkTextChildAnchor obj*: PGtkTextChildAnchor
widgets*: PGSList widgets*: PGSList
tree*: PGtkTextBTree tree*: PGtkTextBTree
@ -2892,17 +2892,17 @@ type
PGtkTextLineSegment* = ptr TGtkTextLineSegment PGtkTextLineSegment* = ptr TGtkTextLineSegment
PGtkTextLineSegmentClass* = ptr TGtkTextLineSegmentClass PGtkTextLineSegmentClass* = ptr TGtkTextLineSegmentClass
PGtkTextTagInfo* = ptr TGtkTextTagInfo PGtkTextTagInfo* = ptr TGtkTextTagInfo
TGtkTextTagInfo* = record TGtkTextTagInfo* {.final.} = object
tag*: PGtkTextTag tag*: PGtkTextTag
tag_root*: PGtkTextBTreeNode tag_root*: PGtkTextBTreeNode
toggle_count*: gint toggle_count*: gint
PGtkTextToggleBody* = ptr TGtkTextToggleBody PGtkTextToggleBody* = ptr TGtkTextToggleBody
TGtkTextToggleBody* = record TGtkTextToggleBody* {.final.} = object
info*: PGtkTextTagInfo info*: PGtkTextTagInfo
inNodeCounts*: gboolean inNodeCounts*: gboolean
TGtkTextLineSegment* = record TGtkTextLineSegment* {.final.} = object
`type`*: PGtkTextLineSegmentClass `type`*: PGtkTextLineSegmentClass
next*: PGtkTextLineSegment next*: PGtkTextLineSegment
char_count*: int32 char_count*: int32
@ -2919,7 +2919,7 @@ type
line: PGtkTextLine){.cdecl.} line: PGtkTextLine){.cdecl.}
TGtkTextSegCheckFunc* = proc (seg: PGtkTextLineSegment, line: PGtkTextLine){. TGtkTextSegCheckFunc* = proc (seg: PGtkTextLineSegment, line: PGtkTextLine){.
cdecl.} cdecl.}
TGtkTextLineSegmentClass* = record TGtkTextLineSegmentClass* {.final.} = object
name*: cstring name*: cstring
leftGravity*: gboolean leftGravity*: gboolean
splitFunc*: TGtkTextSegSplitFunc splitFunc*: TGtkTextSegSplitFunc
@ -2929,13 +2929,13 @@ type
checkFunc*: TGtkTextSegCheckFunc checkFunc*: TGtkTextSegCheckFunc
PGtkTextLineData* = ptr TGtkTextLineData PGtkTextLineData* = ptr TGtkTextLineData
TGtkTextLineData* = record TGtkTextLineData* {.final.} = object
view_id*: gpointer view_id*: gpointer
next*: PGtkTextLineData next*: PGtkTextLineData
height*: gint height*: gint
flag0*: int32 flag0*: int32
TGtkTextLine* = record TGtkTextLine* {.final.} = object
parent*: PGtkTextBTreeNode parent*: PGtkTextBTreeNode
next*: PGtkTextLine next*: PGtkTextLine
segments*: PGtkTextLineSegment segments*: PGtkTextLineSegment
@ -3020,18 +3020,18 @@ type
gtk_reserved4: proc (){.cdecl.} gtk_reserved4: proc (){.cdecl.}
PGtkTextAttrAppearance* = ptr TGtkTextAttrAppearance PGtkTextAttrAppearance* = ptr TGtkTextAttrAppearance
TGtkTextAttrAppearance* = record TGtkTextAttrAppearance* {.final.} = object
attr*: TPangoAttribute attr*: TPangoAttribute
appearance*: TGtkTextAppearance appearance*: TGtkTextAppearance
PGtkTextCursorDisplay* = ptr TGtkTextCursorDisplay PGtkTextCursorDisplay* = ptr TGtkTextCursorDisplay
TGtkTextCursorDisplay* = record TGtkTextCursorDisplay* {.final.} = object
x*: gint x*: gint
y*: gint y*: gint
height*: gint height*: gint
flag0*: guint16 flag0*: guint16
TGtkTextLineDisplay* = record TGtkTextLineDisplay* {.final.} = object
layout*: PPangoLayout layout*: PPangoLayout
cursors*: PGSList cursors*: PGSList
shaped_objects*: PGSList shaped_objects*: PGSList
@ -3152,7 +3152,7 @@ type
PGtkTooltips* = ptr TGtkTooltips PGtkTooltips* = ptr TGtkTooltips
PGtkTooltipsData* = ptr TGtkTooltipsData PGtkTooltipsData* = ptr TGtkTooltipsData
TGtkTooltipsData* = record TGtkTooltipsData* {.final.} = object
tooltips*: PGtkTooltips tooltips*: PGtkTooltips
widget*: PGtkWidget widget*: PGtkWidget
tip_text*: cstring tip_text*: cstring
@ -3184,7 +3184,7 @@ type
TGtkToolbarSpaceStyle* = enum TGtkToolbarSpaceStyle* = enum
GTK_TOOLBAR_SPACE_EMPTY, GTK_TOOLBAR_SPACE_LINE GTK_TOOLBAR_SPACE_EMPTY, GTK_TOOLBAR_SPACE_LINE
PGtkToolbarChild* = ptr TGtkToolbarChild PGtkToolbarChild* = ptr TGtkToolbarChild
TGtkToolbarChild* = record TGtkToolbarChild* {.final.} = object
`type`*: TGtkToolbarChildType `type`*: TGtkToolbarChildType
widget*: PGtkWidget widget*: PGtkWidget
icon*: PGtkWidget icon*: PGtkWidget
@ -3365,13 +3365,13 @@ type
PGtkRBNode* = ptr TGtkRBNode PGtkRBNode* = ptr TGtkRBNode
TGtkRBTreeTraverseFunc* = proc (tree: PGtkRBTree, node: PGtkRBNode, TGtkRBTreeTraverseFunc* = proc (tree: PGtkRBTree, node: PGtkRBNode,
data: gpointer){.cdecl.} data: gpointer){.cdecl.}
TGtkRBTree* = record TGtkRBTree* {.final.} = object
root*: PGtkRBNode root*: PGtkRBNode
`nil`*: PGtkRBNode `nil`*: PGtkRBNode
parent_tree*: PGtkRBTree parent_tree*: PGtkRBTree
parent_node*: PGtkRBNode parent_node*: PGtkRBNode
TGtkRBNode* = record TGtkRBNode* {.final.} = object
flag0*: guint16 flag0*: guint16
left*: PGtkRBNode left*: PGtkRBNode
right*: PGtkRBNode right*: PGtkRBNode
@ -3386,14 +3386,14 @@ type
TGtkTreeViewSearchDialogPositionFunc* = proc (tree_view: PGtkTreeView, TGtkTreeViewSearchDialogPositionFunc* = proc (tree_view: PGtkTreeView,
search_dialog: PGtkWidget){.cdecl.} search_dialog: PGtkWidget){.cdecl.}
PGtkTreeViewColumnReorder* = ptr TGtkTreeViewColumnReorder PGtkTreeViewColumnReorder* = ptr TGtkTreeViewColumnReorder
TGtkTreeViewColumnReorder* = record TGtkTreeViewColumnReorder* {.final.} = object
left_align*: gint left_align*: gint
right_align*: gint right_align*: gint
left_column*: PGtkTreeViewColumn left_column*: PGtkTreeViewColumn
right_column*: PGtkTreeViewColumn right_column*: PGtkTreeViewColumn
PGtkTreeViewPrivate* = ptr TGtkTreeViewPrivate PGtkTreeViewPrivate* = ptr TGtkTreeViewPrivate
TGtkTreeViewPrivate* = record TGtkTreeViewPrivate* {.final.} = object
model*: PGtkTreeModel model*: PGtkTreeModel
flags*: guint flags*: guint
tree*: PGtkRBTree tree*: PGtkRBTree
@ -11304,96 +11304,127 @@ proc GTK_FUNDAMENTAL_TYPE*(thetype: GType): GType =
result = G_TYPE_FUNDAMENTAL(thetype) result = G_TYPE_FUNDAMENTAL(thetype)
proc GTK_VALUE_CHAR*(a: TGtkArg): gchar = proc GTK_VALUE_CHAR*(a: TGtkArg): gchar =
var a = a
Result = cast[ptr gchar](addr(a.d))^ Result = cast[ptr gchar](addr(a.d))^
proc GTK_VALUE_UCHAR*(a: TGtkArg): guchar = proc GTK_VALUE_UCHAR*(a: TGtkArg): guchar =
var a = a
Result = cast[ptr guchar](addr(a.d))^ Result = cast[ptr guchar](addr(a.d))^
proc GTK_VALUE_BOOL*(a: TGtkArg): gboolean = proc GTK_VALUE_BOOL*(a: TGtkArg): gboolean =
var a = a
Result = cast[ptr gboolean](addr(a.d))^ Result = cast[ptr gboolean](addr(a.d))^
proc GTK_VALUE_INT*(a: TGtkArg): gint = proc GTK_VALUE_INT*(a: TGtkArg): gint =
var a = a
Result = cast[ptr gint](addr(a.d))^ Result = cast[ptr gint](addr(a.d))^
proc GTK_VALUE_UINT*(a: TGtkArg): guint = proc GTK_VALUE_UINT*(a: TGtkArg): guint =
var a = a
Result = cast[ptr guint](addr(a.d))^ Result = cast[ptr guint](addr(a.d))^
proc GTK_VALUE_LONG*(a: TGtkArg): glong = proc GTK_VALUE_LONG*(a: TGtkArg): glong =
var a = a
Result = cast[ptr glong](addr(a.d))^ Result = cast[ptr glong](addr(a.d))^
proc GTK_VALUE_ULONG*(a: TGtkArg): gulong = proc GTK_VALUE_ULONG*(a: TGtkArg): gulong =
var a = a
Result = cast[ptr gulong](addr(a.d))^ Result = cast[ptr gulong](addr(a.d))^
proc GTK_VALUE_FLOAT*(a: TGtkArg): gfloat = proc GTK_VALUE_FLOAT*(a: TGtkArg): gfloat =
var a = a
Result = cast[ptr gfloat](addr(a.d))^ Result = cast[ptr gfloat](addr(a.d))^
proc GTK_VALUE_DOUBLE*(a: TGtkArg): gdouble = proc GTK_VALUE_DOUBLE*(a: TGtkArg): gdouble =
var a = a
Result = cast[ptr gdouble](addr(a.d))^ Result = cast[ptr gdouble](addr(a.d))^
proc GTK_VALUE_STRING*(a: TGtkArg): cstring = proc GTK_VALUE_STRING*(a: TGtkArg): cstring =
var a = a
Result = cast[ptr cstring](addr(a.d))^ Result = cast[ptr cstring](addr(a.d))^
proc GTK_VALUE_ENUM*(a: TGtkArg): gint = proc GTK_VALUE_ENUM*(a: TGtkArg): gint =
var a = a
Result = cast[ptr gint](addr(a.d))^ Result = cast[ptr gint](addr(a.d))^
proc GTK_VALUE_FLAGS*(a: TGtkArg): guint = proc GTK_VALUE_FLAGS*(a: TGtkArg): guint =
var a = a
Result = cast[ptr guint](addr(a.d))^ Result = cast[ptr guint](addr(a.d))^
proc GTK_VALUE_BOXED*(a: TGtkArg): gpointer = proc GTK_VALUE_BOXED*(a: TGtkArg): gpointer =
var a = a
Result = cast[ptr gpointer](addr(a.d))^ Result = cast[ptr gpointer](addr(a.d))^
proc GTK_VALUE_OBJECT*(a: TGtkArg): PGtkObject = proc GTK_VALUE_OBJECT*(a: TGtkArg): PGtkObject =
var a = a
Result = cast[ptr PGtkObject](addr(a.d))^ Result = cast[ptr PGtkObject](addr(a.d))^
proc GTK_VALUE_POINTER*(a: TGtkArg): GPointer = proc GTK_VALUE_POINTER*(a: TGtkArg): GPointer =
var a = a
Result = cast[ptr gpointer](addr(a.d))^ Result = cast[ptr gpointer](addr(a.d))^
proc GTK_VALUE_SIGNAL*(a: TGtkArg): TGtkArgSignalData = proc GTK_VALUE_SIGNAL*(a: TGtkArg): TGtkArgSignalData =
var a = a
Result = cast[ptr TGtkArgSignalData](addr(a.d))^ Result = cast[ptr TGtkArgSignalData](addr(a.d))^
proc GTK_RETLOC_CHAR*(a: TGtkArg): cstring = proc GTK_RETLOC_CHAR*(a: TGtkArg): cstring =
var a = a
Result = cast[ptr cstring](addr(a.d))^ Result = cast[ptr cstring](addr(a.d))^
proc GTK_RETLOC_UCHAR*(a: TGtkArg): Pguchar = proc GTK_RETLOC_UCHAR*(a: TGtkArg): Pguchar =
var a = a
Result = cast[ptr pguchar](addr(a.d))^ Result = cast[ptr pguchar](addr(a.d))^
proc GTK_RETLOC_BOOL*(a: TGtkArg): Pgboolean = proc GTK_RETLOC_BOOL*(a: TGtkArg): Pgboolean =
var a = a
Result = cast[ptr pgboolean](addr(a.d))^ Result = cast[ptr pgboolean](addr(a.d))^
proc GTK_RETLOC_INT*(a: TGtkArg): Pgint = proc GTK_RETLOC_INT*(a: TGtkArg): Pgint =
var a = a
Result = cast[ptr pgint](addr(a.d))^ Result = cast[ptr pgint](addr(a.d))^
proc GTK_RETLOC_UINT*(a: TGtkArg): Pguint = proc GTK_RETLOC_UINT*(a: TGtkArg): Pguint =
var a = a
Result = cast[ptr pguint](addr(a.d))^ Result = cast[ptr pguint](addr(a.d))^
proc GTK_RETLOC_LONG*(a: TGtkArg): Pglong = proc GTK_RETLOC_LONG*(a: TGtkArg): Pglong =
var a = a
Result = cast[ptr pglong](addr(a.d))^ Result = cast[ptr pglong](addr(a.d))^
proc GTK_RETLOC_ULONG*(a: TGtkArg): Pgulong = proc GTK_RETLOC_ULONG*(a: TGtkArg): Pgulong =
var a = a
Result = cast[ptr pgulong](addr(a.d))^ Result = cast[ptr pgulong](addr(a.d))^
proc GTK_RETLOC_FLOAT*(a: TGtkArg): Pgfloat = proc GTK_RETLOC_FLOAT*(a: TGtkArg): Pgfloat =
var a = a
Result = cast[ptr pgfloat](addr(a.d))^ Result = cast[ptr pgfloat](addr(a.d))^
proc GTK_RETLOC_DOUBLE*(a: TGtkArg): Pgdouble = proc GTK_RETLOC_DOUBLE*(a: TGtkArg): Pgdouble =
var a = a
Result = cast[ptr pgdouble](addr(a.d))^ Result = cast[ptr pgdouble](addr(a.d))^
proc GTK_RETLOC_STRING*(a: TGtkArg): Ppgchar = proc GTK_RETLOC_STRING*(a: TGtkArg): Ppgchar =
var a = a
Result = cast[ptr Ppgchar](addr(a.d))^ Result = cast[ptr Ppgchar](addr(a.d))^
proc GTK_RETLOC_ENUM*(a: TGtkArg): Pgint = proc GTK_RETLOC_ENUM*(a: TGtkArg): Pgint =
var a = a
Result = cast[ptr Pgint](addr(a.d))^ Result = cast[ptr Pgint](addr(a.d))^
proc GTK_RETLOC_FLAGS*(a: TGtkArg): Pguint = proc GTK_RETLOC_FLAGS*(a: TGtkArg): Pguint =
var a = a
Result = cast[ptr pguint](addr(a.d))^ Result = cast[ptr pguint](addr(a.d))^
proc GTK_RETLOC_BOXED*(a: TGtkArg): Pgpointer = proc GTK_RETLOC_BOXED*(a: TGtkArg): Pgpointer =
var a = a
Result = cast[ptr pgpointer](addr(a.d))^ Result = cast[ptr pgpointer](addr(a.d))^
proc GTK_RETLOC_OBJECT*(a: TGtkArg): PPGtkObject = proc GTK_RETLOC_OBJECT*(a: TGtkArg): PPGtkObject =
var a = a
Result = cast[ptr ppgtkobject](addr(a.d))^ Result = cast[ptr ppgtkobject](addr(a.d))^
proc GTK_RETLOC_POINTER*(a: TGtkArg): Pgpointer = proc GTK_RETLOC_POINTER*(a: TGtkArg): Pgpointer =
var a = a
Result = cast[ptr pgpointer](addr(a.d))^ Result = cast[ptr pgpointer](addr(a.d))^
proc GTK_TYPE_WIDGET*(): GType = proc GTK_TYPE_WIDGET*(): GType =
@ -15108,7 +15139,7 @@ proc gtk_signal_handler_pending_by_func*(anObject: PGtkObject, signal_id: guint,
G_SIGNAL_MATCH_DATA) G_SIGNAL_MATCH_DATA)
if not may_be_blocked: if not may_be_blocked:
t = t or cast[int](G_SIGNAL_MATCH_UNBLOCKED) t = t or cast[int](G_SIGNAL_MATCH_UNBLOCKED)
Result = g_signal_handler_find(anObject, t, signal_id, 0, nil, addr(func_), Result = g_signal_handler_find(anObject, t, signal_id, 0, nil, func_,
data) != 0 data) != 0
proc GTK_TYPE_SIZE_GROUP*(): GType = proc GTK_TYPE_SIZE_GROUP*(): GType =
@ -17045,7 +17076,7 @@ type
GTK_FILE_FILTER_FILENAME = 1 shl 0, GTK_FILE_FILTER_URI = 1 shl 1, GTK_FILE_FILTER_FILENAME = 1 shl 0, GTK_FILE_FILTER_URI = 1 shl 1,
GTK_FILE_FILTER_DISPLAY_NAME = 1 shl 2, GTK_FILE_FILTER_MIME_TYPE = 1 shl 3 GTK_FILE_FILTER_DISPLAY_NAME = 1 shl 2, GTK_FILE_FILTER_MIME_TYPE = 1 shl 3
PGtkFileFilterInfo* = ref TGtkFileFilterInfo PGtkFileFilterInfo* = ref TGtkFileFilterInfo
TGtkFileFilterInfo* = record TGtkFileFilterInfo* {.final.} = object
contains*: TGtkFileFilterFlags contains*: TGtkFileFilterFlags
filename*: cstring filename*: cstring
uri*: cstring uri*: cstring

View file

@ -68,12 +68,12 @@ type
exc: PDomException): PDomString{.cdecl.} exc: PDomException): PDomString{.cdecl.}
PDomDocument* = ptr TDomDocument PDomDocument* = ptr TDomDocument
TDomDocument* = record TDomDocument* {.final.} = object
parent*: PDomNode parent*: PDomNode
iterators*: PGSList iterators*: PGSList
PDomDocumentClass* = ptr TDomDocumentClass PDomDocumentClass* = ptr TDomDocumentClass
TDomDocumentClass* = record TDomDocumentClass* {.final.} = object
parent_class*: PDomNodeClass parent_class*: PDomNodeClass
PHtmlFocusIterator* = ptr THtmlFocusIterator PHtmlFocusIterator* = ptr THtmlFocusIterator

View file

@ -50,7 +50,7 @@ type
PPangoGlyph* = ptr TPangoGlyph PPangoGlyph* = ptr TPangoGlyph
TPangoGlyph* = guint32 TPangoGlyph* = guint32
PPangoRectangle* = ptr TPangoRectangle PPangoRectangle* = ptr TPangoRectangle
TPangoRectangle* = record TPangoRectangle* {.final.} = object
x*: int32 x*: int32
y*: int32 y*: int32
width*: int32 width*: int32
@ -61,7 +61,7 @@ type
PANGO_DIRECTION_LTR, PANGO_DIRECTION_RTL, PANGO_DIRECTION_TTB_LTR, PANGO_DIRECTION_LTR, PANGO_DIRECTION_RTL, PANGO_DIRECTION_TTB_LTR,
PANGO_DIRECTION_TTB_RTL PANGO_DIRECTION_TTB_RTL
PPangoColor* = ptr TPangoColor PPangoColor* = ptr TPangoColor
TPangoColor* = record TPangoColor* {.final.} = object
red*: guint16 red*: guint16
green*: guint16 green*: guint16
blue*: guint16 blue*: guint16
@ -72,12 +72,12 @@ type
TPangoUnderline* = int32 TPangoUnderline* = int32
PPangoAttribute* = ptr TPangoAttribute PPangoAttribute* = ptr TPangoAttribute
PPangoAttrClass* = ptr TPangoAttrClass PPangoAttrClass* = ptr TPangoAttrClass
TPangoAttribute* = record TPangoAttribute* {.final.} = object
klass*: PPangoAttrClass klass*: PPangoAttrClass
start_index*: int start_index*: int
end_index*: int end_index*: int
TPangoAttrClass* = record TPangoAttrClass* {.final.} = object
`type`*: TPangoAttrType `type`*: TPangoAttrType
copy*: proc (attr: PPangoAttribute): PPangoAttribute{.cdecl.} copy*: proc (attr: PPangoAttribute): PPangoAttribute{.cdecl.}
destroy*: proc (attr: PPangoAttribute){.cdecl.} destroy*: proc (attr: PPangoAttribute){.cdecl.}
@ -85,43 +85,43 @@ type
cdecl.} cdecl.}
PPangoAttrString* = ptr TPangoAttrString PPangoAttrString* = ptr TPangoAttrString
TPangoAttrString* = record TPangoAttrString* {.final.} = object
attr*: TPangoAttribute attr*: TPangoAttribute
value*: cstring value*: cstring
PPangoAttrLanguage* = ptr TPangoAttrLanguage PPangoAttrLanguage* = ptr TPangoAttrLanguage
TPangoAttrLanguage* = record TPangoAttrLanguage* {.final.} = object
attr*: TPangoAttribute attr*: TPangoAttribute
value*: PPangoLanguage value*: PPangoLanguage
PPangoAttrInt* = ptr TPangoAttrInt PPangoAttrInt* = ptr TPangoAttrInt
TPangoAttrInt* = record TPangoAttrInt* {.final.} = object
attr*: TPangoAttribute attr*: TPangoAttribute
value*: int32 value*: int32
PPangoAttrFloat* = ptr TPangoAttrFloat PPangoAttrFloat* = ptr TPangoAttrFloat
TPangoAttrFloat* = record TPangoAttrFloat* {.final.} = object
attr*: TPangoAttribute attr*: TPangoAttribute
value*: gdouble value*: gdouble
PPangoAttrColor* = ptr TPangoAttrColor PPangoAttrColor* = ptr TPangoAttrColor
TPangoAttrColor* = record TPangoAttrColor* {.final.} = object
attr*: TPangoAttribute attr*: TPangoAttribute
color*: TPangoColor color*: TPangoColor
PPangoAttrShape* = ptr TPangoAttrShape PPangoAttrShape* = ptr TPangoAttrShape
TPangoAttrShape* = record TPangoAttrShape* {.final.} = object
attr*: TPangoAttribute attr*: TPangoAttribute
ink_rect*: TPangoRectangle ink_rect*: TPangoRectangle
logical_rect*: TPangoRectangle logical_rect*: TPangoRectangle
PPangoAttrFontDesc* = ptr TPangoAttrFontDesc PPangoAttrFontDesc* = ptr TPangoAttrFontDesc
TPangoAttrFontDesc* = record TPangoAttrFontDesc* {.final.} = object
attr*: TPangoAttribute attr*: TPangoAttribute
desc*: PPangoFontDescription desc*: PPangoFontDescription
PPangoLogAttr* = ptr TPangoLogAttr PPangoLogAttr* = ptr TPangoLogAttr
TPangoLogAttr* = record TPangoLogAttr* {.final.} = object
flag0*: guint16 flag0*: guint16
PPangoCoverageLevel* = ptr TPangoCoverageLevel PPangoCoverageLevel* = ptr TPangoCoverageLevel
@ -129,25 +129,25 @@ type
PANGO_COVERAGE_NONE, PANGO_COVERAGE_FALLBACK, PANGO_COVERAGE_APPROXIMATE, PANGO_COVERAGE_NONE, PANGO_COVERAGE_FALLBACK, PANGO_COVERAGE_APPROXIMATE,
PANGO_COVERAGE_EXACT PANGO_COVERAGE_EXACT
PPangoBlockInfo* = ptr TPangoBlockInfo PPangoBlockInfo* = ptr TPangoBlockInfo
TPangoBlockInfo* = record TPangoBlockInfo* {.final.} = object
data*: Pguchar data*: Pguchar
level*: TPangoCoverageLevel level*: TPangoCoverageLevel
PPangoCoverage* = ptr TPangoCoverage PPangoCoverage* = ptr TPangoCoverage
TPangoCoverage* = record TPangoCoverage* {.final.} = object
ref_count*: int ref_count*: int
n_blocks*: int32 n_blocks*: int32
data_size*: int32 data_size*: int32
blocks*: PPangoBlockInfo blocks*: PPangoBlockInfo
PPangoEngineRange* = ptr TPangoEngineRange PPangoEngineRange* = ptr TPangoEngineRange
TPangoEngineRange* = record TPangoEngineRange* {.final.} = object
start*: int32 start*: int32
theEnd*: int32 theEnd*: int32
langs*: cstring langs*: cstring
PPangoEngineInfo* = ptr TPangoEngineInfo PPangoEngineInfo* = ptr TPangoEngineInfo
TPangoEngineInfo* = record TPangoEngineInfo* {.final.} = object
id*: cstring id*: cstring
engine_type*: cstring engine_type*: cstring
render_type*: cstring render_type*: cstring
@ -155,7 +155,7 @@ type
n_ranges*: gint n_ranges*: gint
PPangoEngine* = ptr TPangoEngine PPangoEngine* = ptr TPangoEngine
TPangoEngine* = record TPangoEngine* {.final.} = object
id*: cstring id*: cstring
`type`*: cstring `type`*: cstring
length*: gint length*: gint
@ -165,7 +165,7 @@ type
attrs: PPangoLogAttr, attrs_len: int32){. attrs: PPangoLogAttr, attrs_len: int32){.
cdecl.} cdecl.}
PPangoEngineLang* = ptr TPangoEngineLang PPangoEngineLang* = ptr TPangoEngineLang
TPangoEngineLang* = record TPangoEngineLang* {.final.} = object
engine*: TPangoEngine engine*: TPangoEngine
script_break*: TPangoEngineLangScriptBreak script_break*: TPangoEngineLangScriptBreak
@ -176,7 +176,7 @@ type
language: PPangoLanguage): PPangoCoverage{. language: PPangoLanguage): PPangoCoverage{.
cdecl.} cdecl.}
PPangoEngineShape* = ptr TPangoEngineShape PPangoEngineShape* = ptr TPangoEngineShape
TPangoEngineShape* = record TPangoEngineShape* {.final.} = object
engine*: TPangoEngine engine*: TPangoEngine
script_shape*: TPangoEngineShapeScript script_shape*: TPangoEngineShapeScript
get_coverage*: TPangoEngineShapeGetCoverage get_coverage*: TPangoEngineShapeGetCoverage
@ -194,28 +194,28 @@ type
PPangoGlyphUnit* = ptr TPangoGlyphUnit PPangoGlyphUnit* = ptr TPangoGlyphUnit
TPangoGlyphUnit* = gint32 TPangoGlyphUnit* = gint32
PPangoGlyphGeometry* = ptr TPangoGlyphGeometry PPangoGlyphGeometry* = ptr TPangoGlyphGeometry
TPangoGlyphGeometry* = record TPangoGlyphGeometry* {.final.} = object
width*: TPangoGlyphUnit width*: TPangoGlyphUnit
x_offset*: TPangoGlyphUnit x_offset*: TPangoGlyphUnit
y_offset*: TPangoGlyphUnit y_offset*: TPangoGlyphUnit
PPangoGlyphVisAttr* = ptr TPangoGlyphVisAttr PPangoGlyphVisAttr* = ptr TPangoGlyphVisAttr
TPangoGlyphVisAttr* = record TPangoGlyphVisAttr* {.final.} = object
flag0*: int16 flag0*: int16
PPangoGlyphInfo* = ptr TPangoGlyphInfo PPangoGlyphInfo* = ptr TPangoGlyphInfo
TPangoGlyphInfo* = record TPangoGlyphInfo* {.final.} = object
glyph*: TPangoGlyph glyph*: TPangoGlyph
geometry*: TPangoGlyphGeometry geometry*: TPangoGlyphGeometry
attr*: TPangoGlyphVisAttr attr*: TPangoGlyphVisAttr
TPangoGlyphString* = record TPangoGlyphString* {.final.} = object
num_glyphs*: gint num_glyphs*: gint
glyphs*: PPangoGlyphInfo glyphs*: PPangoGlyphInfo
log_clusters*: Pgint log_clusters*: Pgint
space*: gint space*: gint
TPangoAnalysis* = record TPangoAnalysis* {.final.} = object
shape_engine*: PPangoEngineShape shape_engine*: PPangoEngineShape
lang_engine*: PPangoEngineLang lang_engine*: PPangoEngineLang
font*: PPangoFont font*: PPangoFont
@ -223,7 +223,7 @@ type
language*: PPangoLanguage language*: PPangoLanguage
extra_attrs*: PGSList extra_attrs*: PGSList
TPangoItem* = record TPangoItem* {.final.} = object
offset*: gint offset*: gint
length*: gint length*: gint
num_chars*: gint num_chars*: gint
@ -236,14 +236,14 @@ type
TPangoWrapMode* = enum TPangoWrapMode* = enum
PANGO_WRAP_WORD, PANGO_WRAP_CHAR PANGO_WRAP_WORD, PANGO_WRAP_CHAR
PPangoLayoutLine* = ptr TPangoLayoutLine PPangoLayoutLine* = ptr TPangoLayoutLine
TPangoLayoutLine* = record TPangoLayoutLine* {.final.} = object
layout*: PPangoLayout layout*: PPangoLayout
start_index*: gint start_index*: gint
length*: gint length*: gint
runs*: PGSList runs*: PGSList
PPangoLayoutRun* = ptr TPangoLayoutRun PPangoLayoutRun* = ptr TPangoLayoutRun
TPangoLayoutRun* = record TPangoLayoutRun* {.final.} = object
item*: PPangoItem item*: PPangoItem
glyphs*: PPangoGlyphString glyphs*: PPangoGlyphString

View file

@ -12,7 +12,7 @@ type
regMN, regMN,
regNewline regNewline
TRegex = record TRegex = object of TObject
case kind: TRegexKind case kind: TRegexKind
of regChar: c: char of regChar: c: char
of regSet: s: ref set[char] of regSet: s: ref set[char]

View file

@ -162,7 +162,7 @@ type
# Data passed back in callouts # Data passed back in callouts
# Const before type ignored # Const before type ignored
# Pointer to character tables # Pointer to character tables
Tpcre_extra* = record Tpcre_extra* {.final.} = object
flags: cuint flags: cuint
study_data: pointer study_data: pointer
match_limit: cuint match_limit: cuint
@ -189,7 +189,7 @@ type
# Offset to next item in the pattern # Offset to next item in the pattern
# Length of next item in the pattern # Length of next item in the pattern
# ------------------------------------------------------------------ # ------------------------------------------------------------------
TPcre_callout_block* = record TPcre_callout_block* {.final.} = object
version: cint version: cint
callout_number: cint callout_number: cint
offset_vector: ptr cint offset_vector: ptr cint

View file

@ -19,10 +19,8 @@ import
math math
type type
TComplex* = record ## a complex number, consisting of a real and an TComplex* = tuple[re, im: float]
## imaginary part ## a complex number, consisting of a real and an imaginary part
re*: float ## real part of the complex number
im*: float ## imarginary part of the complex number
proc `==` *(x, y: TComplex): bool = proc `==` *(x, y: TComplex): bool =
## Compare two complex numbers `x` and `y` for equality. ## Compare two complex numbers `x` and `y` for equality.

View file

@ -25,23 +25,24 @@ type
dbQuiting, # debugger wants to quit dbQuiting, # debugger wants to quit
dbBreakpoints # debugger is only interested in breakpoints dbBreakpoints # debugger is only interested in breakpoints
TDbgBreakpoint = record TDbgBreakpoint {.final.} = object
low, high: int # range from low to high; if disabled low, high: int # range from low to high; if disabled
# both low and high are set to their negative values # both low and high are set to their negative values
# this makes the check faster and safes memory # this makes the check faster and safes memory
filename: string filename: string
name: string # name of breakpoint name: string # name of breakpoint
TVarSlot {.compilerproc.} = record # variable slots used for debugger: TVarSlot {.compilerproc, final.} = object # variable slots used for debugger:
address: pointer address: pointer
typ: PNimType typ: PNimType
name: cstring # for globals this is "module.name" name: cstring # for globals this is "module.name"
PExtendedFrame = ptr TExtendedFrame PExtendedFrame = ptr TExtendedFrame
TExtendedFrame = record # If the debugger is enabled the compiler provides TExtendedFrame {.final.} = object # If the debugger is enabled the compiler
# an extended frame. Of course only slots that are # provides an extended frame. Of course
# needed are allocated and not 10_000, except for # only slots that are
# the global data description. # needed are allocated and not 10_000,
# except for the global data description.
f: TFrame f: TFrame
slots: array[0..10_000, TVarSlot] slots: array[0..10_000, TVarSlot]
@ -69,7 +70,7 @@ proc findBreakpoint(name: string): int =
return -1 return -1
proc ListBreakPoints() = proc ListBreakPoints() =
write(stdout, "*** emdb| Breakpoints:\n") write(stdout, "*** endb| Breakpoints:\n")
for i in 0 .. dbgBPlen-1: for i in 0 .. dbgBPlen-1:
write(stdout, dbgBP[i].name & ": " & $abs(dbgBP[i].low) & ".." & write(stdout, dbgBP[i].name & ": " & $abs(dbgBP[i].low) & ".." &
$abs(dbgBP[i].high) & dbgBP[i].filename) $abs(dbgBP[i].high) & dbgBP[i].filename)
@ -101,13 +102,13 @@ proc writeVariable(stream: TFile, slot: TVarSlot) =
writeln(stream, dbgRepr(slot.address, slot.typ)) writeln(stream, dbgRepr(slot.address, slot.typ))
proc ListFrame(stream: TFile, f: PExtendedFrame) = proc ListFrame(stream: TFile, f: PExtendedFrame) =
write(stream, "*** emdb| Frame (" & $f.f.len & " slots):\n") write(stream, "*** endb| Frame (" & $f.f.len & " slots):\n")
for i in 0 .. f.f.len-1: for i in 0 .. f.f.len-1:
writeVariable(stream, f.slots[i]) writeVariable(stream, f.slots[i])
write(stream, "***\n") write(stream, "***\n")
proc ListVariables(stream: TFile, f: PExtendedFrame) = proc ListVariables(stream: TFile, f: PExtendedFrame) =
write(stream, "*** emdb| Frame (" & $f.f.len & " slots):\n") write(stream, "*** endb| Frame (" & $f.f.len & " slots):\n")
for i in 0 .. f.f.len-1: for i in 0 .. f.f.len-1:
writeln(stream, f.slots[i].name) writeln(stream, f.slots[i].name)
write(stream, "***\n") write(stream, "***\n")
@ -115,7 +116,7 @@ proc ListVariables(stream: TFile, f: PExtendedFrame) =
proc debugOut(msg: cstring) = proc debugOut(msg: cstring) =
# the *** *** markers are for easy recognition of debugger # the *** *** markers are for easy recognition of debugger
# output for external frontends. # output for external frontends.
write(stdout, "*** emdb| ") write(stdout, "*** endb| ")
write(stdout, msg) write(stdout, msg)
write(stdout, "***\n") write(stdout, "***\n")
@ -131,14 +132,14 @@ proc findVariable(frame: PExtendedFrame, varname: cstring): int =
proc dbgShowCurrentProc(dbgFramePointer: PFrame) = proc dbgShowCurrentProc(dbgFramePointer: PFrame) =
if dbgFramePointer != nil: if dbgFramePointer != nil:
write(stdout, "*** emdb| now in proc: ") write(stdout, "*** endb| now in proc: ")
write(stdout, dbgFramePointer.procname) write(stdout, dbgFramePointer.procname)
write(stdout, " ***\n") write(stdout, " ***\n")
else: else:
write(stdout, "*** emdb| (procedure name not available) ***\n") write(stdout, "*** endb| (procedure name not available) ***\n")
proc dbgShowExecutionPoint() = proc dbgShowExecutionPoint() =
write(stdout, "*** emdb| " & $framePtr.filename & "(" & $framePtr.line & write(stdout, "*** endb| " & $framePtr.filename & "(" & $framePtr.line &
") " & $framePtr.procname & " ***\n") ") " & $framePtr.procname & " ***\n")
when defined(windows) or defined(dos) or defined(os2): when defined(windows) or defined(dos) or defined(os2):
@ -219,26 +220,26 @@ h, help display this help message
q, quit quit the debugger and the program q, quit quit the debugger and the program
<ENTER> repeat the previous debugger command <ENTER> repeat the previous debugger command
EXECUTING EXECUTING
s, stepinto single step, stepping into routine calls s, step single step, stepping into routine calls
n, stepover single step, without stepping into routine calls n, next single step, without stepping into routine calls
f, skipcurrent continue execution until the current routine finishes f, skipcurrent continue execution until the current routine finishes
c, continue continue execution until the next breakpoint c, continue continue execution until the next breakpoint
i, ignore continue execution, ignore all breakpoints i, ignore continue execution, ignore all breakpoints
BREAKPOINTS BREAKPOINTS
b, setbreak <name> [fromline [toline]] [file] b, break <name> [fromline [toline]] [file]
set a new breakpoint named 'name' for line and file set a new breakpoint named 'name' for line and file
if line or file are omitted the current one is used if line or file are omitted the current one is used
breakpoints display the entire breakpoint list breakpoints display the entire breakpoint list
disable <name> disable a breakpoint disable <name> disable a breakpoint
enable <name> enable a breakpoint enable <name> enable a breakpoint
DATA DISPLAY DATA DISPLAY
e, eval <exp> evaluate the expression <exp> e, eval <expr> evaluate the expression <expr>
o, out <file> <exp> evaluate <exp> and write it to <file> o, out <file> <expr> evaluate <expr> and write it to <file>
w, where display the current execution point w, where display the current execution point
stackframe [file] display current stack frame [and write it to file] stackframe [file] display current stack frame [and write it to file]
u, up go up in the call stack u, up go up in the call stack
d, down go down in the call stack d, down go down in the call stack
callstack display the entire call stack bt, backtrace display the entire call stack
l, locals display available local variables l, locals display available local variables
g, globals display available global variables g, globals display available global variables
maxdisplay <integer> set the display's recursion maximum maxdisplay <integer> set the display's recursion maximum
@ -352,7 +353,7 @@ proc CommandPrompt() =
dbgDown: int = 0 # how often we did go down dbgDown: int = 0 # how often we did go down
while again: while again:
write(stdout, "*** emdb| >>") write(stdout, "*** endb| >>")
var tmp = readLine(stdin) var tmp = readLine(stdin)
if tmp.len > 0: dbgUser = tmp if tmp.len > 0: dbgUser = tmp
# now look what we have to do: # now look what we have to do:
@ -360,10 +361,10 @@ proc CommandPrompt() =
var i = scanWord(dbgUser, dbgTemp, 0) var i = scanWord(dbgUser, dbgTemp, 0)
case dbgTemp case dbgTemp
of "": InvalidCommand() of "": InvalidCommand()
of "s", "stepinto": of "s", "step":
dbgState = dbStepInto dbgState = dbStepInto
again = false again = false
of "n", "stepover": of "n", "next":
dbgState = dbStepOver dbgState = dbStepOver
dbgSkipToFrame = framePtr dbgSkipToFrame = framePtr
again = false again = false
@ -412,9 +413,9 @@ proc CommandPrompt() =
dbgShowCurrentProc(dbgFramePtr) dbgShowCurrentProc(dbgFramePtr)
else: else:
debugOut("[Warning] cannot go down any further ") debugOut("[Warning] cannot go down any further ")
of "callstack": of "bt", "backtrace":
WriteStackTrace() WriteStackTrace()
of "b", "setbreak": of "b", "break":
setBreakPoint(dbgUser, i) setBreakPoint(dbgUser, i)
of "breakpoints": of "breakpoints":
ListBreakPoints() ListBreakPoints()
@ -443,7 +444,7 @@ proc endbStep() =
proc checkForBreakpoint() = proc checkForBreakpoint() =
var i = dbgBreakpointReached(framePtr.line) var i = dbgBreakpointReached(framePtr.line)
if i >= 0: if i >= 0:
write(stdout, "*** emdb| reached ") write(stdout, "*** endb| reached ")
write(stdout, dbgBP[i].name) write(stdout, dbgBP[i].name)
write(stdout, " in ") write(stdout, " in ")
write(stdout, framePtr.filename) write(stdout, framePtr.filename)

View file

@ -6,6 +6,8 @@
#define ABORT_ON_ASSERT_FAILURE 0 #define ABORT_ON_ASSERT_FAILURE 0
*/ */
#define ABORT do { printf("abort was called\n"); abort(); } while (0)
/* /*
This is a version (aka dlmalloc) of malloc/free/realloc written by This is a version (aka dlmalloc) of malloc/free/realloc written by
Doug Lea and released to the public domain, as explained at Doug Lea and released to the public domain, as explained at

View file

@ -1,7 +1,7 @@
# #
# #
# Nimrod's Runtime Library # Nimrod's Runtime Library
# (c) Copyright 2006 Andreas Rumpf # (c) Copyright 2008 Andreas Rumpf
# #
# See the file "copying.txt", included in this # See the file "copying.txt", included in this
# distribution, for details about the copyright. # distribution, for details about the copyright.
@ -35,35 +35,34 @@ proc chckNil(p: pointer) {.inline, compilerproc.}
type type
PSafePoint = ptr TSafePoint PSafePoint = ptr TSafePoint
TSafePoint {.compilerproc.} = record TSafePoint {.compilerproc, final.} = object
prev: PSafePoint # points to next safe point ON THE STACK prev: PSafePoint # points to next safe point ON THE STACK
exc: ref E_Base exc: ref E_Base
status: int status: int
context: C_JmpBuf context: C_JmpBuf
var var
excHandler {.compilerproc, volatile.}: PSafePoint = nil excHandler {.compilerproc.}: PSafePoint = nil
# list of exception handlers # list of exception handlers
# a global variable for the root of all try blocks # a global variable for the root of all try blocks
proc reraiseException() = proc reraiseException() =
if excHandler != nil: if excHandler == nil:
raise newException(ENoExceptionToReraise, "no exception to reraise") raise newException(ENoExceptionToReraise, "no exception to reraise")
else: else:
c_longjmp(excHandler.context, 1) c_longjmp(excHandler.context, 1)
type type
PFrame = ptr TFrame PFrame = ptr TFrame
TFrame {.importc, nodecl.} = record TFrame {.importc, nodecl, final.} = object
prev: PFrame prev: PFrame
procname: CString procname: CString
line: int # current line number line: int # current line number
filename: CString filename: CString
len: int # length of slots (when not debugging always zero) len: int # length of slots (when not debugging always zero)
TTempFrame = record # used for recursion elimination in WriteStackTrace TTempFrame = tuple[ # used for recursion elimination in WriteStackTrace
procname: CString procname: CString, line: int]
line: int
var var
buf: string # cannot be allocated on the stack! buf: string # cannot be allocated on the stack!
@ -71,7 +70,7 @@ var
# assert, as it raises an exception and # assert, as it raises an exception and
# exception handler needs the buffer too # exception handler needs the buffer too
framePtr {.exportc, volatile.}: PFrame framePtr {.exportc.}: PFrame
tempFrames: array [0..255, TTempFrame] # cannot be allocated tempFrames: array [0..255, TTempFrame] # cannot be allocated
# on the stack! # on the stack!
@ -82,8 +81,7 @@ proc auxWriteStackTrace(f: PFrame, s: var string) =
i = 0 i = 0
total = 0 total = 0
while it != nil and i <= high(tempFrames): while it != nil and i <= high(tempFrames):
tempFrames[i].procname = it.procname tempFrames[i] = (it.procname, it.line)
tempFrames[i].line = it.line
inc(i) inc(i)
inc(total) inc(total)
it = it.prev it = it.prev
@ -110,10 +108,10 @@ proc rawWriteStackTrace(s: var string) =
auxWriteStackTrace(framePtr, s) auxWriteStackTrace(framePtr, s)
proc quitOrDebug() {.inline.} = proc quitOrDebug() {.inline.} =
when not defined(emdb): when not defined(endb):
quit(1) quit(1)
else: else:
emdbStep() # call the debugger endbStep() # call the debugger
proc raiseException(e: ref E_Base, ename: CString) = proc raiseException(e: ref E_Base, ename: CString) =
GC_disable() # a bad thing is an error in the GC while raising an exception GC_disable() # a bad thing is an error in the GC while raising an exception
@ -122,7 +120,7 @@ proc raiseException(e: ref E_Base, ename: CString) =
excHandler.exc = e excHandler.exc = e
c_longjmp(excHandler.context, 1) c_longjmp(excHandler.context, 1)
else: else:
if cast[pointer](buf) != nil: if not isNil(buf):
setLen(buf, 0) setLen(buf, 0)
rawWriteStackTrace(buf) rawWriteStackTrace(buf)
if e.msg != nil and e.msg[0] != '\0': if e.msg != nil and e.msg[0] != '\0':
@ -135,9 +133,7 @@ proc raiseException(e: ref E_Base, ename: CString) =
add(buf, "]\n") add(buf, "]\n")
writeToStdErr(buf) writeToStdErr(buf)
else: else:
writeToStdErr("*** FATAL ERROR *** ")
writeToStdErr(ename) writeToStdErr(ename)
writeToStdErr("\n")
quitOrDebug() quitOrDebug()
GC_enable() GC_enable()
@ -147,7 +143,8 @@ var
proc internalAssert(file: cstring, line: int, cond: bool) {.compilerproc.} = proc internalAssert(file: cstring, line: int, cond: bool) {.compilerproc.} =
if not cond: if not cond:
GC_disable() # BUGFIX: `$` allocates a new string object! GC_disable() # BUGFIX: `$` allocates a new string object!
if cast[pointer](assertBuf) != nil: # BUGFIX: when debugging the GC, assertBuf may be nil if not isNil(assertBuf):
# BUGFIX: when debugging the GC, assertBuf may be nil
setLen(assertBuf, 0) setLen(assertBuf, 0)
add(assertBuf, "[Assertion failure] file: ") add(assertBuf, "[Assertion failure] file: ")
add(assertBuf, file) add(assertBuf, file)
@ -164,6 +161,11 @@ proc WriteStackTrace() =
rawWriteStackTrace(s) rawWriteStackTrace(s)
writeToStdErr(s) writeToStdErr(s)
#proc stackTraceWrapper {.noconv.} =
# writeStackTrace()
#addQuitProc(stackTraceWrapper)
var var
dbgAborting: bool # whether the debugger wants to abort dbgAborting: bool # whether the debugger wants to abort
@ -171,6 +173,7 @@ proc signalHandler(sig: cint) {.exportc: "signalHandler", noconv.} =
# print stack trace and quit # print stack trace and quit
var var
s = int(sig) s = int(sig)
GC_disable()
setLen(buf, 0) setLen(buf, 0)
rawWriteStackTrace(buf) rawWriteStackTrace(buf)
@ -185,6 +188,7 @@ proc signalHandler(sig: cint) {.exportc: "signalHandler", noconv.} =
else: add(buf, "unknown signal\n") else: add(buf, "unknown signal\n")
writeToStdErr(buf) writeToStdErr(buf)
dbgAborting = True # play safe here... dbgAborting = True # play safe here...
GC_enable()
quit(1) # always quit when SIGABRT quit(1) # always quit when SIGABRT
proc registerSignalHandler() = proc registerSignalHandler() =
@ -204,12 +208,15 @@ assertBuf = newString(2048)
setLen(buf, 0) setLen(buf, 0)
setLen(assertBuf, 0) setLen(assertBuf, 0)
proc raiseRangeError() {.compilerproc, noreturn.} = proc raiseRangeError(val: biggestInt) {.compilerproc, noreturn.} =
raise newException(EOutOfRange, "value out of range") raise newException(EOutOfRange, "value " & $val & " out of range")
proc raiseIndexError() {.compilerproc, noreturn.} = proc raiseIndexError() {.compilerproc, noreturn.} =
raise newException(EInvalidIndex, "index out of bounds") raise newException(EInvalidIndex, "index out of bounds")
proc raiseFieldError(f: string) {.compilerproc, noreturn.} =
raise newException(EInvalidField, f & " is not accessible")
proc chckIndx(i, a, b: int): int = proc chckIndx(i, a, b: int): int =
if i >= a and i <= b: if i >= a and i <= b:
return i return i
@ -220,19 +227,19 @@ proc chckRange(i, a, b: int): int =
if i >= a and i <= b: if i >= a and i <= b:
return i return i
else: else:
raiseRangeError() raiseRangeError(i)
proc chckRange64(i, a, b: int64): int64 {.compilerproc.} = proc chckRange64(i, a, b: int64): int64 {.compilerproc.} =
if i >= a and i <= b: if i >= a and i <= b:
return i return i
else: else:
raiseRangeError() raiseRangeError(i)
proc chckRangeF(x, a, b: float): float = proc chckRangeF(x, a, b: float): float =
if x >= a and x <= b: if x >= a and x <= b:
return x return x
else: else:
raiseRangeError() raise newException(EOutOfRange, "value " & $x & " out of range")
proc chckNil(p: pointer) = proc chckNil(p: pointer) =
if p == nil: c_raise(SIGSEGV) if p == nil: c_raise(SIGSEGV)

View file

@ -1,7 +1,7 @@
# #
# #
# Nimrod's Runtime Library # Nimrod's Runtime Library
# (c) Copyright 2006 Andreas Rumpf # (c) Copyright 2008 Andreas Rumpf
# #
# See the file "copying.txt", included in this # See the file "copying.txt", included in this
# distribution, for details about the copyright. # distribution, for details about the copyright.
@ -13,33 +13,39 @@
# For a description of the algorithms used here see: # For a description of the algorithms used here see:
# intern.html # intern.html
#{.define: debugGC.} # we wish to debug the GC... {.define: debugGC.} # we wish to debug the GC...
#when defined(debugGC): #when defined(debugGC):
# {.define: logGC.} # define if the GC should log some of its activities # {.define: logGC.} # define if the GC should log some of its activities
{.define: cycleGC.} {.define: cycleGC.}
const
traceGC = false # extensive debugging
reallyDealloc = true # for debugging purposes this can be set to false
# Guess the page size of the system; if it is the # Guess the page size of the system; if it is the
# wrong value, performance may be worse (this is not # wrong value, performance may be worse (this is not
# for sure though), but GC still works; must be a power of two! # for sure though), but GC still works; must be a power of two!
const const
PageSize = 1024 * sizeof(int) PageShift = if sizeof(pointer) == 4: 12 else: 13
RC_Increase = 7 * PageSize # is an additive increase PageSize = 1 shl PageShift # on 32 bit systems 4096
CycleIncrease = 2 # is a multiplicative increase CycleIncrease = 2 # is a multiplicative increase
InitialCycleThreshold = 8*1024*1024 # X MB because cycle checking is slow
ZctThreshold = 512 # we collect garbage if the ZCT's size
# reaches this threshold
# this needs benchmarking...
when defined(debugGC): when defined(debugGC):
const InitialThreshold = 64*1024 const stressGC = False
const stressGC = True # GC is debugged; no need to stress it
else: else:
const stressGC = False const stressGC = False
const InitialThreshold = RC_Increase
# this may need benchmarking...
# things the System module thinks should be available: # things the System module thinks should be available:
when defined(useDL) or defined(nativeDL): when defined(useDL) or defined(nativeDL):
type type
TMallocInfo {.importc: "struct mallinfo", nodecl.} = record TMallocInfo {.importc: "struct mallinfo", nodecl, final.} = object
arena: cint # non-mmapped space allocated from system arena: cint # non-mmapped space allocated from system
ordblks: cint # number of free chunks ordblks: cint # number of free chunks
smblks: cint # number of fastbin blocks smblks: cint # number of fastbin blocks
@ -68,8 +74,7 @@ else: # not available:
proc getTotalMem(): int = return -1 proc getTotalMem(): int = return -1
var var
rcThreshold: int = InitialThreshold cycleThreshold: int = InitialCycleThreshold
cycleThreshold: int = InitialThreshold
memUsed: int = 0 # we have to keep track how much we have allocated memUsed: int = 0 # we have to keep track how much we have allocated
@ -113,9 +118,10 @@ type
waNone, waRelease, waZctDecRef, waCycleDecRef, waCycleIncRef, waDebugIncRef waNone, waRelease, waZctDecRef, waCycleDecRef, waCycleIncRef, waDebugIncRef
TCollectorData = int TCollectorData = int
TCell = record TCell {.final.} = object
refcount: TCollectorData # the refcount and bit flags refcount: TCollectorData # the refcount and bit flags
typ: PNimType typ: PNimType
when stressGC:
stackcount: int # stack counter for debugging stackcount: int # stack counter for debugging
drefc: int # real reference counter for debugging drefc: int # real reference counter for debugging
@ -145,6 +151,7 @@ proc extGetCellType(c: pointer): PNimType {.compilerproc.} =
proc internRefcount(p: pointer): int {.exportc: "getRefcount".} = proc internRefcount(p: pointer): int {.exportc: "getRefcount".} =
result = int(usrToCell(p).refcount) result = int(usrToCell(p).refcount)
if result < 0: result = 0
proc gcAlloc(size: int): pointer = proc gcAlloc(size: int): pointer =
result = alloc0(size) result = alloc0(size)
@ -162,7 +169,7 @@ proc GC_setStrategy(strategy: TGC_Strategy) =
of gcOptimizeTime: nil of gcOptimizeTime: nil
proc GC_enableMarkAndSweep() = proc GC_enableMarkAndSweep() =
cycleThreshold = InitialThreshold cycleThreshold = InitialCycleThreshold
proc GC_disableMarkAndSweep() = proc GC_disableMarkAndSweep() =
cycleThreshold = high(cycleThreshold)-1 cycleThreshold = high(cycleThreshold)-1
@ -174,7 +181,7 @@ proc nextTry(h, maxHash: int): int {.inline.} =
# generates each int in range(maxHash) exactly once (see any text on # generates each int in range(maxHash) exactly once (see any text on
# random-number generation for proof). # random-number generation for proof).
# ------------------ Zero count table (ZCT) and any table (AT) ------------- # ------------------ Any table (AT) -------------
# these values are for DL-malloc known for sure (and other allocators # these values are for DL-malloc known for sure (and other allocators
# can only be worse): # can only be worse):
@ -200,8 +207,7 @@ when BitsPerPage mod BitsPerUnit != 0:
# ------------------- cell set handling ------------------------------ # ------------------- cell set handling ------------------------------
# A cellset consists of a hash table of page descriptors. A page # A cellset consists of a hash table of page descriptors. A page
# descriptor has a bit for # descriptor has a bit for every Memalignment'th byte in the page.
# every Memalignment'th byte in the page.
# However, only bits corresponding to addresses that start memory blocks # However, only bits corresponding to addresses that start memory blocks
# are set. # are set.
# Page descriptors are also linked to a list; the list # Page descriptors are also linked to a list; the list
@ -217,17 +223,59 @@ type
TBitIndex = range[0..UnitsPerPage-1] TBitIndex = range[0..UnitsPerPage-1]
TPageDesc = record TPageDesc {.final.} = object
next: PPageDesc # all nodes are connected with this pointer next: PPageDesc # all nodes are connected with this pointer
key: TAddress # start address at bit 0 key: TAddress # start address at bit 0
bits: array[TBitIndex, int] # a bit vector bits: array[TBitIndex, int] # a bit vector
PPageDescArray = ptr array[0..1000_000, PPageDesc] PPageDescArray = ptr array[0..1000_000, PPageDesc]
TCellSet = record TCellSet {.final.} = object
counter, max: int counter, max: int
head: PPageDesc head: PPageDesc
data: PPageDescArray data: PPageDescArray
PCellArray = ptr array[0..100_000_000, PCell]
TCellSeq {.final.} = object
len, cap: int
d: PCellArray
TSlowSet {.final.} = object # used for debugging purposes only
L: int # current length
cap: int # capacity
d: PCellArray
TGcHeap {.final.} = object # this contains the zero count and
# non-zero count table
mask: TAddress # mask for fast pointer detection
zct: TCellSeq # the zero count table
at: TCellSet # a table that contains all references
newAT: TCellSet
stackCells: TCellSeq # cells that need to be decremented because they
# are in the hardware stack; a cell may occur
# several times in this data structure
var
stackBottom: pointer
gch: TGcHeap
proc add(s: var TCellSeq, c: PCell) {.inline.} =
if s.len >= s.cap:
s.cap = s.cap * 3 div 2
s.d = cast[PCellArray](realloc(s.d, s.cap * sizeof(PCell)))
if s.d == nil: raiseOutOfMem()
s.d[s.len] = c
inc(s.len)
proc inOperator(s: TCellSeq, c: PCell): bool {.inline.} =
for i in 0 .. s.len-1:
if s.d[i] == c: return True
return False
proc init(s: var TCellSeq, cap: int = 1024) =
s.len = 0
s.cap = cap
s.d = cast[PCellArray](gcAlloc(cap * sizeof(PCell)))
const const
InitCellSetSize = 1024 # must be a power of two! InitCellSetSize = 1024 # must be a power of two!
@ -284,7 +332,8 @@ proc CellSetPut(t: var TCellSet, key: TAddress): PPageDesc =
if x.key == key: return x if x.key == key: return x
h = nextTry(h, t.max) h = nextTry(h, t.max)
if (t.max+1) * 2 < t.counter * 3: CellSetEnlarge(t) if ((t.max+1)*2 < t.counter*3) or ((t.max+1)-t.counter < 4):
CellSetEnlarge(t)
inc(t.counter) inc(t.counter)
h = cast[int](key) and t.max h = cast[int](key) and t.max
while t.data[h] != nil: h = nextTry(h, t.max) while t.data[h] != nil: h = nextTry(h, t.max)
@ -303,7 +352,7 @@ proc in_Operator(s: TCellSet, cell: PCell): bool =
u: TAddress u: TAddress
t: PPageDesc t: PPageDesc
u = cast[TAddress](cell) u = cast[TAddress](cell)
t = CellSetGet(s, u /% PageSize) t = CellSetGet(s, u shr PageShift)
if t != nil: if t != nil:
u = (u %% PageSize) /% MemAlignment u = (u %% PageSize) /% MemAlignment
result = (t.bits[u /% BitsPerUnit] and (1 shl (u %% BitsPerUnit))) != 0 result = (t.bits[u /% BitsPerUnit] and (1 shl (u %% BitsPerUnit))) != 0
@ -315,7 +364,7 @@ proc incl(s: var TCellSet, cell: PCell) =
u: TAddress u: TAddress
t: PPageDesc t: PPageDesc
u = cast[TAddress](cell) u = cast[TAddress](cell)
t = CellSetPut(s, u /% PageSize) t = CellSetPut(s, u shr PageShift)
u = (u %% PageSize) /% MemAlignment u = (u %% PageSize) /% MemAlignment
t.bits[u /% BitsPerUnit] = t.bits[u /% BitsPerUnit] or t.bits[u /% BitsPerUnit] = t.bits[u /% BitsPerUnit] or
(1 shl (u %% BitsPerUnit)) (1 shl (u %% BitsPerUnit))
@ -325,7 +374,7 @@ proc excl(s: var TCellSet, cell: PCell) =
u: TAddress u: TAddress
t: PPageDesc t: PPageDesc
u = cast[TAddress](cell) u = cast[TAddress](cell)
t = CellSetGet(s, u /% PageSize) t = CellSetGet(s, u shr PageShift)
if t != nil: if t != nil:
u = (u %% PageSize) /% MemAlignment u = (u %% PageSize) /% MemAlignment
t.bits[u /% BitsPerUnit] = (t.bits[u /% BitsPerUnit] and t.bits[u /% BitsPerUnit] = (t.bits[u /% BitsPerUnit] and
@ -342,7 +391,7 @@ iterator elements(t: TCellSet): PCell {.inline.} =
var j = 0 var j = 0
while w != 0: # test all remaining bits for zero while w != 0: # test all remaining bits for zero
if (w and 1) != 0: # the bit is set! if (w and 1) != 0: # the bit is set!
yield cast[PCell]((r.key *% PageSize) +% yield cast[PCell]((r.key shl PageShift) or # +%
(i*%BitsPerUnit+%j) *% MemAlignment) (i*%BitsPerUnit+%j) *% MemAlignment)
inc(j) inc(j)
w = w shr 1 w = w shr 1
@ -354,68 +403,121 @@ iterator elements(t: TCellSet): PCell {.inline.} =
proc testPageDescs() = proc testPageDescs() =
var root: TCellSet var root: TCellSet
CellSetInit(root) CellSetInit(root)
var u = 10_000 #var u = 10_000
while u <= 20_000: #while u <= 20_000:
incl(root, cast[PCell](u)) # incl(root, cast[PCell](u))
inc(u, 8) # inc(u, 8)
incl(root, cast[PCell](0x81cdfb8))
for cell in elements(root): for cell in elements(root):
c_fprintf(c_stdout, "%ld\n", cast[int](cell)) c_fprintf(c_stdout, "%p\n", cast[int](cell))
#testPageDescs() #testPageDescs()
when defined(debugGC): when defined(debugGC):
proc writeCell(msg: CString, c: PCell) = proc writeCell(msg: CString, c: PCell) =
c_fprintf(c_stdout, "%s: %p\n", msg, c) if c.typ != nil:
if c.typ.kind == tyString:
c_fprintf(c_stdout, "%s\n", cast[TAddress](cellToUsr(c)) + sizeof(int)*2)
c_fprintf(c_stdout, "%s: %p %d\n", msg, c, c.typ.kind)
else: c_fprintf(c_stdout, "%s: %p (nil type)\n", msg, c)
proc writePtr(msg: CString, p: Pointer) = proc writePtr(msg: CString, p: Pointer) =
c_fprintf(c_stdout, "%s: %p\n", msg, p) c_fprintf(c_stdout, "%s: %p\n", msg, p)
# -------------------------------------------------------------------------
when traceGC:
# traceGC is a special switch to enable extensive debugging
type type
PStackCells = ptr array[0..1000_0000, PCell] TCellState = enum
TCountTables = record # this contains the zero count and csAllocated, csZctFreed, csCycFreed
# non-zero count table
mask: TAddress # mask for fast pointer detection
zct: TCellSet # the zero count table
at: TCellSet # a table that contains all references
newAT: TCellSet
newZCT: TCellSet
stackCells: PStackCells # cells that need to be decremented because they
# are in the hardware stack; a cell may occur
# several times in this data structure
stackLen, stackMax: int # for managing the stack cells
proc addStackCell(ct: var TCountTables, cell: PCell) = proc cellSetInit(s: var TSlowSet) =
if ct.stackLen >= ct.stackMax: s.L = 0
ct.stackMax = ct.stackMax * 3 div 2 s.cap = 4096
ct.stackCells = cast[PStackCells](realloc(ct.stackCells, ct.stackMax * s.d = cast[PCellArray](gcAlloc(s.cap * sizeof(PCell)))
sizeof(PCell)))
if ct.stackCells == nil: raiseOutOfMem() proc cellSetDeinit(s: var TSlowSet) =
ct.stackCells[ct.stackLen] = cell s.L = 0
inc(ct.stackLen) s.cap = 0
dealloc(s.d)
proc incl(s: var TSlowSet, c: PCell) =
if s.L >= s.cap:
s.cap = s.cap * 3 div 2
s.d = cast[PCellArray](realloc(s.d, s.cap * sizeof(PCell)))
if s.d == nil: raiseOutOfMem()
s.d[s.L] = c
inc(s.L)
proc excl(s: var TSlowSet, c: PCell) =
var i = 0
while i < s.L:
if s.d[i] == c:
s.d[i] = s.d[s.L-1]
dec(s.L)
break
inc(i)
proc inOperator(s: TSlowSet, c: PCell): bool =
var i = 0
while i < s.L:
if s.d[i] == c: return true
inc(i)
iterator elements(s: TSlowSet): PCell =
var i = 0
while i < s.L:
yield s.d[i]
inc(i)
var var
stackBottom: pointer states: array[TCellState, TSlowSet] # TCellSet]
ct: TCountTables
proc GC_invariant(): bool = proc traceCell(c: PCell, state: TCellState) =
result = True case state
when stressGC: of csAllocated:
if recGcLock == 0: if c in states[csAllocated]:
GC_disable() writeCell("attempt to alloc a already allocated cell", c)
for cell in elements(ct.at):
var t = cell.typ # getCellType(cell)
if t == nil or t.kind notin {tySequence, tyString, tyRef}:
writeCell("corrupt cell?", cell)
result = false
GC_enable()
when stressGC:
proc GCdebugHook() =
if not GC_invariant():
assert(false) assert(false)
excl(states[csCycFreed], c)
excl(states[csZctFreed], c)
of csZctFreed:
if c notin states[csAllocated]:
writeCell("attempt to free a not allocated cell", c)
assert(false)
if c in states[csZctFreed]:
writeCell("attempt to free zct cell twice", c)
assert(false)
if c in states[csCycFreed]:
writeCell("attempt to free with zct, but already freed with cyc", c)
assert(false)
excl(states[csAllocated], c)
of csCycFreed:
if c notin states[csAllocated]:
writeCell("attempt to free a not allocated cell", c)
assert(false)
if c in states[csCycFreed]:
writeCell("attempt to free cyc cell twice", c)
assert(false)
if c in states[csZctFreed]:
writeCell("attempt to free with cyc, but already freed with zct", c)
assert(false)
excl(states[csAllocated], c)
incl(states[state], c)
dbgLineHook = GCdebugHook template gcTrace(cell, state: expr): stmt =
when traceGC: traceCell(cell, state)
# -------------------------------------------------------------------------
# forward declarations:
proc collectCT(gch: var TGcHeap)
proc IsOnStack(p: pointer): bool
proc forAllChildren(cell: PCell, op: TWalkOp)
proc collectCycles(gch: var TGcHeap)
proc reprAny(p: pointer, typ: PNimType): string {.compilerproc.}
# we need the prototype here for debugging purposes
proc prepareDealloc(cell: PCell) = proc prepareDealloc(cell: PCell) =
if cell.typ.finalizer != nil: if cell.typ.finalizer != nil:
@ -433,79 +535,95 @@ proc prepareDealloc(cell: PCell) =
else: else:
memUsed = memUsed - cell.typ.size memUsed = memUsed - cell.typ.size
proc setStackBottom(theStackBottom: pointer) {.compilerproc.} = proc checkZCT(): bool =
stackBottom = theStackBottom if recGcLock >= 1: return true # prevent endless recursion
proc initGC() =
# init the rt
CellSetInit(ct.zct)
CellSetInit(ct.at)
ct.stackLen = 0
ct.stackMax = 255
ct.stackCells = cast[PStackCells](gcAlloc((ct.stackMax+1) * sizeof(PCell)))
ct.mask = 0
new(gOutOfMem) # reserve space for the EOutOfMemory exception here!
assert(GC_invariant())
# forward declarations:
proc collectCT(ct: var TCountTables)
proc IsOnStack(p: pointer): bool
proc forAllChildren(cell: PCell, op: TWalkOp)
proc collectCycles()
proc reprAny(p: pointer, typ: PNimType): string {.compilerproc.}
# we need the prototype here for debugging purposes
proc outputCell(c: PCell) =
inc(recGcLock) inc(recGcLock)
write(stdout, reprAny(cellToUsr(c), c.typ)) result = true
for i in 0..gch.zct.len-1:
var c = gch.zct.d[i]
if c.refcount > 0: # should be in the ZCT!
writeCell("wrong ZCT entry", c)
result = false
elif gch.zct.d[-c.refcount] != c:
writeCell("wrong ZCT position", c)
result = false
dec(recGcLock) dec(recGcLock)
proc writeGraph() = proc GC_invariant(): bool =
{.checkpoint.}
block:
inc(recGcLock)
for c in elements(ct.AT): outputCell(c)
dec(recGcLock)
proc checkRefc(): bool =
if recGcLock >= 1: return true # prevent endless recursion if recGcLock >= 1: return true # prevent endless recursion
inc(recGcLock) inc(recGcLock)
result = True result = True
block checks:
if not checkZCT():
result = false
break checks
# set counters back to zero: # set counters back to zero:
for c in elements(ct.AT): for c in elements(gch.AT):
c.drefc = 0 var t = c.typ
for c in elements(ct.AT): if t == nil or t.kind notin {tySequence, tyString, tyRef}:
writeCell("corrupt cell?", c)
result = false
break checks
when stressGC: c.drefc = 0
for c in elements(gch.AT):
forAllChildren(c, waDebugIncRef) forAllChildren(c, waDebugIncRef)
for c in elements(ct.AT): when stressGC:
if c.drefc > c.refcount - c.stackcount: for c in elements(gch.AT):
var rc = c.refcount
if rc < 0: rc = 0
if c.drefc > rc + c.stackcount:
result = false # failed result = false # failed
c_fprintf(c_stdout, c_fprintf(c_stdout,
"broken cell: %p, refc: %ld, stack: %ld, real: %ld\n", "broken cell: %p, refc: %ld, stack: %ld, real: %ld\n",
c, c.refcount, c.stackcount, c.drefc) c, c.refcount, c.stackcount, c.drefc)
break checks
dec(recGcLock) dec(recGcLock)
proc seqCheck(cell: PCell): bool = when stressGC:
assert(cell.typ != nil) proc GCdebugHook() =
if cell.typ.kind in {tySequence, tyString}: if not GC_invariant():
result = cell.refcount - cell.stackcount <= 1 assert(false)
else:
result = true dbgLineHook = GCdebugHook
proc setStackBottom(theStackBottom: pointer) {.compilerproc.} =
stackBottom = theStackBottom
proc initGC() =
when traceGC:
for i in low(TCellState)..high(TCellState): CellSetInit(states[i])
# init the rt
init(gch.zct)
CellSetInit(gch.at)
init(gch.stackCells)
gch.mask = 0
new(gOutOfMem) # reserve space for the EOutOfMemory exception here!
assert(GC_invariant())
proc decRef(cell: PCell) {.inline.} = proc decRef(cell: PCell) {.inline.} =
assert(cell in ct.AT)
when defined(debugGC):
if cell.refcount == 0:
writePtr("decref broken", cellToUsr(cell))
assert(cell.refcount > 0) # this should be the case! assert(cell.refcount > 0) # this should be the case!
assert(seqCheck(cell)) when stressGC: assert(cell in gch.AT)
dec(cell.refcount) dec(cell.refcount)
if cell.refcount == 0: if cell.refcount == 0:
incl(ct.zct, cell) cell.refcount = -gch.zct.len
when stressGC: assert(cell notin gch.zct)
add(gch.zct, cell)
when stressGC: assert(checkZCT())
proc incRef(cell: PCell) {.inline.} = proc incRef(cell: PCell) {.inline.} =
assert(seqCheck(cell)) var rc = cell.refcount
if rc <= 0:
# remove from zero count table:
when stressGC: assert(gch.zct.len > -rc)
when stressGC: assert(gch.zct.d[-rc] == cell)
gch.zct.d[-rc] = gch.zct.d[gch.zct.len-1]
gch.zct.d[-rc].refcount = rc
dec(gch.zct.len)
cell.refcount = 1
when stressGC: assert(checkZCT())
else:
inc(cell.refcount) inc(cell.refcount)
when stressGC: assert(checkZCT())
proc asgnRef(dest: ppointer, src: pointer) = proc asgnRef(dest: ppointer, src: pointer) =
# the code generator calls this proc! # the code generator calls this proc!
@ -514,18 +632,18 @@ proc asgnRef(dest: ppointer, src: pointer) =
if src != nil: incRef(usrToCell(src)) if src != nil: incRef(usrToCell(src))
if dest^ != nil: decRef(usrToCell(dest^)) if dest^ != nil: decRef(usrToCell(dest^))
dest^ = src dest^ = src
#assert(checkRefc()) when stressGC: assert(GC_invariant())
proc unsureAsgnRef(dest: ppointer, src: pointer) = proc unsureAsgnRef(dest: ppointer, src: pointer) =
if not IsOnStack(dest): if not IsOnStack(dest):
if src != nil: incRef(usrToCell(src)) if src != nil: incRef(usrToCell(src))
if dest^ != nil: decRef(usrToCell(dest^)) if dest^ != nil: decRef(usrToCell(dest^))
dest^ = src dest^ = src
#assert(checkRefc()) when stressGC: assert(GC_invariant())
proc restore(cell: PCell) = proc restore(cell: PCell) =
if cell notin ct.newAT: if cell notin gch.newAT:
incl(ct.newAT, Cell) incl(gch.newAT, Cell)
forAllChildren(cell, waCycleIncRef) forAllChildren(cell, waCycleIncRef)
proc doOperation(p: pointer, op: TWalkOp) = proc doOperation(p: pointer, op: TWalkOp) =
@ -536,19 +654,15 @@ proc doOperation(p: pointer, op: TWalkOp) =
of waNone: assert(false) of waNone: assert(false)
of waRelease: decRef(cell) # DEAD CODE! of waRelease: decRef(cell) # DEAD CODE!
of waZctDecRef: of waZctDecRef:
assert(cell.refcount > 0) decRef(cell)
assert(seqCheck(cell))
dec(cell.refcount)
if cell.refcount == 0:
incl(ct.newZCT, cell)
of waCycleDecRef: of waCycleDecRef:
assert(cell.refcount != 0) assert(cell.refcount > 0)
dec(cell.refcount) dec(cell.refcount)
of waCycleIncRef: of waCycleIncRef:
inc(cell.refcount) # restore proper reference counts! inc(cell.refcount) # restore proper reference counts!
restore(cell) restore(cell)
of waDebugIncRef: of waDebugIncRef:
inc(cell.drefc) when stressGC: inc(cell.drefc)
type type
TByteArray = array[0..1000_0000, byte] TByteArray = array[0..1000_0000, byte]
@ -590,16 +704,20 @@ proc forAllSlotsAux(dest: pointer, n: ptr TNimNode, op: TWalkOp) =
if m != nil: forAllSlotsAux(dest, m, op) if m != nil: forAllSlotsAux(dest, m, op)
proc forAllChildrenAux(dest: Pointer, mt: PNimType, op: TWalkOp) = proc forAllChildrenAux(dest: Pointer, mt: PNimType, op: TWalkOp) =
const
handledTypes = {tyArray, tyArrayConstr, tyOpenArray, tyRef,
tyString, tySequence, tyObject, tyPureObject, tyTuple}
var var
d = cast[TAddress](dest) d = cast[TAddress](dest)
if dest == nil: return # nothing to do if dest == nil: return # nothing to do
case mt.Kind case mt.Kind
of tyArray, tyArrayConstr, tyOpenArray: of tyArray, tyArrayConstr, tyOpenArray:
if mt.base.kind in handledTypes:
for i in 0..(mt.size div mt.base.size)-1: for i in 0..(mt.size div mt.base.size)-1:
forAllChildrenAux(cast[pointer](d +% i *% mt.base.size), mt.base, op) forAllChildrenAux(cast[pointer](d +% i *% mt.base.size), mt.base, op)
of tyRef, tyString, tySequence: # leaf: of tyRef, tyString, tySequence: # leaf:
doOperation(cast[ppointer](d)^, op) doOperation(cast[ppointer](d)^, op)
of tyRecord, tyObject, tyTuple: of tyObject, tyTuple, tyPureObject:
forAllSlotsAux(dest, mt.node, op) forAllSlotsAux(dest, mt.node, op)
else: nil else: nil
@ -608,6 +726,13 @@ proc forAllChildren(cell: PCell, op: TWalkOp) =
when defined(debugGC): when defined(debugGC):
if cell.typ == nil: if cell.typ == nil:
writeCell("cell has no type descriptor", cell) writeCell("cell has no type descriptor", cell)
when traceGC:
if cell notin states[csAllocated]:
writeCell("cell has never been allocated!", cell)
if cell in states[csCycFreed]:
writeCell("cell has been freed by Cyc", cell)
if cell in states[csZctFreed]:
writeCell("cell has been freed by Zct", cell)
assert(cell.typ != nil) assert(cell.typ != nil)
case cell.typ.Kind case cell.typ.Kind
of tyRef: # common case of tyRef: # common case
@ -625,36 +750,36 @@ proc forAllChildren(cell: PCell, op: TWalkOp) =
proc checkCollection() {.inline.} = proc checkCollection() {.inline.} =
# checks if a collection should be done # checks if a collection should be done
if recGcLock == 0: if recGcLock == 0:
if memUsed >= rcThreshold or stressGC: collectCT(gch)
collectCT(ct)
when defined(debugGC):
write(stdout, "threshold is now: ")
writeln(stdout, rcThreshold)
proc newObj(typ: PNimType, size: int): pointer = proc newObj(typ: PNimType, size: int): pointer =
# generates a new object and sets its reference counter to 0 # generates a new object and sets its reference counter to 0
var var
res: PCell res: PCell
when stressGC: assert(checkZCT())
assert(typ.kind in {tyRef, tyString, tySequence}) assert(typ.kind in {tyRef, tyString, tySequence})
# check if we have to collect: # check if we have to collect:
checkCollection() checkCollection()
res = cast[PCell](Alloc0(size + sizeof(TCell))) res = cast[PCell](Alloc0(size + sizeof(TCell)))
when stressGC: assert((cast[TAddress](res) and (MemAlignment-1)) == 0)
if res == nil: raiseOutOfMem() if res == nil: raiseOutOfMem()
when defined(nimSize): when defined(nimSize):
memUsed = memUsed + nimSize(res) memUsed = memUsed + nimSize(res)
else: else:
memUsed = memUsed + size memUsed = memUsed + size
res.refcount = 0
# now it is buffered in the ZCT # now it is buffered in the ZCT
res.typ = typ res.typ = typ
incl(ct.zct, res) # its refcount is zero, so add it to the ZCT res.refcount = -gch.zct.len
incl(ct.at, res) # add it to the any table too add(gch.zct, res) # its refcount is zero, so add it to the ZCT
ct.mask = ct.mask or cast[TAddress](res) incl(gch.at, res) # add it to the any table too
gch.mask = gch.mask or cast[TAddress](res)
when defined(debugGC): when defined(debugGC):
writeCell("new cell", res) when defined(logGC): writeCell("new cell", res)
assert(gcInvariant()) gcTrace(res, csAllocated)
result = cellToUsr(res) result = cellToUsr(res)
assert(res.typ == typ)
when stressGC: assert(checkZCT())
proc newSeq(typ: PNimType, len: int): pointer = proc newSeq(typ: PNimType, len: int): pointer =
# XXX: overflow checks! # XXX: overflow checks!
@ -665,16 +790,19 @@ proc newSeq(typ: PNimType, len: int): pointer =
proc growObj(old: pointer, newsize: int): pointer = proc growObj(old: pointer, newsize: int): pointer =
var var
res, ol: PCell res, ol: PCell
when stressGC: assert(checkZCT())
checkCollection() checkCollection()
ol = usrToCell(old) ol = usrToCell(old)
assert(ol.typ.kind in {tyString, tySequence}) assert(ol.typ.kind in {tyString, tySequence})
assert(seqCheck(ol))
when defined(nimSize): when defined(nimSize):
memUsed = memUsed - nimSize(ol) memUsed = memUsed - nimSize(ol)
else: else:
memUsed = memUsed - ol.size # this is not exact memUsed = memUsed - ol.size # this is not exact
# pity that we don't know the old size # pity that we don't know the old size
res = cast[PCell](realloc(ol, newsize + sizeof(TCell))) res = cast[PCell](realloc(ol, newsize + sizeof(TCell)))
#res = cast[PCell](gcAlloc(newsize + sizeof(TCell)))
#copyMem(res, ol, nimSize(ol))
assert((cast[TAddress](res) and (MemAlignment-1)) == 0)
when defined(nimSize): when defined(nimSize):
memUsed = memUsed + nimSize(res) memUsed = memUsed + nimSize(res)
else: else:
@ -682,74 +810,69 @@ proc growObj(old: pointer, newsize: int): pointer =
if res != ol: if res != ol:
if res == nil: raiseOutOfMem() if res == nil: raiseOutOfMem()
excl(ct.zct, ol) # remove old pointer in any case: if res.refcount <= 0:
# It may have a refcount > 0 and is still in the ZCT. assert(gch.zct.d[-res.refcount] == ol)
# So do it safe here and remove it anyway. gch.zct.d[-res.refcount] = res
excl(ct.at, ol) excl(gch.at, ol)
if res.refcount == 0: incl(gch.at, res)
# store new pointer in ZCT, if refcount == 0: gch.mask = gch.mask or cast[TAddress](res)
incl(ct.zct, res) when defined(logGC):
incl(ct.at, res)
ct.mask = ct.mask or cast[TAddress](res)
when defined(debugGC):
writeCell("growObj old cell", ol) writeCell("growObj old cell", ol)
writeCell("growObj new cell", res) writeCell("growObj new cell", res)
gcTrace(ol, csZctFreed)
gcTrace(res, csAllocated)
result = cellToUsr(res) result = cellToUsr(res)
#assert(checkRefc()) when stressGC: assert(checkZCT())
proc collectCycles() = proc collectCycles(gch: var TGcHeap) =
when defined(debugGC): when defined(logGC):
echo("collecting cycles!\n") c_fprintf(c_stdout, "collecting cycles!\n")
# step 1: pretend that any node is dead # step 1: pretend that any node is dead
for c in elements(ct.at): for c in elements(gch.at):
forallChildren(c, waCycleDecRef) forallChildren(c, waCycleDecRef)
CellSetInit(ct.newAt) CellSetInit(gch.newAt)
# step 2: restore life cells # step 2: restore life cells
for c in elements(ct.at): for c in elements(gch.at):
if c.refcount > 0: restore(c) if c.refcount > 0: restore(c)
# step 3: free dead cells: # step 3: free dead cells:
for cell in elements(ct.at): for cell in elements(gch.at):
if cell.refcount == 0: if cell.refcount == 0:
assert(cell notin ct.zct)
# We free an object that is part of a cycle here. Its children # We free an object that is part of a cycle here. Its children
# may have been freed already. Thus the finalizer could access # may have been freed already. Thus the finalizer could access
# garbage. To handle this case properly we need two passes for # garbage. To handle this case properly we need two passes for
# freeing here which is too expensive. We just don't call the # freeing here which is too expensive. We just don't call the
# finalizer for now. YYY: Any better ideas? # finalizer for now. YYY: Any better ideas?
prepareDealloc(cell) prepareDealloc(cell)
dealloc(cell) gcTrace(cell, csCycFreed)
when defined(debugGC): when defined(logGC):
writeCell("cycle collector dealloc cell", cell) writeCell("cycle collector dealloc cell", cell)
CellSetDeinit(ct.at) when reallyDealloc: dealloc(cell)
ct.at = ct.newAt CellSetDeinit(gch.at)
#ct.newAt = nil gch.at = gch.newAt
proc gcMark(p: pointer) = proc gcMark(gch: var TGcHeap, p: pointer) =
# the addresses are not as objects on the stack, so turn them to objects: # the addresses are not as objects on the stack, so turn them to objects:
var cell = usrToCell(p) var cell = usrToCell(p)
var c = cast[TAddress](cell) var c = cast[TAddress](cell)
if ((c and ct.mask) == c) and cell in ct.at: if ((c and gch.mask) == c) and cell in gch.at:
# is the page that p "points to" in the AT? (All allocated pages are # is the page that p "points to" in the AT? (All allocated pages are
# always in the AT) # always in the AT)
inc(cell.refcount) incRef(cell)
inc(cell.stackcount) when stressGC: inc(cell.stackcount)
addStackCell(ct, cell) add(gch.stackCells, cell)
proc unmarkStackAndRegisters() = proc unmarkStackAndRegisters(gch: var TGcHeap) =
for i in 0 .. ct.stackLen-1: when stressGC: assert(checkZCT())
var cell = ct.stackCells[i] for i in 0 .. gch.stackCells.len-1:
var cell = gch.stackCells.d[i]
assert(cell.refcount > 0) assert(cell.refcount > 0)
when defined(debugGC): when stressGC:
if cell.stackcount == 0:
writeGraph()
writePtr("broken stackcount", cellToUsr(cell))
assert(cell.stackcount > 0) assert(cell.stackcount > 0)
dec(cell.refcount)
dec(cell.stackcount) dec(cell.stackcount)
if cell.refcount == 0: decRef(cell)
incl(ct.zct, cell) gch.stackCells.len = 0 # reset to zero
ct.stackLen = 0 # reset to zero when stressGC: assert(checkZCT())
# ----------------- stack management -------------------------------------- # ----------------- stack management --------------------------------------
# inspired from Smart Eiffel (c) # inspired from Smart Eiffel (c)
@ -765,7 +888,7 @@ when defined(sparc): # For SPARC architecture.
stackTop: array[0..1, pointer] stackTop: array[0..1, pointer]
result = p >= addr(stackTop[0]) and p <= stackBottom result = p >= addr(stackTop[0]) and p <= stackBottom
proc markStackAndRegisters() = proc markStackAndRegisters(gch: var TGcHeap) =
when defined(sparcv9): when defined(sparcv9):
asm " flushw" asm " flushw"
else: else:
@ -780,7 +903,7 @@ when defined(sparc): # For SPARC architecture.
sp = addr(stackTop[0]) sp = addr(stackTop[0])
# Addresses decrease as the stack grows. # Addresses decrease as the stack grows.
while sp <= max: while sp <= max:
gcMark(sp^) gcMark(gch, sp^)
sp = cast[ppointer](cast[TAddress](sp) +% sizeof(pointer)) sp = cast[ppointer](cast[TAddress](sp) +% sizeof(pointer))
elif defined(ELATE): elif defined(ELATE):
@ -802,7 +925,7 @@ elif defined(hppa) or defined(hp9000) or defined(hp9000s300) or
# a little hack to get the size of a TJmpBuf in the generated C code # a little hack to get the size of a TJmpBuf in the generated C code
# in a platform independant way # in a platform independant way
proc markStackAndRegisters() = proc markStackAndRegisters(gch: var TGcHeap) =
var var
max = stackBottom max = stackBottom
registers: C_JmpBuf # The jmp_buf buffer is in the C stack. registers: C_JmpBuf # The jmp_buf buffer is in the C stack.
@ -814,7 +937,7 @@ elif defined(hppa) or defined(hp9000) or defined(hp9000s300) or
# sp will traverse the JMP_BUF as well (jmp_buf size is added, # sp will traverse the JMP_BUF as well (jmp_buf size is added,
# otherwise sp would be below the registers structure). # otherwise sp would be below the registers structure).
while sp >= max: while sp >= max:
gcMark(sp^) gcMark(gch, sp^)
sp = cast[ppointer](cast[TAddress](sp) -% sizeof(pointer)) sp = cast[ppointer](cast[TAddress](sp) -% sizeof(pointer))
else: else:
@ -826,7 +949,7 @@ else:
stackTop: array [0..1, pointer] stackTop: array [0..1, pointer]
result = p >= addr(stackTop[0]) and p <= stackBottom result = p >= addr(stackTop[0]) and p <= stackBottom
proc markStackAndRegisters() = proc markStackAndRegisters(gch: var TGcHeap) =
var var
max = stackBottom max = stackBottom
registers: C_JmpBuf # The jmp_buf buffer is in the C stack. registers: C_JmpBuf # The jmp_buf buffer is in the C stack.
@ -835,63 +958,58 @@ else:
c_setjmp(registers) # To fill the C stack with registers. c_setjmp(registers) # To fill the C stack with registers.
sp = cast[ppointer](addr(registers)) sp = cast[ppointer](addr(registers))
while sp <= max: while sp <= max:
gcMark(sp^) gcMark(gch, sp^)
sp = cast[ppointer](cast[TAddress](sp) +% sizeof(pointer)) sp = cast[ppointer](cast[TAddress](sp) +% sizeof(pointer))
# ---------------------------------------------------------------------------- # ----------------------------------------------------------------------------
# end of non-portable code # end of non-portable code
# ---------------------------------------------------------------------------- # ----------------------------------------------------------------------------
proc CollectZCT = proc CollectZCT(gch: var TGcHeap) =
CellSetInit(ct.newZCT) while gch.zct.len > 0:
for c in elements(ct.zct): var c = gch.zct.d[0]
if c.refcount == 0: assert(c.refcount <= 0)
# if != 0 the reference count has been increased, so this does not # remove from ZCT:
# belong to the ZCT. We simply do nothing - it won't appear in the newZCT gch.zct.d[0] = gch.zct.d[gch.zct.len-1]
# anyway. gch.zct.d[0].refcount = 0
dec(gch.zct.len)
# We are about to free the object, call the finalizer BEFORE its # We are about to free the object, call the finalizer BEFORE its
# children are deleted as well, because otherwise the finalizer may # children are deleted as well, because otherwise the finalizer may
# access invalid memory. This is done by prepareDealloc(): # access invalid memory. This is done by prepareDealloc():
gcTrace(c, csZctFreed)
prepareDealloc(c) prepareDealloc(c)
forAllChildren(c, waZctDecRef) forAllChildren(c, waZctDecRef)
assert(c.refcount == 0) # should still be zero excl(gch.at, c)
excl(ct.at, c) when defined(logGC):
excl(ct.newZCT, c) # BUGFIX
when defined(debugGC):
writeCell("zct dealloc cell", c) writeCell("zct dealloc cell", c)
dealloc(c) #when defined(debugGC) and defined(nimSize): zeroMem(c, nimSize(c))
CellSetDeinit(ct.zct) when reallyDealloc: dealloc(c)
ct.zct = ct.newZCT
#ct.newZCT = nil
proc collectCT(ct: var TCountTables) = proc collectCT(gch: var TGcHeap) =
when defined(debugGC): when defined(logGC):
c_fprintf(c_stdout, "collecting zero count table; stack size: %ld\n", c_fprintf(c_stdout, "collecting zero count table; stack size: %ld\n",
stackSize()) stackSize())
markStackAndRegisters() when stressGC: assert(checkZCT())
assert(GC_invariant()) if gch.zct.len >= ZctThreshold or memUsed >= cycleThreshold or stressGC:
while True: markStackAndRegisters(gch)
collectZCT() when stressGC: assert(GC_invariant())
if ct.zct.counter == 0: break collectZCT(gch)
# ``counter`` counts the pages, but zero pages means zero cells when stressGC: assert(GC_invariant())
assert(gch.zct.len == 0)
when defined(cycleGC): when defined(cycleGC):
# still over the cycle threshold?
if memUsed >= cycleThreshold or stressGC: if memUsed >= cycleThreshold or stressGC:
# collect the cyclic things: when defined(logGC):
assert(ct.zct.counter == 0) c_fprintf(c_stdout, "collecting cycles; memory used: %ld\n", memUsed)
assert(GC_invariant()) collectCycles(gch)
collectCycles() cycleThreshold = max(InitialCycleThreshold, memUsed * cycleIncrease)
when defined(logGC):
# recompute the thresholds: c_fprintf(c_stdout, "now used: %ld; threshold: %ld\n",
rcThreshold = (memUsed div RC_increase + 1) * RC_Increase memUsed, cycleThreshold)
cycleThreshold = memUsed * cycleIncrease unmarkStackAndRegisters(gch)
when stressGC: assert(GC_invariant())
assert(GC_invariant())
unmarkStackAndRegisters()
proc GC_fullCollect() = proc GC_fullCollect() =
var oldThreshold = cycleThreshold var oldThreshold = cycleThreshold
cycleThreshold = 0 # forces cycle collection cycleThreshold = 0 # forces cycle collection
collectCT(ct) collectCT(gch)
cycleThreshold = oldThreshold cycleThreshold = oldThreshold

View file

@ -10,29 +10,38 @@
type # This should be he same as ast.TTypeKind type # This should be he same as ast.TTypeKind
# some enum fields are not used at runtime # some enum fields are not used at runtime
TNimKind = enum TNimKind = enum
tyNone, tyBool, tyChar, tyNone, # 0
tyEmptySet, tyArrayConstr, tyNil, tyRecordConstr, tyBool, # 1
tyGeneric, tyChar, # 2
tyGenericInst, tyEmptySet, # 3
tyGenericParam, tyArrayConstr, # 4
tyEnum, tyAnyEnum, tyNil, # 5
tyArray, tyGeneric, # 6
tyRecord, tyGenericInst, # 7
tyObject, tyGenericParam, # 8
tyTuple, tyEnum, # 9
tySet, tyAnyEnum, # 10
tyRange, tyArray, # 11
tyPtr, tyRef, tyObject, # 12
tyVar, tyTuple, # 13
tySequence, tySet, # 14
tyProc, tyRange, # 15
tyPointer, tyOpenArray, tyPtr, # 16
tyString, tyCString, tyForward, tyRef, # 17
tyVar, # 18
tySequence, # 19
tyProc, # 20
tyPointer, # 21
tyOpenArray, # 22
tyString, # 23
tyCString, # 24
tyForward, # 25
tyInt, tyInt8, tyInt16, tyInt32, tyInt64, tyInt, tyInt8, tyInt16, tyInt32, tyInt64,
tyFloat, tyFloat32, tyFloat64, tyFloat128 tyFloat, tyFloat32, tyFloat64, tyFloat128,
tyPureObject # 35: signals that object has no `n_type` field
TNimNodeKind = enum nkNone, nkSlot, nkList, nkCase TNimNodeKind = enum nkNone, nkSlot, nkList, nkCase
TNimNode {.compilerproc.} = record TNimNode {.compilerproc, final.} = object
kind: TNimNodeKind kind: TNimNodeKind
offset: int offset: int
typ: ptr TNimType typ: ptr TNimType
@ -40,7 +49,7 @@ type # This should be he same as ast.TTypeKind
len: int len: int
sons: ptr array [0..0x7fff, ptr TNimNode] sons: ptr array [0..0x7fff, ptr TNimNode]
TNimType {.compilerproc.} = record TNimType {.compilerproc, final.} = object
size: int size: int
kind: TNimKind kind: TNimKind
base: ptr TNimType base: ptr TNimType

View file

@ -10,8 +10,7 @@
# 64 bit integers for platforms that don't have those # 64 bit integers for platforms that don't have those
type type
IInt64 = record # "internal" int64 IInt64 = tuple[lo, hi: int32]
lo, hi: int32
proc cmpI64(x, y: IInt64): int32 {.compilerproc.} = proc cmpI64(x, y: IInt64): int32 {.compilerproc.} =
result = x.hi -% y.hi result = x.hi -% y.hi

View file

@ -1,75 +1,22 @@
# #
# #
# Nimrod's Runtime Library # Nimrod's Runtime Library
# (c) Copyright 2006 Andreas Rumpf # (c) Copyright 2008 Andreas Rumpf
# #
# See the file "copying.txt", included in this # See the file "copying.txt", included in this
# distribution, for details about the copyright. # distribution, for details about the copyright.
# #
## Basic math routines for Nimrod.
## This module is available for the ECMAScript target.
# math routines
# interface
{.push debugger:off .} # the user does not want to trace a part {.push debugger:off .} # the user does not want to trace a part
# of the standard library! # of the standard library!
{.push checks:off, line_dir:off, stack_trace:off.} {.push checks:off, line_dir:off, stack_trace:off.}
proc nextPowerOfTwo*(x: int): int when defined(Posix):
## returns the nearest power of two, so that {.passl: "-lm".}
## result**2 >= x > (result-1)**2.
proc isPowerOfTwo*(x: int): bool {.noSideEffect.}
## returns true, if x is a power of two, false otherwise.
## Negative numbers are not a power of two.
proc countBits*(n: int32): int {.noSideEffect.}
## counts the set bits in `n`.
proc random*(max: int): int
## returns a random number in the range 0..max-1. The sequence of
## random number is always the same, unless `randomize` is called
## which initializes the random number generator with a "random"
## number, i.e. a tickcount.
proc randomize*()
## initializes the random number generator with a "random"
## number, i.e. a tickcount.
proc sqrt*(x: float): float {.importc: "sqrt", header: "<math.h>".}
## computes the square root of `x`.
proc ln*(x: float): float {.importc: "log", header: "<math.h>".}
## computes ln(x).
proc exp*(x: float): float {.importc: "exp", header: "<math.h>".}
## computes e**x.
proc frexp*(x: float, exponent: var int): float {.
importc: "frexp", header: "<math.h>".}
## Split a number into mantissa and exponent.
## `frexp` calculates the mantissa m (a float greater than or equal to 0.5
## and less than 1) and the integer value n such that `x` (the original
## float value) equals m * 2**n. frexp stores n in `exponent` and returns
## m.
proc arccos*(x: float): float {.importc: "acos", header: "<math.h>".}
proc arcsin*(x: float): float {.importc: "asin", header: "<math.h>".}
proc arctan*(x: float): float {.importc: "atan", header: "<math.h>".}
proc arctan2*(y, x: float): float {.importc: "atan2", header: "<math.h>".}
## Calculate the arc tangent of `y` / `x`.
## `atan2` returns the arc tangent of `y` / `x`; it produces correct
## results even when the resulting angle is near pi/2 or -pi/2
## (`x` near 0).
proc cos*(x: float): float {.importc: "cos", header: "<math.h>".}
proc cosh*(x: float): float {.importc: "cosh", header: "<math.h>".}
proc hypot*(x: float): float {.importc: "hypot", header: "<math.h>".}
proc log10*(x: float): float {.importc: "log10", header: "<math.h>".}
proc sinh*(x: float): float {.importc: "sinh", header: "<math.h>".}
proc tan*(x: float): float {.importc: "tan", header: "<math.h>".}
proc tanh*(x: float): float {.importc: "tanh", header: "<math.h>".}
proc pow*(x, y: float): float {.importc: "pos", header: "<math.h>".}
## computes x to power raised of y.
type type
TFloatClass* = enum ## describes the class a floating point value belongs to. TFloatClass* = enum ## describes the class a floating point value belongs to.
@ -82,34 +29,11 @@ type
fcInf, ## value is positive infinity fcInf, ## value is positive infinity
fcNegInf ## value is negative infinity fcNegInf ## value is negative infinity
proc classify*(x: float): TFloatClass proc classify*(x: float): TFloatClass =
## classifies a floating point value. Returns `x`'s class as specified by ## classifies a floating point value. Returns `x`'s class as specified by
## `TFloatClass` ## `TFloatClass`.
# implementation # ECMAScript and most C compilers have no classify:
include cntbits
proc nextPowerOfTwo(x: int): int =
result = x - 1
when defined(cpu64):
result = result or (result shr 32)
result = result or (result shr 16)
result = result or (result shr 8)
result = result or (result shr 4)
result = result or (result shr 2)
result = result or (result shr 1)
Inc(result)
# C procs:
proc gettime(dummy: ptr cint): cint {.
importc: "time", header: "<time.h>".}
proc srand(seed: cint) {.
importc: "srand", nodecl.}
proc rand(): cint {.importc: "rand", nodecl.}
# most C compilers have no classify:
proc classify(x: float): TFloatClass =
if x == 0.0: if x == 0.0:
if 1.0/x == 1.0/0.0: if 1.0/x == 1.0/0.0:
return fcZero return fcZero
@ -122,10 +46,130 @@ proc classify(x: float): TFloatClass =
return fcNormal return fcNormal
# XXX: fcSubnormal is not detected! # XXX: fcSubnormal is not detected!
proc isPowerOfTwo*(x: int): bool {.noSideEffect.} =
## returns true, if x is a power of two, false otherwise.
## Negative numbers are not a power of two.
return (x and -x) == x
proc nextPowerOfTwo*(x: int): int =
## returns the nearest power of two, so that
## result**2 >= x > (result-1)**2.
result = x - 1
when defined(cpu64):
result = result or (result shr 32)
result = result or (result shr 16)
result = result or (result shr 8)
result = result or (result shr 4)
result = result or (result shr 2)
result = result or (result shr 1)
Inc(result)
proc countBits*(n: int32): int {.noSideEffect.}
## counts the set bits in `n`.
include cntbits
when not defined(ECMAScript):
proc random*(max: int): int
## returns a random number in the range 0..max-1. The sequence of
## random number is always the same, unless `randomize` is called
## which initializes the random number generator with a "random"
## number, i.e. a tickcount.
proc randomize*()
## initializes the random number generator with a "random"
## number, i.e. a tickcount. Note: Does nothing for the ECMAScript target,
## as ECMAScript does not support this.
proc sqrt*(x: float): float {.importc: "sqrt", header: "<math.h>".}
## computes the square root of `x`.
proc ln*(x: float): float {.importc: "log", header: "<math.h>".}
## computes ln(x).
proc log10*(x: float): float {.importc: "log10", header: "<math.h>".}
proc log2*(x: float): float = return ln(x) / ln(2.0)
proc exp*(x: float): float {.importc: "exp", header: "<math.h>".}
## computes e**x.
proc frexp*(x: float, exponent: var int): float {.
importc: "frexp", header: "<math.h>".}
## Split a number into mantissa and exponent.
## `frexp` calculates the mantissa m (a float greater than or equal to 0.5
## and less than 1) and the integer value n such that `x` (the original
## float value) equals m * 2**n. frexp stores n in `exponent` and returns
## m.
proc round*(x: float): int {.importc: "lrint", nodecl.}
## converts a float to an int by rounding.
proc arccos*(x: float): float {.importc: "acos", header: "<math.h>".}
proc arcsin*(x: float): float {.importc: "asin", header: "<math.h>".}
proc arctan*(x: float): float {.importc: "atan", header: "<math.h>".}
proc arctan2*(y, x: float): float {.importc: "atan2", header: "<math.h>".}
## Calculate the arc tangent of `y` / `x`.
## `atan2` returns the arc tangent of `y` / `x`; it produces correct
## results even when the resulting angle is near pi/2 or -pi/2
## (`x` near 0).
proc cos*(x: float): float {.importc: "cos", header: "<math.h>".}
proc cosh*(x: float): float {.importc: "cosh", header: "<math.h>".}
proc hypot*(x, y: float): float {.importc: "hypot", header: "<math.h>".}
## same as ``sqrt(x*x + y*y)``.
proc sinh*(x: float): float {.importc: "sinh", header: "<math.h>".}
proc tan*(x: float): float {.importc: "tan", header: "<math.h>".}
proc tanh*(x: float): float {.importc: "tanh", header: "<math.h>".}
proc pow*(x, y: float): float {.importc: "pow", header: "<math.h>".}
## computes x to power raised of y.
# C procs:
proc gettime(dummy: ptr cint): cint {.importc: "time", header: "<time.h>".}
proc srand(seed: cint) {.importc: "srand", nodecl.}
proc rand(): cint {.importc: "rand", nodecl.}
proc randomize() = srand(gettime(nil)) proc randomize() = srand(gettime(nil))
proc random(max: int): int = return rand() mod max proc random(max: int): int = return rand() mod max
proc isPowerOfTwo(x: int): bool = return (x and -x) == x else:
proc mathrandom(): float {.importc: "Math.random", nodecl.}
proc mathfloor(x: float): float {.importc: "Math.floor", nodecl.}
proc random*(max: int): int = return mathfloor(mathrandom() * max)
proc randomize*() = nil
proc sqrt*(x: float): float {.importc: "Math.sqrt", nodecl.}
proc ln*(x: float): float {.importc: "Math.log", nodecl.}
proc log10*(x: float): float = return ln(x) / ln(10.0)
proc log2*(x: float): float = return ln(x) / ln(2.0)
proc exp*(x: float): float {.importc: "Math.exp", nodecl.}
proc round*(x: float): int {.importc: "Math.round", nodecl.}
proc pow*(x, y: float): float {.importc: "Math.pow", nodecl.}
proc frexp*(x: float, exponent: var int): float =
if x == 0.0:
exponent = 0.0
result = 0.0
elif x < 0.0:
result = -frexp(-x, exponent)
else:
var ex = mathfloor(log2(x))
exponent = round(ex)
result = x / pow(2.0, ex)
proc arccos*(x: float): float {.importc: "Math.acos", nodecl.}
proc arcsin*(x: float): float {.importc: "Math.asin", nodecl.}
proc arctan*(x: float): float {.importc: "Math.atan", nodecl.}
proc arctan2*(y, x: float): float {.importc: "Math.atan2", nodecl.}
proc cos*(x: float): float {.importc: "Math.cos", nodecl.}
proc cosh*(x: float): float = return (exp(x)+exp(-x))*0.5
proc hypot*(x, y: float): float = return sqrt(x*x + y*y)
proc sinh*(x: float): float = return (exp(x)-exp(-x))*0.5
proc tan*(x: float): float {.importc: "Math.tan", nodecl.}
proc tanh*(x: float): float =
var y = exp(2.0*x)
return (y-1.0)/(y+1.0)
{.pop.} {.pop.}
{.pop.} {.pop.}

View file

@ -37,24 +37,24 @@ const
realFli = MaxFli - fliOffset realFli = MaxFli - fliOffset
type type
TFreePtr = record TFreePtr {.final.} = object
prev, next: PBhdr prev, next: PBhdr
Pbhdr = ptr Tbhdr Pbhdr = ptr Tbhdr
Tbhdr = record Tbhdr {.final.} = object
prevHdr: Pbhdr # this is just valid if the first bit of size is set prevHdr: Pbhdr # this is just valid if the first bit of size is set
size: int # the size is stored in bytes size: int # the size is stored in bytes
# bit 0 indicates whether the block is used and # bit 0 indicates whether the block is used and
# bit 1 allows to know whether the previous block is free # bit 1 allows to know whether the previous block is free
freePtr: TFreePtr # at this offset bhdr.buffer starts (was a union in the freePtr: TFreePtr # at this offset bhdr.buffer starts (was a union in the
# C version) # C version)
TAreaInfo = record # This structure is embedded at the beginning of each TAreaInfo {.final.} = object # This structure is embedded at the beginning
# area, giving us enough information to cope with a set # of each area, giving us enough information
# of areas # to cope with a set of areas
theEnd: Pbhdr theEnd: Pbhdr
next: PAreaInfo next: PAreaInfo
PAreaInfo = ptr TAreaInfo PAreaInfo = ptr TAreaInfo
TLSF = record TLSF {.final.} = object
tlsf_signature: int32 # the TLSF's structure signature tlsf_signature: int32 # the TLSF's structure signature
usedSize, maxSize: int usedSize, maxSize: int
areaHead: PAreaInfo # A linked list holding all the existing areas areaHead: PAreaInfo # A linked list holding all the existing areas
@ -147,6 +147,7 @@ elif defined(windows):
if result == nil: raiseOutOfMem() if result == nil: raiseOutOfMem()
else: else:
{.warning: "Generic code for allocating pages is used".}
# generic implementation relying on malloc: # generic implementation relying on malloc:
proc malloc(size: int): pointer {.nodecl, importc.} proc malloc(size: int): pointer {.nodecl, importc.}
@ -155,6 +156,124 @@ else:
result = malloc(size) result = malloc(size)
if result == nil: raiseOutOfMem() if result == nil: raiseOutOfMem()
# ---------------------------------------------------------------------------
# small fixed size allocator:
# Design: We manage pages. A page is of constant size, but not necessarily
# the OS's page size. Pages are managed in a hash table taking advantage of
# the fact that the OS is likely to give us pages with contingous numbers.
# A page contains either small fixed size objects of the same size or
# variable length objects. An object's size is always aligned at 16 byte
# boundry. Huge objects are dealt with the TLSF algorithm.
# The design supports iterating over any object in a fast way.
# A bitset contains any page that starts an allocated page. The page may be
# empty however. This bitset can be used to quickly determine if a given
# page belongs to the GC heap. The design of the memory allocator makes it
# simple to return unused pages back to the OS.
# Small bocks
# -----------
#
# If we use a list in the free object's space. Allocation and deallocation are
# O(1). Since any object is of the same size, iteration is quite efficient too.
# However, pointer detection is easy too: Just check if the type-field is nil.
# Deallocation sets it to nil.
# Algorithm:
# i = 0
# f = b.f # first free address
# while i < max:
# if a[i] == f: # not a valid block
# f = f.next # next free address
# else:
# a[i] is a valid object of size s
# inc(i)
# The zero count table is an array. Since we know that the RC is zero, we can
# use the bits for an index into this array. Thus multiple ZCT tables are not
# difficult to support and insertion and removal is O(1). We use negative
# indexes for this. This makes it even fast enough (and necessary!) to do a ZCT
# removal if the RC is incremented.
#
# Huge blocks
# -----------
#
# Huge blocks are always rounded up to a multiple of the page size. These are
# called *strides*. We also need to keep an index structure
# of (stridesize, pagelist).
#
const
MemAlign = 8
PageShift = if sizeof(int) == 4: 12 else: 13
PageSize = 1 shl PageShift
type
TFreeList {.final.} = object
next, prev: ptr TFreeList
TPageDesc {.final.} = object # the start of a stride always starts with this!
size: int # lowest bit is set, if it is a huge block
free: ptr TFreeList # only used if it manages multiple cells
snext, sprev: ptr TPageDesc # next and prev pagedescs with the same size
TCellArray {.final.} = object
i: int # length
d: ptr array [0..1000_000, TCell]
TPageManager = table[page, ptr TPageDesc]
TGcHeap {.final.} = object
# structure that manages the garbage collected heap
zct: TCellArray
stackCells: TCellArray
smallBlocks: array [PageSize div MemAlign, ptr TPageDesc]
pages: TPageManager
usedPages: TPageList
freePages: TPageList
# small blocks:
proc allocSmall(var h: TGcHeap, size: int): pointer =
var s = align(size)
var p = h.smallBlocks[s]
if p == nil or p.free == nil:
p = newSmallBlock(s, p)
h.smallBlocks[s] = p
proc decRef(cell: PCell) {.inline.} =
assert(cell in ct.AT)
assert(cell.refcount > 0) # this should be the case!
assert(seqCheck(cell))
dec(cell.refcount)
if cell.refcount == 0:
# add to zero count table:
zct.d[zct.i] = cell
cell.recfcount = -zct.i
inc(zct.i)
proc incRef(cell: PCell) {.inline.} =
assert(seqCheck(cell))
if cell.refcount < 0:
# remove from zero count table:
zct.d[-cell.refcount] = zct.d[zct.i-1]
dec(zct.i)
cell.refcount = 1
else:
inc(cell.refcount)
proc asgnRef(dest: ppointer, src: pointer) =
# the code generator calls this proc!
assert(not isOnStack(dest))
# BUGFIX: first incRef then decRef!
if src != nil: incRef(usrToCell(src))
if dest^ != nil: decRef(usrToCell(dest^))
dest^ = src
# ---------------------------------------------------------------------------- # ----------------------------------------------------------------------------
# helpers # helpers
@ -261,7 +380,7 @@ proc extractBlock(b: Pbhdr, t: var TLSF, fl, sl: int) {.inline.} =
proc insertBlock(b: Pbhdr, t: var TLSF, fl, sl: int) {.inline.} = proc insertBlock(b: Pbhdr, t: var TLSF, fl, sl: int) {.inline.} =
b.freePtr.prev = nil b.freePtr.prev = nil
b.freePtr.next = t.matrix[fl][sl] b.freePtr.next = t.matrix[fl][sl]
if t.matrix[fl][sl] != 0: if t.matrix[fl][sl] != nil:
t.matrix[fl][sl].freePtr.prev = b t.matrix[fl][sl].freePtr.prev = b
t.matrix[fl][sl] = b t.matrix[fl][sl] = b
set_bit(sl, t.slBitmap[fl]) set_bit(sl, t.slBitmap[fl])
@ -295,9 +414,6 @@ proc processArea(area: pointer, size: int): Pbhdr =
# ---------------------------------------------------------------------------- # ----------------------------------------------------------------------------
# Begin of the allocator code # Begin of the allocator code
var
mp: pointer # default memory pool.
proc initMemoryPool(memPoolSize: int, memPool: pointer): int = proc initMemoryPool(memPoolSize: int, memPool: pointer): int =
var var
t: PLSF t: PLSF
@ -307,16 +423,14 @@ proc initMemoryPool(memPoolSize: int, memPool: pointer): int =
writeToStdErr("initMemoryPool(): memory_pool invalid\n") writeToStdErr("initMemoryPool(): memory_pool invalid\n")
return -1 return -1
if (memPool and ptrMask) != 0: if (cast[TAddress](memPool) and ptrMask) != 0:
writeToStdErr("initMemoryPool(): memPool must be aligned to a word\n") writeToStdErr("initMemoryPool(): memPool must be aligned to a word\n")
return -1 return -1
t = cast[PLSF](memPool) t = cast[PLSF](memPool)
# Check if already initialised # Check if already initialised
if t.signature == tlsfSignature: if t.signature == tlsfSignature:
mp = memPool b = getNextBlock(memPool, roundupSize(sizeof(TLSF)))
b = getNextBlock(mp, roundupSize(sizeof(TLSF)))
return b.size and blockSize return b.size and blockSize
mp = memPool
zeroMem(memPool, sizeof(TLSF)) zeroMem(memPool, sizeof(TLSF))
t.signature = tlsfSignature t.signature = tlsfSignature
@ -456,7 +570,7 @@ proc freeEx(p: pointer, t: var TLSF) =
b.freePtr.prev = nil b.freePtr.prev = nil
b.freePtr.next = nil b.freePtr.next = nil
tmpB = getNextBlock(getBuffer(b), b.size and blockSize) tmpB = getNextBlock(getBuffer(b), b.size and blockSize)
if tmpB.size and freeBlock != 0: if (tmpB.size and freeBlock) != 0:
mappingInsert(tmpB.size and blockSize, fl, sl) mappingInsert(tmpB.size and blockSize, fl, sl)
extractBlock(tmpB, t, fl, sl) extractBlock(tmpB, t, fl, sl)
inc(b.size, (tmpB.size and blockSize) + bhdrOverhead) inc(b.size, (tmpB.size and blockSize) + bhdrOverhead)
@ -549,51 +663,30 @@ proc ansiCrealloc(p: pointer, newSize: int, t: var TLSF): pointer =
else: else:
result = reallocEx(p, newSize, t) result = reallocEx(p, newSize, t)
proc InitTLSF(t: var TLSF) =
var areaSize = sizeof(TLSF) + BHDR_OVERHEAD * 8 # Just a safety constant
areaSize = max(areaSize, DEFAULT_areaSize)
var area = getNewArea(areaSize)
void *tlsf_malloc(size_t size)
{
void *ret
#if USE_MMAP || USE_SBRK
if (!mp) {
size_t areaSize
void *area
areaSize = sizeof(tlsf_t) + BHDR_OVERHEAD * 8 # Just a safety constant
areaSize = (areaSize > DEFAULT_areaSize) ? areaSize : DEFAULT_areaSize
area = get_new_area(&areaSize)
if (area == ((void *) ~0))
return NULL # Not enough system memory
initMemoryPool(areaSize, area) initMemoryPool(areaSize, area)
}
#endif
TLSF_ACQUIRE_LOCK(&((tlsf_t *)mp)->lock) var
t: PLSF
b, ib: Pbhdr
ret = malloc_ex(size, mp) t = cast[PLSF](memPool)
TLSF_RELEASE_LOCK(&((tlsf_t *)mp)->lock) zeroMem(area, areaSize)
return ret t.signature = tlsfSignature
} var ib = processArea(getNextBlock(memPool, roundupSize(sizeof(TLSF))),
rounddownSize(memPoolSize - sizeof(TLSF)))
var b = getNextBlock(getBuffer(ib), ib.size and blockSize)
freeEx(getBuffer(b), t)
t.areaHead = cast[PAreaInfo](getBuffer(ib))
void tlsf_free(void *p) t.used_size = memPoolSize - (b.size and blockSize)
{ t.max_size = t.used_size
TLSF_ACQUIRE_LOCK(&((tlsf_t *)mp)->lock)
free_ex(p, mp)
TLSF_RELEASE_LOCK(&((tlsf_t *)mp)->lock)
}
void *tlsf_realloc(void *p, size_t size) # XXX
{
void *ret
#if USE_MMAP || USE_SBRK
if (!mp) {
return tlsf_malloc(size)
}
#endif
TLSF_ACQUIRE_LOCK(&((tlsf_t *)mp)->lock)
ret = realloc_ex(p, size, mp)
TLSF_RELEASE_LOCK(&((tlsf_t *)mp)->lock)
return ret
}

View file

@ -1,7 +1,7 @@
/* /*
Nimrod's Runtime Library Nimrod's Runtime Library
(c) Copyright 2006 Andreas Rumpf (c) Copyright 2008 Andreas Rumpf
See the file "copying.txt", included in this See the file "copying.txt", included in this
distribution, for details about the copyright. distribution, for details about the copyright.
@ -11,7 +11,8 @@
#define NIMBASE_H #define NIMBASE_H
/* calling convention mess ----------------------------------------------- */ /* calling convention mess ----------------------------------------------- */
#if defined(__GNUC__) || defined(__LCC__) || defined(__POCC__) #if defined(__GNUC__) || defined(__LCC__) || defined(__POCC__) \
|| defined(__TINYC__)
/* these should support C99's inline */ /* these should support C99's inline */
/* the test for __POCC__ has to come before the test for _MSC_VER, /* the test for __POCC__ has to come before the test for _MSC_VER,
because PellesC defines _MSC_VER too. This is brain-dead. */ because PellesC defines _MSC_VER too. This is brain-dead. */
@ -30,10 +31,18 @@
# define N_INLINE(rettype, name) rettype __inline name # define N_INLINE(rettype, name) rettype __inline name
#endif #endif
#if defined(_MSC_VER) #if defined(__POCC__) || defined(_MSC_VER)
# define HAVE_LRINT 1 # define HAVE_LRINT 1
#endif #endif
#if defined(__POCC__)
# define NIM_CONST /* PCC is really picky with const modifiers */
#elif defined(__cplusplus)
# define NIM_CONST /* C++ is picky with const modifiers */
#else
# define NIM_CONST const
#endif
/* --------------- how int64 constants should be declared: ----------- */ /* --------------- how int64 constants should be declared: ----------- */
#if defined(__GNUC__) || defined(__LCC__) || \ #if defined(__GNUC__) || defined(__LCC__) || \
defined(__POCC__) || defined(__DMC__) defined(__POCC__) || defined(__DMC__)
@ -136,8 +145,7 @@
** long int lrint (double x); ** long int lrint (double x);
*/ */
#if defined(__LCC__) || defined(__POCC__) \ #if defined(__LCC__) || (defined(__GNUC__) && defined(WIN32))
|| (defined(__GNUC__) && defined(WIN32))
/* Linux' GCC does not seem to have these. Why? */ /* Linux' GCC does not seem to have these. Why? */
# define HAVE_LRINT # define HAVE_LRINT
# define HAVE_LRINTF # define HAVE_LRINTF
@ -159,7 +167,7 @@
# include <math.h> # include <math.h>
#elif (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) \ #elif (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) \
&& !defined(__BORLANDC__) && !defined(__BORLANDC__) && !defined(__POCC__)
# include <math.h> # include <math.h>
@ -206,6 +214,17 @@ static N_INLINE(long int, lrintf)(float flt) {
#include <signal.h> #include <signal.h>
#include <setjmp.h> #include <setjmp.h>
#ifndef NAN
static unsigned long nimNaN[2]={0xffffffff, 0x7fffffff};
# define NAN (*(double*) nimNaN)
#endif
/*
#ifndef INF
static unsigned long nimInf[2]={0xffffffff, 0x7fffffff};
# define INF (*(double*) nimInf)
#endif */
/* compiler symbols: /* compiler symbols:
__BORLANDC__ __BORLANDC__
_MSC_VER _MSC_VER
@ -214,6 +233,7 @@ __LCC__
__GNUC__ __GNUC__
__DMC__ __DMC__
__POCC__ __POCC__
__TINYC__
*/ */
/* C99 compiler? */ /* C99 compiler? */
@ -254,46 +274,37 @@ __POCC__
#if defined(HAVE_STDINT_H) #if defined(HAVE_STDINT_H)
# include <stdint.h> # include <stdint.h>
typedef int8_t NS8; typedef int8_t NI8;
typedef int16_t NS16; typedef int16_t NI16;
typedef int32_t NS32; typedef int32_t NI32;
typedef int64_t NS64; typedef int64_t NI64;
typedef uint64_t NU64; typedef uint64_t NU64;
typedef uint8_t NU8; typedef uint8_t NU8;
typedef uint16_t NU16; typedef uint16_t NU16;
typedef uint32_t NU32; typedef uint32_t NU32;
#elif defined(__BORLANDC__) || defined(__DMC__) \ #elif defined(__BORLANDC__) || defined(__DMC__) \
|| defined(__WATCOMC__) || defined(_MSC_VER) || defined(__WATCOMC__) || defined(_MSC_VER)
typedef signed char NS8; typedef signed char NI8;
typedef signed short int NS16; typedef signed short int NI16;
typedef signed int NS32; typedef signed int NI32;
/* XXX: Float128? */ /* XXX: Float128? */
typedef unsigned char NU8; typedef unsigned char NU8;
typedef unsigned short int NU16; typedef unsigned short int NU16;
typedef unsigned __int64 NU64; typedef unsigned __int64 NU64;
typedef __int64 NS64; typedef __int64 NI64;
typedef unsigned int NU32; typedef unsigned int NU32;
#else #else
typedef signed char NS8; typedef signed char NI8;
typedef signed short int NS16; typedef signed short int NI16;
typedef signed int NS32; typedef signed int NI32;
/* XXX: Float128? */ /* XXX: Float128? */
typedef unsigned char NU8; typedef unsigned char NU8;
typedef unsigned short int NU16; typedef unsigned short int NU16;
typedef unsigned long long int NU64; typedef unsigned long long int NU64;
typedef long long int NS64; typedef long long int NI64;
typedef unsigned int NU32; typedef unsigned int NU32;
#endif #endif
#if defined(_MSC_VER) && (defined(AMD64) || defined(_M_AMD64))
/* Microsoft C is brain-dead in this case; long is still not an int64 */
typedef unsigned long long int NU;
typedef signed long long int NS;
#else
typedef unsigned long int NU; /* note: int would be wrong for AMD64 */
typedef signed long int NS;
#endif
typedef float NF32; typedef float NF32;
typedef double NF64; typedef double NF64;
typedef double NF; typedef double NF;
@ -307,13 +318,13 @@ typedef char* NCSTRING;
# define NIM_IMAN 0 # define NIM_IMAN 0
#endif #endif
static N_INLINE(NS32, float64ToInt32)(double val) { static N_INLINE(NI32, float64ToInt32)(double val) {
val = val + 68719476736.0*1.5; val = val + 68719476736.0*1.5;
/* 2^36 * 1.5, (52-_shiftamt=36) uses limited precisicion to floor */ /* 2^36 * 1.5, (52-_shiftamt=36) uses limited precisicion to floor */
return ((NS32*)&val)[NIM_IMAN] >> 16; /* 16.16 fixed point representation */ return ((NI32*)&val)[NIM_IMAN] >> 16; /* 16.16 fixed point representation */
} }
static N_INLINE(NS32, float32ToInt32)(float val) { static N_INLINE(NI32, float32ToInt32)(float val) {
return float64ToInt32((double)val); return float64ToInt32((double)val);
} }
@ -322,7 +333,7 @@ static N_INLINE(NS32, float32ToInt32)(float val) {
#define STRING_LITERAL(name, str, length) \ #define STRING_LITERAL(name, str, length) \
static const struct { \ static const struct { \
NS len, space; \ NI len, space; \
NIM_CHAR data[length + 1]; \ NIM_CHAR data[length + 1]; \
} name = {length, length, str} } name = {length, length, str}
@ -357,7 +368,7 @@ typedef struct TStringDesc* string;
/* /*
typedef struct TSafePoint TSafePoint; typedef struct TSafePoint TSafePoint;
struct TSafePoint { struct TSafePoint {
NS exc; NI exc;
NCSTRING excname; NCSTRING excname;
NCSTRING msg; NCSTRING msg;
TSafePoint* prev; TSafePoint* prev;
@ -368,19 +379,19 @@ typedef struct TFrame TFrame;
struct TFrame { struct TFrame {
TFrame* prev; TFrame* prev;
NCSTRING procname; NCSTRING procname;
NS line; NI line;
NCSTRING filename; NCSTRING filename;
NS len; NI len;
}; };
extern TFrame* volatile framePtr; extern TFrame* framePtr;
/*extern TSafePoint* volatile excHandler; */ /*extern TSafePoint* excHandler; */
#if defined(__cplusplus) #if defined(__cplusplus)
struct NimException { struct NimException {
TSafePoint sp; TSafePoint sp;
NimException(NS aExc, NCSTRING aExcname, NCSTRING aMsg) { NimException(NI aExc, NCSTRING aExcname, NCSTRING aMsg) {
sp.exc = aExc; sp.excname = aExcname; sp.msg = aMsg; sp.exc = aExc; sp.excname = aExcname; sp.msg = aMsg;
sp.prev = excHandler; sp.prev = excHandler;
excHandler = &sp; excHandler = &sp;
@ -389,13 +400,13 @@ struct NimException {
#endif #endif
typedef struct TStringDesc { typedef struct TStringDesc {
NS len; NI len;
NS space; NI space;
NIM_CHAR data[1]; /* SEQ_DECL_SIZE]; */ NIM_CHAR data[1]; /* SEQ_DECL_SIZE]; */
} TStringDesc; } TStringDesc;
typedef struct { typedef struct {
NS len, space; NI len, space;
} TGenericSeq; } TGenericSeq;
typedef TGenericSeq* PGenericSeq; typedef TGenericSeq* PGenericSeq;

View file

@ -1,39 +0,0 @@
#
#
# Nimrod's Runtime Library
# (c) Copyright 2006 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
## This module provides a command line parser.
## It supports one iterator over all command line options.
#interface
{.push debugger: off.}
import
os
proc findSep(s: string): int {.nostatic.} =
for i in 0 .. high(s)-1:
if s[i] in {'=', ':'}: return i
return high(s)+1
iterator getopt*(): tuple[string, string] =
# returns a (cmd, arg) tuple.
for k in 1 .. ParamCount():
var param = paramStr(k)
if param[0] == '-':
var j = findSep(param)
cmd = copy(param, 0, j-1)
arg = copy(param, j+1)
else:
cmd = ""
arg = param
yield cmd, arg
{.pop.}

View file

@ -1,7 +1,7 @@
# #
# #
# Nimrod's Runtime Library # Nimrod's Runtime Library
# (c) Copyright 2006 Andreas Rumpf # (c) Copyright 2008 Andreas Rumpf
# #
# See the file "copying.txt", included in this # See the file "copying.txt", included in this
# distribution, for details about the copyright. # distribution, for details about the copyright.
@ -10,7 +10,9 @@
## Basic operating system facilities like retrieving environment variables, ## Basic operating system facilities like retrieving environment variables,
## reading command line arguments, working with directories, running shell ## reading command line arguments, working with directories, running shell
## commands, etc. This module is -- like any other basic library -- ## commands, etc. This module is -- like any other basic library --
## platform independant. ## platform independant. However, the ECMAScript target is not supported,
## as there is no way to perform these operations in ECMAScript portably
## or at all.
{.push debugger:off.} {.push debugger:off.}
@ -371,8 +373,11 @@ proc UnixToNativePath(path: string): string =
# interface to C library: # interface to C library:
const
cunder = if defined(pcc): "_" else: ""
type type
TStat {.importc: "struct stat".} = record TStat {.importc: "struct " & cunder & "stat", final.} = object
st_dev: int16 st_dev: int16
st_ino: int16 st_ino: int16
st_mode: int16 st_mode: int16
@ -397,7 +402,8 @@ else:
{.error: "os library not ported to your OS. Please help!".} {.error: "os library not ported to your OS. Please help!".}
proc chdir(path: CString): cint {.importc: "chdir", header: dirHeader.} proc chdir(path: CString): cint {.
importc: cunder & "chdir", header: dirHeader.}
when defined(unix): when defined(unix):
proc mkdir(dir: CString, theAccess: cint): cint {. proc mkdir(dir: CString, theAccess: cint): cint {.
@ -412,7 +418,7 @@ elif defined(windows):
proc fullpath(buffer, file: CString, size: int): CString {. proc fullpath(buffer, file: CString, size: int): CString {.
importc: "_fullpath", header: "<stdlib.h>".} importc: "_fullpath", header: "<stdlib.h>".}
proc getcwd(buf: CString, buflen: cint): CString {. proc getcwd(buf: CString, buflen: cint): CString {.
importc: "getcwd", header: "<direct.h>".} importc: cunder & "getcwd", header: "<direct.h>".}
proc CreateDirectory(pathName: cstring, security: Pointer): cint {. proc CreateDirectory(pathName: cstring, security: Pointer): cint {.
importc: "CreateDirectory", header: "<windows.h>".} importc: "CreateDirectory", header: "<windows.h>".}
@ -421,7 +427,8 @@ else:
{.error: "os library not ported to your OS. Please help!".} {.error: "os library not ported to your OS. Please help!".}
proc rmdir(dir: CString): cint {.importc: "rmdir", header: "<time.h>".} proc rmdir(dir: CString): cint {.
importc: cunder & "rmdir", header: "<time.h>".}
# rmdir is of course in ``dirHeader``, but we check here to include # rmdir is of course in ``dirHeader``, but we check here to include
# time.h which is needed for stat(). stat() needs time.h and # time.h which is needed for stat(). stat() needs time.h and
# sys/stat.h; we workaround a C library issue here. # sys/stat.h; we workaround a C library issue here.
@ -432,17 +439,7 @@ proc free(c: cstring) {.importc: "free", nodecl.}
proc strlen(str: CString): int {.importc: "strlen", nodecl.} proc strlen(str: CString): int {.importc: "strlen", nodecl.}
proc stat(f: CString, res: var TStat): cint {. proc stat(f: CString, res: var TStat): cint {.
importc: "stat", header: "<sys/stat.h>".} importc: cunder & "stat", header: "<sys/stat.h>".}
proc sameFile*(path1, path2: string): bool =
## Returns True if both pathname arguments refer to the same file or
## directory (as indicated by device number and i-node number).
## Raises an exception if an os.stat() call on either pathname fails.
var
a, b: TStat
if stat(path1, a) < 0 or stat(path2, b) < 0:
raise newException(EOS, "stat() call failed")
return int(a.st_dev) == b.st_dev and int(a.st_ino) == b.st_ino
when defined(windows): when defined(windows):
proc getModuleFilename(handle: int32, buf: CString, size: int32): int32 {. proc getModuleFilename(handle: int32, buf: CString, size: int32): int32 {.
@ -473,6 +470,13 @@ when defined(linux) or defined(solaris) or defined(bsd):
when defined(solaris) or defined(bsd): when defined(solaris) or defined(bsd):
proc getpid(): int {.importc, header: "<unistd.h>", cdecl.} proc getpid(): int {.importc, header: "<unistd.h>", cdecl.}
elif defined(macosx):
# a really hacky solution: since we like to include 2 headers we have to
# define two procs which in reality are the same
proc getExecPath1(c: cstring, size: var int32) {.
importc: "_NSGetExecutablePath", header: "<sys/param.h>".}
proc getExecPath2(c: cstring, size: var int32): bool {.
importc: "_NSGetExecutablePath", header: "<mach-o/dyld.h>".}
proc getApplicationFilename(): string = proc getApplicationFilename(): string =
# Linux: /proc/<pid>/exe # Linux: /proc/<pid>/exe
@ -491,6 +495,12 @@ proc getApplicationFilename(): string =
result = getApplAux("/proc/" & $getpid() & "/path/a.out") result = getApplAux("/proc/" & $getpid() & "/path/a.out")
elif defined(bsd): elif defined(bsd):
result = getApplAux("/proc/" & $getpid() & "file") result = getApplAux("/proc/" & $getpid() & "file")
elif defined(macosx):
var size: int32
getExecPath1(nil, size)
result = newString(int(size))
if getExecPath2(result, size):
result = "" # error!
else: else:
# little heuristic that may work on other POSIX-like systems: # little heuristic that may work on other POSIX-like systems:
result = getEnv("_") result = getEnv("_")
@ -612,7 +622,7 @@ when defined(wcc):
proc cputenv(env: CString): cint {.importc: "putenv", header: "<process.h>".} proc cputenv(env: CString): cint {.importc: "putenv", header: "<process.h>".}
else: # is in <stdlib.h> else: # is in <stdlib.h>
proc cputenv(env: CString): cint {.importc: "putenv", noDecl.} proc cputenv(env: CString): cint {.importc: cunder & "putenv", noDecl.}
proc cgetenv(env: CString): CString {.importc: "getenv", noDecl.} proc cgetenv(env: CString): CString {.importc: "getenv", noDecl.}
@ -621,7 +631,7 @@ proc cgetenv(env: CString): CString {.importc: "getenv", noDecl.}
#int _findclose(long); #int _findclose(long);
when defined(windows): when defined(windows):
type type
TFindData {.importc: "struct _finddata_t".} = record TFindData {.importc: "struct _finddata_t", final.} = object
attrib {.importc: "attrib".}: cint attrib {.importc: "attrib".}: cint
time_create {.importc: "time_create".}: cint time_create {.importc: "time_create".}: cint
time_access {.importc: "time_access".}: cint time_access {.importc: "time_access".}: cint
@ -636,7 +646,7 @@ when defined(windows):
proc findclose(handle: cint) {.importc: "_findclose", header: "<io.h>".} proc findclose(handle: cint) {.importc: "_findclose", header: "<io.h>".}
else: else:
type type
TFindData {.importc: "glob_t".} = record TFindData {.importc: "glob_t", final.} = object
gl_pathc: int # count of paths matched by pattern gl_pathc: int # count of paths matched by pattern
gl_pathv: ptr array[0..1000_000, CString] # list of matched path names gl_pathv: ptr array[0..1000_000, CString] # list of matched path names
gl_offs: int # slots to reserve at beginning of gl_pathv gl_offs: int # slots to reserve at beginning of gl_pathv
@ -649,6 +659,30 @@ else:
proc globfree(pglob: PFindData) {. proc globfree(pglob: PFindData) {.
importc: "globfree", header: "<glob.h>".} importc: "globfree", header: "<glob.h>".}
proc sameFile*(path1, path2: string): bool =
## Returns True if both pathname arguments refer to the same file or
## directory (as indicated by device number and i-node number).
## Raises an exception if an os.stat() call on either pathname fails.
when defined(Windows):
var
a, b: TFindData
var resA = findfirst(path1, addr(a))
var resB = findfirst(path2, addr(b))
if resA != -1 and resB != -1:
result = $a.name == $b.name
else:
# work around some ``findfirst`` bugs
result = cmpPaths(path1, path2) == 0
if resA != -1: findclose(resA)
if resB != -1: findclose(resB)
else:
var
a, b: TStat
if stat(path1, a) < 0 or stat(path2, b) < 0:
result = cmpPaths(path1, path2) == 0 # be consistent with Windows
else:
result = int(a.st_dev) == b.st_dev and int(a.st_ino) == b.st_ino
proc cremove(filename: CString): cint {.importc: "remove", noDecl.} proc cremove(filename: CString): cint {.importc: "remove", noDecl.}
proc crename(oldname, newname: CString): cint {.importc: "rename", noDecl.} proc crename(oldname, newname: CString): cint {.importc: "rename", noDecl.}
@ -787,7 +821,7 @@ proc existsEnv(key: string): bool =
if cgetenv(key) != nil: return true if cgetenv(key) != nil: return true
else: return findEnvVar(key) >= 0 else: return findEnvVar(key) >= 0
iterator iterOverEnvironment*(): tuple[string, string] = iterator iterOverEnvironment*(): tuple[key, value: string] =
## Iterate over all environments varialbes. In the first component of the ## Iterate over all environments varialbes. In the first component of the
## tuple is the name of the current variable stored, in the second its value. ## tuple is the name of the current variable stored, in the second its value.
getEnvVarsC() getEnvVarsC()

View file

@ -14,7 +14,7 @@
## This is a raw POSIX interface module. It does not not provide any ## This is a raw POSIX interface module. It does not not provide any
## convenience: cstrings are used instead of proper Nimrod strings and ## convenience: cstrings are used instead of proper Nimrod strings and
## return codes indicate errors. If you want exceptions ## return codes indicate errors. If you want exceptions
## and a proper Nimrod-like interface, use the OS module. ## and a proper Nimrod-like interface, use the OS module or write a wrapper.
## Coding conventions: ## Coding conventions:
## ALL types are named the same as in the POSIX standard except that they start ## ALL types are named the same as in the POSIX standard except that they start
@ -60,7 +60,7 @@ const
STDOUT_FILENO = 1 ## File number of stdout; STDOUT_FILENO = 1 ## File number of stdout;
type type
Taiocb* {.importc: "struct aiocb", header: "<aio.h>".} = record Taiocb* {.importc: "struct aiocb", header: "<aio.h>", final.} = object
aio_fildes*: cint ## File descriptor. aio_fildes*: cint ## File descriptor.
aio_offset*: TOff ## File offset. aio_offset*: TOff ## File offset.
aio_buf*: pointer ## Location of buffer. aio_buf*: pointer ## Location of buffer.
@ -69,14 +69,14 @@ type
aio_sigevent*: TSigEvent ## Signal number and value. aio_sigevent*: TSigEvent ## Signal number and value.
aio_lio_opcode: cint ## Operation to be performed. aio_lio_opcode: cint ## Operation to be performed.
TDIR* {.importc: "DIR", header: "<dirent.h>".} = record TDIR* {.importc: "DIR", header: "<dirent.h>", final.} = object
## A type representing a directory stream. ## A type representing a directory stream.
Tdirent* {.importc: "struct dirent", header: "<dirent.h>".} = record Tdirent* {.importc: "struct dirent", header: "<dirent.h>", final.} = object
d_ino*: TIno ## File serial number. d_ino*: TIno ## File serial number.
d_name*: array [0..255, char] ## Name of entry. d_name*: array [0..255, char] ## Name of entry.
Tflock* {.importc: "flock", header: "<fcntl>".} = record Tflock* {.importc: "flock", header: "<fcntl>", final.} = object
l_type*: cshort ## Type of lock; F_RDLCK, F_WRLCK, F_UNLCK. l_type*: cshort ## Type of lock; F_RDLCK, F_WRLCK, F_UNLCK.
l_whence*: cshort ## Flag for starting offset. l_whence*: cshort ## Flag for starting offset.
l_start*: Toff ## Relative offset in bytes. l_start*: Toff ## Relative offset in bytes.
@ -84,13 +84,13 @@ type
l_pid*: TPid ## Process ID of the process holding the lock; l_pid*: TPid ## Process ID of the process holding the lock;
## returned with F_GETLK. ## returned with F_GETLK.
Tfenv* {.importc: "fenv_t", header: "<fenv.h>".} = Tfenv* {.importc: "fenv_t", header: "<fenv.h>", final.} =
record ## Represents the entire floating-point environment. The object ## Represents the entire floating-point environment. The
## floating-point environment refers collectively to any ## floating-point environment refers collectively to any
## floating-point status flags and control modes supported ## floating-point status flags and control modes supported
## by the implementation. ## by the implementation.
Tfexcept* {.importc: "fexcept_t", header: "<fenv.h>".} = Tfexcept* {.importc: "fexcept_t", header: "<fenv.h>", final.} =
record ## Represents the floating-point status flags collectively, object ## Represents the floating-point status flags collectively,
## including any status the implementation associates with the ## including any status the implementation associates with the
## flags. A floating-point status flag is a system variable ## flags. A floating-point status flag is a system variable
## whose value is set (but never cleared) when a floating-point ## whose value is set (but never cleared) when a floating-point
@ -100,25 +100,25 @@ type
## whose value may be set by the user to affect the subsequent ## whose value may be set by the user to affect the subsequent
## behavior of floating-point arithmetic. ## behavior of floating-point arithmetic.
TFTW* {.importc: "struct FTW", header: "<ftw.h>".} = record TFTW* {.importc: "struct FTW", header: "<ftw.h>", final.} = object
base*: cint base*: cint
level*: cint level*: cint
TGlob* {.importc: "glob_t", header: "<glob.h>".} = record TGlob* {.importc: "glob_t", header: "<glob.h>", final.} = object
gl_pathc*: int ## Count of paths matched by pattern. gl_pathc*: int ## Count of paths matched by pattern.
gl_pathv*: ptr cstring ## Pointer to a list of matched pathnames. gl_pathv*: ptr cstring ## Pointer to a list of matched pathnames.
gl_offs*: int ## Slots to reserve at the beginning of gl_pathv. gl_offs*: int ## Slots to reserve at the beginning of gl_pathv.
TGroup* {.importc: "struct group", header: "<grp.h>".} = record TGroup* {.importc: "struct group", header: "<grp.h>", final.} = object
gr_name*: cstring ## The name of the group. gr_name*: cstring ## The name of the group.
gr_gid*: TGid ## Numerical group ID. gr_gid*: TGid ## Numerical group ID.
gr_mem*: cstringArray ## Pointer to a null-terminated array of character gr_mem*: cstringArray ## Pointer to a null-terminated array of character
## pointers to member names. ## pointers to member names.
Ticonv* {.importc: "iconv_t", header: "<iconv.h>".} = Ticonv* {.importc: "iconv_t", header: "<iconv.h>", final.} =
record ## Identifies the conversion from one codeset to another. object ## Identifies the conversion from one codeset to another.
Tlconv* {.importc: "struct lconv", header: "<locale.h>".} = record Tlconv* {.importc: "struct lconv", header: "<locale.h>", final.} = object
currency_symbol*: cstring currency_symbol*: cstring
decimal_point*: cstring decimal_point*: cstring
frac_digits*: char frac_digits*: char
@ -144,14 +144,14 @@ type
p_sign_posn*: char p_sign_posn*: char
thousands_sep*: cstring thousands_sep*: cstring
TMqd* {.importc: "mqd_t", header: "<mqueue.h>".} = record TMqd* {.importc: "mqd_t", header: "<mqueue.h>", final.} = object
TMqAttr* {.importc: "struct mq_attr", header: "<mqueue.h>".} = record TMqAttr* {.importc: "struct mq_attr", header: "<mqueue.h>", final.} = object
mq_flags*: int ## Message queue flags. mq_flags*: int ## Message queue flags.
mq_maxmsg*: int ## Maximum number of messages. mq_maxmsg*: int ## Maximum number of messages.
mq_msgsize*: int ## Maximum message size. mq_msgsize*: int ## Maximum message size.
mq_curmsgs*: int ## Number of messages currently queued. mq_curmsgs*: int ## Number of messages currently queued.
TPasswd* {.importc: "struct passwd", header: "<pwd.h>".} = record TPasswd* {.importc: "struct passwd", header: "<pwd.h>", final.} = object
pw_name*: cstring ## User's login name. pw_name*: cstring ## User's login name.
pw_uid*: TUid ## Numerical user ID. pw_uid*: TUid ## Numerical user ID.
pw_gid*: TGid ## Numerical group ID. pw_gid*: TGid ## Numerical group ID.
@ -198,7 +198,7 @@ type
Tuid* {.importc: "uid_t", header: "<sys/types.h>".} = int Tuid* {.importc: "uid_t", header: "<sys/types.h>".} = int
Tuseconds* {.importc: "useconds_t", header: "<sys/types.h>".} = int Tuseconds* {.importc: "useconds_t", header: "<sys/types.h>".} = int
Tutsname* {.importc: "struct utsname", header: "<sys/utsname.h>".} = record Tutsname* {.importc: "struct utsname", header: "<sys/utsname.h>", final.} = object
sysname*, ## Name of this implementation of the operating system. sysname*, ## Name of this implementation of the operating system.
nodename*, ## Name of this node within the communications nodename*, ## Name of this node within the communications
## network to which this node is attached, if any. ## network to which this node is attached, if any.
@ -207,15 +207,15 @@ type
machine*: array [0..255, char] ## Name of the hardware type on which the machine*: array [0..255, char] ## Name of the hardware type on which the
## system is running. ## system is running.
TSem* {.importc: "sem_t", header: "<semaphore.h>".} = record TSem* {.importc: "sem_t", header: "<semaphore.h>", final.} = object
Tipc_perm* {.importc: "struct ipc_perm", header: "<sys/ipc.h>".} = record Tipc_perm* {.importc: "struct ipc_perm", header: "<sys/ipc.h>", final.} = object
uid*: tuid ## Owner's user ID. uid*: tuid ## Owner's user ID.
gid*: tgid ## Owner's group ID. gid*: tgid ## Owner's group ID.
cuid*: Tuid ## Creator's user ID. cuid*: Tuid ## Creator's user ID.
cgid*: Tgid ## Creator's group ID. cgid*: Tgid ## Creator's group ID.
mode*: TMode ## Read/write permission. mode*: TMode ## Read/write permission.
TStat* {.importc: "struct stat", header: "<sys/stat.h>".} = record TStat* {.importc: "struct stat", header: "<sys/stat.h>", final.} = object
st_dev*: TDev ## Device ID of device containing file. st_dev*: TDev ## Device ID of device containing file.
st_ino*: TIno ## File serial number. st_ino*: TIno ## File serial number.
st_mode*: TMode ## Mode of file (see below). st_mode*: TMode ## Mode of file (see below).
@ -239,7 +239,7 @@ type
st_blocks*: Tblkcnt ## Number of blocks allocated for this object. st_blocks*: Tblkcnt ## Number of blocks allocated for this object.
TStatvfs* {.importc: "struct statvfs", header: "<sys/statvfs.h>".} = record TStatvfs* {.importc: "struct statvfs", header: "<sys/statvfs.h>", final.} = object
f_bsize*: int ## File system block size. f_bsize*: int ## File system block size.
f_frsize*: int ## Fundamental file system block size. f_frsize*: int ## Fundamental file system block size.
f_blocks*: Tfsblkcnt ## Total number of blocks on file system in units of f_frsize. f_blocks*: Tfsblkcnt ## Total number of blocks on file system in units of f_frsize.
@ -255,10 +255,10 @@ type
f_namemax*: int ## Maximum filename length. f_namemax*: int ## Maximum filename length.
Tposix_typed_mem_info* {.importc: "struct posix_typed_mem_info", Tposix_typed_mem_info* {.importc: "struct posix_typed_mem_info",
header: "<sys/mman.h>".} = record header: "<sys/mman.h>", final.} = object
posix_tmi_length*: int posix_tmi_length*: int
Ttm* {.importc: "struct tm", header: "<time.h>".} = record Ttm* {.importc: "struct tm", header: "<time.h>", final.} = object
tm_sec*: cint ## Seconds [0,60]. tm_sec*: cint ## Seconds [0,60].
tm_min*: cint ## Minutes [0,59]. tm_min*: cint ## Minutes [0,59].
tm_hour*: cint ## Hour [0,23]. tm_hour*: cint ## Hour [0,23].
@ -268,10 +268,10 @@ type
tm_wday*: cint ## Day of week [0,6] (Sunday =0). tm_wday*: cint ## Day of week [0,6] (Sunday =0).
tm_yday*: cint ## Day of year [0,365]. tm_yday*: cint ## Day of year [0,365].
tm_isdst*: cint ## Daylight Savings flag. tm_isdst*: cint ## Daylight Savings flag.
Ttimespec* {.importc: "struct timespec", header: "<time.h>".} = record Ttimespec* {.importc: "struct timespec", header: "<time.h>", final.} = object
tv_sec*: Ttime ## Seconds. tv_sec*: Ttime ## Seconds.
tv_nsec*: int ## Nanoseconds. tv_nsec*: int ## Nanoseconds.
titimerspec* {.importc: "struct itimerspec", header: "<time.h>".} = record titimerspec* {.importc: "struct itimerspec", header: "<time.h>", final.} = object
it_interval*: ttimespec ## Timer period. it_interval*: ttimespec ## Timer period.
it_value*: ttimespec ## Timer expiration. it_value*: ttimespec ## Timer expiration.
@ -279,19 +279,19 @@ type
## Possibly volatile-qualified integer type of an object that can be ## Possibly volatile-qualified integer type of an object that can be
## accessed as an atomic entity, even in the presence of asynchronous ## accessed as an atomic entity, even in the presence of asynchronous
## interrupts. ## interrupts.
Tsigset* {.importc: "sigset_t", header: "<signal.h>".} = record Tsigset* {.importc: "sigset_t", header: "<signal.h>", final.} = object
TsigEvent* {.importc: "struct sigevent", header: "<signal.h>".} = record TsigEvent* {.importc: "struct sigevent", header: "<signal.h>", final.} = object
sigev_notify*: cint ## Notification type. sigev_notify*: cint ## Notification type.
sigev_signo*: cint ## Signal number. sigev_signo*: cint ## Signal number.
sigev_value*: Tsigval ## Signal value. sigev_value*: Tsigval ## Signal value.
sigev_notify_function*: proc (x: TSigval) {.noconv.} ## Notification function. sigev_notify_function*: proc (x: TSigval) {.noconv.} ## Notification function.
sigev_notify_attributes*: ptr Tpthreadattr ## Notification attributes. sigev_notify_attributes*: ptr Tpthreadattr ## Notification attributes.
TsigVal* {.importc: "union sigval", header: "<signal.h>".} = record TsigVal* {.importc: "union sigval", header: "<signal.h>", final.} = object
sival_ptr*: pointer ## pointer signal value; sival_ptr*: pointer ## pointer signal value;
## integer signal value not defined! ## integer signal value not defined!
TSigaction* {.importc: "struct sigaction", header: "<signal.h>".} = record TSigaction* {.importc: "struct sigaction", header: "<signal.h>", final.} = object
sa_handler*: proc (x: cint) {.noconv.} ## Pointer to a signal-catching sa_handler*: proc (x: cint) {.noconv.} ## Pointer to a signal-catching
## function or one of the macros ## function or one of the macros
## SIG_IGN or SIG_DFL. ## SIG_IGN or SIG_DFL.
@ -300,16 +300,16 @@ type
sa_flags*: cint ## Special flags. sa_flags*: cint ## Special flags.
sa_sigaction*: proc (x: cint, y: var TSigInfo, z: pointer) {.noconv.} sa_sigaction*: proc (x: cint, y: var TSigInfo, z: pointer) {.noconv.}
TStack* {.importc: "stack_t", header: "<signal.h>".} = record TStack* {.importc: "stack_t", header: "<signal.h>", final.} = object
ss_sp*: pointer ## Stack base or pointer. ss_sp*: pointer ## Stack base or pointer.
ss_size*: int ## Stack size. ss_size*: int ## Stack size.
ss_flags*: cint ## Flags. ss_flags*: cint ## Flags.
TSigStack* {.importc: "struct sigstack", header: "<signal.h>".} = record TSigStack* {.importc: "struct sigstack", header: "<signal.h>", final.} = object
ss_onstack*: cint ## Non-zero when signal stack is in use. ss_onstack*: cint ## Non-zero when signal stack is in use.
ss_sp*: pointer ## Signal stack pointer. ss_sp*: pointer ## Signal stack pointer.
TsigInfo* {.importc: "siginfo_t", header: "<signal.h>".} = record TsigInfo* {.importc: "siginfo_t", header: "<signal.h>", final.} = object
si_signo*: cint ## Signal number. si_signo*: cint ## Signal number.
si_code*: cint ## Signal code. si_code*: cint ## Signal code.
si_errno*: cint ## If non-zero, an errno value associated with si_errno*: cint ## If non-zero, an errno value associated with
@ -324,7 +324,7 @@ type
Tnl_item* {.importc: "nl_item", header: "<nl_types.h>".} = cint Tnl_item* {.importc: "nl_item", header: "<nl_types.h>".} = cint
Tnl_catd* {.importc: "nl_catd", header: "<nl_types.h>".} = cint Tnl_catd* {.importc: "nl_catd", header: "<nl_types.h>".} = cint
Tsched_param* {.importc: "struct sched_param", header: "<sched.h>".} = record Tsched_param* {.importc: "struct sched_param", header: "<sched.h>", final.} = object
sched_priority*: cint sched_priority*: cint
sched_ss_low_priority*: cint ## Low scheduling priority for sched_ss_low_priority*: cint ## Low scheduling priority for
## sporadic server. ## sporadic server.
@ -334,15 +334,15 @@ type
sched_ss_max_repl*: cint ## Maximum pending replenishments for sched_ss_max_repl*: cint ## Maximum pending replenishments for
## sporadic server. ## sporadic server.
Ttimeval* {.importc: "struct timeval", header: "<sys/select.h>".} = record Ttimeval* {.importc: "struct timeval", header: "<sys/select.h>", final.} = object
tv_sec*: ttime ## Seconds. tv_sec*: ttime ## Seconds.
tv_usec*: tsuseconds ## Microseconds. tv_usec*: tsuseconds ## Microseconds.
Tfd_set* {.importc: "struct fd_set", header: "<sys/select.h>".} = record Tfd_set* {.importc: "struct fd_set", header: "<sys/select.h>", final.} = object
Tposix_spawnattr* {.importc: "posix_spawnattr_t", header: "<spawn.h>".} = cint Tposix_spawnattr* {.importc: "posix_spawnattr_t", header: "<spawn.h>".} = cint
Tposix_spawn_file_actions* {.importc: "posix_spawn_file_actions_t", header: "<spawn.h>".} = cint Tposix_spawn_file_actions* {.importc: "posix_spawn_file_actions_t", header: "<spawn.h>".} = cint
Tmcontext* {.importc: "mcontext_t", header: "<ucontext.h>".} = record Tmcontext* {.importc: "mcontext_t", header: "<ucontext.h>", final.} = object
Tucontext* {.importc: "ucontext_t", header: "<ucontext.h>".} = record Tucontext* {.importc: "ucontext_t", header: "<ucontext.h>", final.} = object
uc_link*: ptr Tucontext ## Pointer to the context that is resumed uc_link*: ptr Tucontext ## Pointer to the context that is resumed
## when this context returns. ## when this context returns.
uc_sigmask*: Tsigset ## The set of signals that are blocked when this uc_sigmask*: Tsigset ## The set of signals that are blocked when this
@ -729,7 +729,7 @@ var
GLOB_NOSORT* {.importc, header: "<glob.h>".}: cint GLOB_NOSORT* {.importc, header: "<glob.h>".}: cint
## Do not sort the pathnames returned. ## Do not sort the pathnames returned.
GLOB_ABORTED* {.importc, header: "<glob.h>".}: cint GLOB_ABORTED* {.importc, header: "<glob.h>".}: cint
## The scan was stopped because GLOB_ERR was set or (*errfunc)() ## The scan was stopped because GLOB_ERR was set or errfunc()
## returned non-zero. ## returned non-zero.
GLOB_NOMATCH* {.importc, header: "<glob.h>".}: cint GLOB_NOMATCH* {.importc, header: "<glob.h>".}: cint
## The pattern does not match any existing pathname, and GLOB_NOCHECK ## The pattern does not match any existing pathname, and GLOB_NOCHECK

View file

@ -1,7 +1,7 @@
# #
# #
# Nimrod's Runtime Library # Nimrod's Runtime Library
# (c) Copyright 2006 Andreas Rumpf # (c) Copyright 2008 Andreas Rumpf
# #
# See the file "copying.txt", included in this # See the file "copying.txt", included in this
# distribution, for details about the copyright. # distribution, for details about the copyright.

View file

@ -18,7 +18,7 @@ type
PPointer = ptr pointer PPointer = ptr pointer
TCollectorData = int TCollectorData = int
TCell = record TCell {.final.} = object
refcount: TCollectorData # the refcount and bit flags refcount: TCollectorData # the refcount and bit flags
typ: PNimType typ: PNimType
stackcount: int # stack counter for debugging stackcount: int # stack counter for debugging
@ -67,18 +67,18 @@ type
TBitIndex = range[0..UnitsPerPage-1] TBitIndex = range[0..UnitsPerPage-1]
TPageDesc = record TPageDesc {.final.} = object
next: PPageDesc # all nodes are connected with this pointer next: PPageDesc # all nodes are connected with this pointer
key: TAddress # start address at bit 0 key: TAddress # start address at bit 0
bits: array[TBitIndex, int] # a bit vector bits: array[TBitIndex, int] # a bit vector
PPageDescArray = ptr array[0..1000_000, PPageDesc] PPageDescArray = ptr array[0..1000_000, PPageDesc]
TCellSet = record TCellSet {.final.} = object
counter, max: int counter, max: int
head: PPageDesc head: PPageDesc
data: PPageDescArray data: PPageDescArray
TSetNode = record TSetNode {.final.} = object
n: array[0.. (1 shl bitsPerNode)-1, PSetNode] n: array[0.. (1 shl bitsPerNode)-1, PSetNode]
PSetNode = ptr TSetNode PSetNode = ptr TSetNode

View file

@ -81,9 +81,9 @@ proc reprSetAux(result: var string, p: pointer, typ: PNimType) =
of 1: u = ze64(cast[ptr int8](p)^) of 1: u = ze64(cast[ptr int8](p)^)
of 2: u = ze64(cast[ptr int16](p)^) of 2: u = ze64(cast[ptr int16](p)^)
of 4: u = ze64(cast[ptr int32](p)^) of 4: u = ze64(cast[ptr int32](p)^)
of 8: u = ze64(cast[ptr int64](p)^) of 8: u = cast[ptr int64](p)^
else: else:
var a = cast[pbyteArray](p)^ var a = cast[pbyteArray](p)
for i in 0 .. typ.size*8-1: for i in 0 .. typ.size*8-1:
if (a[i div 8] and (1 shl (i mod 8))) != 0: if (a[i div 8] and (1 shl (i mod 8))) != 0:
if elemCounter > 0: add result, ", " if elemCounter > 0: add result, ", "
@ -102,7 +102,7 @@ proc reprSet(p: pointer, typ: PNimType): string {.compilerproc.} =
reprSetAux(result, p, typ) reprSetAux(result, p, typ)
type type
TReprClosure = record # we cannot use a global variable here TReprClosure {.final.} = object # we cannot use a global variable here
# as this wouldn't be thread-safe # as this wouldn't be thread-safe
marked: TCellSet marked: TCellSet
recdepth: int # do not recurse endless recdepth: int # do not recurse endless
@ -189,8 +189,8 @@ proc reprAux(result: var string, p: pointer, typ: PNimType,
case typ.kind case typ.kind
of tySet: reprSetAux(result, p, typ) of tySet: reprSetAux(result, p, typ)
of tyArray: reprArray(result, p, typ, cl) of tyArray: reprArray(result, p, typ, cl)
of tyRecord: reprRecord(result, p, typ, cl) of tyTuple, tyPureObject: reprRecord(result, p, typ, cl)
of tyObject: # result = reprRecord(p, typ, cl) of tyObject:
var t = cast[ptr PNimType](p)^ var t = cast[ptr PNimType](p)^
reprRecord(result, p, t, cl) reprRecord(result, p, t, cl)
of tyRef, tyPtr: of tyRef, tyPtr:
@ -220,14 +220,28 @@ proc reprAux(result: var string, p: pointer, typ: PNimType,
add result, "(invalid data!)" add result, "(invalid data!)"
inc(cl.recdepth) inc(cl.recdepth)
proc reprOpenArray(p: pointer, length: int, elemtyp: PNimType): string {.
compilerproc.} =
var
cl: TReprClosure
initReprClosure(cl)
result = "["
var bs = elemtyp.size
for i in 0..length - 1:
if i > 0: add result, ", "
reprAux(result, cast[pointer](cast[TAddress](p) + i*bs), elemtyp, cl)
add result, "]"
deinitReprClosure(cl)
proc reprAny(p: pointer, typ: PNimType): string = proc reprAny(p: pointer, typ: PNimType): string =
var var
cl: TReprClosure cl: TReprClosure
initReprClosure(cl) initReprClosure(cl)
result = "" result = ""
if typ.kind in {tyObject, tyRecord, tyArray, tySet}: if typ.kind in {tyObject, tyPureObject, tyTuple, tyArray, tySet}:
reprAux(result, p, typ, cl) reprAux(result, p, typ, cl)
else: else:
var p = p
reprAux(result, addr(p), typ, cl) reprAux(result, addr(p), typ, cl)
add result, "\n" add result, "\n"
deinitReprClosure(cl) deinitReprClosure(cl)

View file

@ -7,10 +7,10 @@
# distribution, for details about the copyright. # distribution, for details about the copyright.
# #
## This module contains various string utility routines. ## This module contains various string utility routines.
## See the module `regexprs` for regular expression support. ## See the module `regexprs` for regular expression support.
## All the routines here are avaiable for the EMCAScript target
## too!
{.push debugger:off .} # the user does not want to trace a part {.push debugger:off .} # the user does not want to trace a part
# of the standard library! # of the standard library!
@ -153,6 +153,10 @@ proc ParseInt*(s: string): int {.noSideEffect.}
## a valid integer, `EInvalidValue` is raised. ## a valid integer, `EInvalidValue` is raised.
# XXX: make this biggestint! # XXX: make this biggestint!
proc ParseBiggestInt*(s: string): biggestInt {.noSideEffect.}
## Parses a decimal integer value contained in `s`. If `s` is not
## a valid integer, `EInvalidValue` is raised.
proc ParseFloat*(s: string): float {.noSideEffect.} proc ParseFloat*(s: string): float {.noSideEffect.}
## Parses a decimal floating point value contained in `s`. If `s` is not ## Parses a decimal floating point value contained in `s`. If `s` is not
## a valid floating point number, `EInvalidValue` is raised. ## a valid floating point number, `EInvalidValue` is raised.
@ -213,7 +217,13 @@ proc allCharsInSet*(s: string, theSet: TCharSet): bool =
if not (c in theSet): return false if not (c in theSet): return false
return true return true
proc c_strcmp(a, b: CString): int {.importc: "strcmp", nodecl.} proc quoteIfSpaceExists*(s: string): string =
## returns ``'"' & s & '"'`` if `s` contains a space and does not
## start with a quote, else returns `s`
if findSubStr(' ', s) >= 0 and s[0] != '"':
result = '"' & s & '"'
else:
result = s
proc startsWith(s, prefix: string): bool = proc startsWith(s, prefix: string): bool =
var i = 0 var i = 0
@ -306,11 +316,9 @@ proc `%`(formatstr: string, a: openarray[string]): string =
proc cmpIgnoreCase(a, b: string): int = proc cmpIgnoreCase(a, b: string): int =
# makes usage of the fact that strings are zero-terminated # makes usage of the fact that strings are zero-terminated
var
aa, bb: char
for i in 0..len(a)-1: for i in 0..len(a)-1:
aa = toLower(a[i]) var aa = toLower(a[i])
bb = toLower(b[i]) var bb = toLower(b[i])
result = ord(aa) - ord(bb) result = ord(aa) - ord(bb)
if result != 0: break if result != 0: break
@ -319,14 +327,13 @@ proc cmpIgnoreCase(a, b: string): int =
proc cmpIgnoreStyle(a, b: string): int = proc cmpIgnoreStyle(a, b: string): int =
var var
aa, bb: char
i = 0 i = 0
j = 0 j = 0
while True: while True:
while a[i] == '_': inc(i) while a[i] == '_': inc(i)
while b[j] == '_': inc(j) # BUGFIX: typo while b[j] == '_': inc(j) # BUGFIX: typo
aa = toLower(a[i]) var aa = toLower(a[i])
bb = toLower(b[j]) var bb = toLower(b[j])
result = ord(aa) - ord(bb) result = ord(aa) - ord(bb)
if result != 0 or aa == '\0': break if result != 0 or aa == '\0': break
inc(i) inc(i)
@ -475,15 +482,12 @@ proc deleteStr(s: var string, first, last: int) =
# parsing numbers: # parsing numbers:
proc sprintf(buf, frmt: CString) {.nodecl, importc: "sprintf", varargs.}
proc toHex(x: BiggestInt, len: int): string = proc toHex(x: BiggestInt, len: int): string =
const const
HexChars = "0123456789ABCDEF" HexChars = "0123456789ABCDEF"
var var
shift: BiggestInt shift: BiggestInt
result = newString(len) result = newString(len)
shift = 0
for j in countdown(len-1, 0): for j in countdown(len-1, 0):
result[j] = HexChars[toU32(x shr shift) and 0xF] result[j] = HexChars[toU32(x shr shift) and 0xF]
shift = shift + 4 shift = shift + 4
@ -497,11 +501,8 @@ proc rawParseInt(s: string, index: var int): BiggestInt =
# one more valid negative than prositive integer. Thus we perform the # one more valid negative than prositive integer. Thus we perform the
# computation as a negative number and then change the sign at the end. # computation as a negative number and then change the sign at the end.
var var
i: int i: int = index # a local i is more efficient than accessing a var parameter
sign: BiggestInt sign: BiggestInt = -1
i = index
# a local i is more efficient than accessing an in out parameter
sign = -1
if s[i] == '+': if s[i] == '+':
inc(i) inc(i)
elif s[i] == '-': elif s[i] == '-':
@ -523,9 +524,7 @@ proc rawParseInt(s: string, index: var int): BiggestInt =
proc parseInt(s: string): int = proc parseInt(s: string): int =
var var
index: int index: int = 0
res: BiggestInt
index = strStart
res = rawParseInt(s, index) res = rawParseInt(s, index)
if index == -1: if index == -1:
raise newException(EInvalidValue, "invalid integer: " & s) raise newException(EInvalidValue, "invalid integer: " & s)
@ -535,17 +534,20 @@ proc parseInt(s: string): int =
else: else:
result = int(res) # convert to smaller integer type result = int(res) # convert to smaller integer type
proc ParseBiggestInt(s: string): biggestInt =
var
index: int = 0
result = rawParseInt(s, index)
if index == -1:
raise newException(EInvalidValue, "invalid integer: " & s)
proc ParseFloat(s: string): float = proc ParseFloat(s: string): float =
var var
hd, esign, sign: float esign = 1.0
sign = 1.0
exponent, i: int exponent, i: int
flags: int flags: int
result = 0.0 result = 0.0
i = 0
exponent = 0
esign = 1.0
flags = 0
sign = 1.0
if s[i] == '+': inc(i) if s[i] == '+': inc(i)
elif s[i] == '-': elif s[i] == '-':
sign = -1.0 sign = -1.0
@ -558,7 +560,7 @@ proc ParseFloat(s: string): float =
while s[i] == '_': inc(i) while s[i] == '_': inc(i)
# Decimal? # Decimal?
if s[i] == '.': if s[i] == '.':
hd = 1.0 var hd = 1.0
inc(i) inc(i)
while s[i] in {'0'..'9'}: while s[i] in {'0'..'9'}:
# Read fractional part # Read fractional part
@ -586,7 +588,7 @@ proc ParseFloat(s: string): float =
inc(i) inc(i)
while s[i] == '_': inc(i) while s[i] == '_': inc(i)
# Calculate Exponent # Calculate Exponent
hd = 1.0 var hd = 1.0
for j in 1..exponent: for j in 1..exponent:
hd = hd * 10.0 hd = hd * 10.0
if esign > 0.0: result = result * hd if esign > 0.0: result = result * hd
@ -600,11 +602,10 @@ proc toOct*(x: BiggestInt, len: int): string =
## converts `x` into its octal representation. The resulting string is ## converts `x` into its octal representation. The resulting string is
## always `len` characters long. No leading ``0c`` prefix is generated. ## always `len` characters long. No leading ``0c`` prefix is generated.
var var
mask, shift: BiggestInt mask: BiggestInt = 7
shift: BiggestInt = 0
assert(len > 0) assert(len > 0)
result = newString(len) result = newString(len)
mask = 7
shift = 0
for j in countdown(len-1, 0): for j in countdown(len-1, 0):
result[j] = chr(int((x and mask) shr shift) + ord('0')) result[j] = chr(int((x and mask) shr shift) + ord('0'))
shift = shift + 3 shift = shift + 3
@ -614,11 +615,10 @@ proc toBin*(x: BiggestInt, len: int): string =
## converts `x` into its binary representation. The resulting string is ## converts `x` into its binary representation. The resulting string is
## always `len` characters long. No leading ``0b`` prefix is generated. ## always `len` characters long. No leading ``0b`` prefix is generated.
var var
mask, shift: BiggestInt mask: BiggestInt = 1
shift: BiggestInt = 0
assert(len > 0) assert(len > 0)
result = newString(len) result = newString(len)
mask = 1
shift = 0
for j in countdown(len-1, 0): for j in countdown(len-1, 0):
result[j] = chr(int((x and mask) shr shift) + ord('0')) result[j] = chr(int((x and mask) shr shift) + ord('0'))
shift = shift + 1 shift = shift + 1

View file

@ -33,10 +33,6 @@ var
IOFBF {.importc: "_IOFBF", nodecl.}: cint IOFBF {.importc: "_IOFBF", nodecl.}: cint
IONBF {.importc: "_IONBF", nodecl.}: cint IONBF {.importc: "_IONBF", nodecl.}: cint
# copied here to remove dependancy on strutils:
#proc toNimstr(x: Cstring, len: int): string {.
# noSideEffect, importc: "toNimStr".}
proc rawReadLine(f: TFile, result: var string) {.noStatic.} = proc rawReadLine(f: TFile, result: var string) {.noStatic.} =
# of course this could be optimized a bit; but IO is slow anyway... # of course this could be optimized a bit; but IO is slow anyway...
# and it was difficult to get this CORRECT with Ansi C's methods # and it was difficult to get this CORRECT with Ansi C's methods
@ -81,6 +77,8 @@ proc write(f: TFile, b: bool) =
else: write(f, "false") else: write(f, "false")
proc write(f: TFile, r: float) = fprintf(f, "%g", r) proc write(f: TFile, r: float) = fprintf(f, "%g", r)
proc write(f: TFile, c: Char) = putc(c, f) proc write(f: TFile, c: Char) = putc(c, f)
proc write(f: TFile, a: openArray[string]) =
for x in items(a): write(f, x)
proc EndOfFile(f: TFile): bool = proc EndOfFile(f: TFile): bool =
# do not blame me; blame the ANSI C standard this is so brain-damaged # do not blame me; blame the ANSI C standard this is so brain-damaged
@ -93,6 +91,11 @@ proc EndOfFile(f: TFile): bool =
proc writeln[Ty](f: TFile, x: Ty) = proc writeln[Ty](f: TFile, x: Ty) =
write(f, x) write(f, x)
write(f, "\n") write(f, "\n")
proc writeln[Ty](f: TFile, x: openArray[Ty]) =
write(f, x)
write(f, "\n")
proc echo[Ty](x: Ty) = writeln(stdout, x) proc echo[Ty](x: Ty) = writeln(stdout, x)
# interface to the C procs: # interface to the C procs:
@ -128,7 +131,6 @@ proc ftell(f: TFile): int {.importc: "ftell", noDecl.}
proc fwrite(buf: Pointer, size, n: int, f: TFile): int {. proc fwrite(buf: Pointer, size, n: int, f: TFile): int {.
importc: "fwrite", noDecl.} importc: "fwrite", noDecl.}
# size_t fwrite(const void *ptr, size_t size, size_t n, FILE *stream);
proc readBuffer(f: TFile, buffer: pointer, len: int): int = proc readBuffer(f: TFile, buffer: pointer, len: int): int =
result = fread(buffer, 1, len, f) result = fread(buffer, 1, len, f)
@ -140,9 +142,11 @@ proc ReadChars(f: TFile, a: var openarray[char], start, len: int): int =
result = readBuffer(f, addr(a[start]), len) result = readBuffer(f, addr(a[start]), len)
proc writeBytes(f: TFile, a: openarray[byte], start, len: int): int = proc writeBytes(f: TFile, a: openarray[byte], start, len: int): int =
result = writeBuffer(f, addr(a[start]), len) var x = cast[ptr array[0..1000_000_000, byte]](a)
result = writeBuffer(f, addr(x[start]), len)
proc writeChars(f: TFile, a: openarray[char], start, len: int): int = proc writeChars(f: TFile, a: openarray[char], start, len: int): int =
result = writeBuffer(f, addr(a[start]), len) var x = cast[ptr array[0..1000_000_000, byte]](a)
result = writeBuffer(f, addr(x[start]), len)
proc writeBuffer(f: TFile, buffer: pointer, len: int): int = proc writeBuffer(f: TFile, buffer: pointer, len: int): int =
result = fwrite(buffer, 1, len, f) result = fwrite(buffer, 1, len, f)

View file

@ -16,7 +16,7 @@
# the programmer may not want # the programmer may not want
type type
TStringDesc {.importc, nodecl.} = record TStringDesc {.importc, nodecl, final.} = object
len, space: int # len and space without counting the terminating zero len, space: int # len and space without counting the terminating zero
data: array[0..0, char] # for the '\0' character data: array[0..0, char] # for the '\0' character
@ -25,7 +25,6 @@ type
# implementation: # implementation:
proc resize(old: int): int {.inline.} = proc resize(old: int): int {.inline.} =
assert(old < 65536 * 4)
if old <= 0: return 1 if old <= 0: return 1
elif old < 65536: return old * 2 elif old < 65536: return old * 2
else: return old * 3 div 2 # for large arrays * 3/2 is better else: return old * 3 div 2 # for large arrays * 3/2 is better
@ -64,6 +63,7 @@ proc cstrToNimstr(str: CString): mstring {.compilerProc.} =
return toNimstr(str, c_strlen(str)) return toNimstr(str, c_strlen(str))
proc copyString(src: mstring): mstring {.compilerProc.} = proc copyString(src: mstring): mstring {.compilerProc.} =
if src == nil: return nil
result = rawNewString(src.space) result = rawNewString(src.space)
result.len = src.len result.len = src.len
c_memcpy(result.data, src.data, (src.len + 1) * sizeof(Char)) c_memcpy(result.data, src.data, (src.len + 1) * sizeof(Char))
@ -220,7 +220,7 @@ proc setLengthSeq(seq: PGenericSeq, elemSize, newLen: int): PGenericSeq {.
result.len = newLen result.len = newLen
# --------------- other string routines ---------------------------------- # --------------- other string routines ----------------------------------
proc `$`(x: int): string = proc nimIntToStr(x: int): string {.compilerproc.} =
result = newString(sizeof(x)*4) result = newString(sizeof(x)*4)
var i = 0 var i = 0
var y = x var y = x
@ -238,14 +238,12 @@ proc `$`(x: int): string =
for j in 0..i div 2 - 1: for j in 0..i div 2 - 1:
swap(result[j], result[i-j-1]) swap(result[j], result[i-j-1])
{.push warnings: off.} proc nimFloatToStr(x: float): string {.compilerproc.} =
proc `$`(x: float): string =
var buf: array [0..59, char] var buf: array [0..59, char]
c_sprintf(buf, "%#g", x) c_sprintf(buf, "%#g", x)
return $buf return $buf
{.pop.}
proc `$`(x: int64): string = proc nimInt64ToStr(x: int64): string {.compilerproc.} =
# we don't rely on C's runtime here as some C compiler's # we don't rely on C's runtime here as some C compiler's
# int64 support is weak # int64 support is weak
result = newString(sizeof(x)*4) result = newString(sizeof(x)*4)
@ -265,19 +263,13 @@ proc `$`(x: int64): string =
for j in 0..i div 2 - 1: for j in 0..i div 2 - 1:
swap(result[j], result[i-j-1]) swap(result[j], result[i-j-1])
proc `$`(x: bool): string = proc nimBoolToStr(x: bool): string {.compilerproc.} =
if x: result = "true" return if x: "true" else: "false"
else: result = "false"
proc `$`(x: char): string = proc nimCharToStr(x: char): string {.compilerproc.} =
result = newString(1) result = newString(1)
result[0] = x result[0] = x
proc `$`(x: string): string =
# this is useful for generic code!
return x
proc binaryStrSearch(x: openarray[string], y: string): int {.compilerproc.} = proc binaryStrSearch(x: openarray[string], y: string): int {.compilerproc.} =
var var
a = 0 a = 0

View file

@ -86,7 +86,6 @@ type
## length field. ## length field.
seq*{.magic: "Seq".}[T] ## Generic type to construct sequences. seq*{.magic: "Seq".}[T] ## Generic type to construct sequences.
set*{.magic: "Set".}[T] ## Generic type to construct bit sets. set*{.magic: "Set".}[T] ## Generic type to construct bit sets.
tuple*{.magic: "Tuple".}[T] ## Generic type to construct tuple types.
Byte* = Int8 ## this is an alias for ``int8``, that is a signed Byte* = Int8 ## this is an alias for ``int8``, that is a signed
## int 8 bits wide. ## int 8 bits wide.
@ -110,7 +109,8 @@ type
name*: cstring ## The exception's name is its Nimrod identifier. name*: cstring ## The exception's name is its Nimrod identifier.
## This field is filled automatically in the ## This field is filled automatically in the
## ``raise`` statement. ## ``raise`` statement.
msg*: cstring ## the exception's message. Not providing an msg* {.exportc: "message".}: cstring ## the exception's message. Not
## providing an
## exception message is bad style. ## exception message is bad style.
EAsynch* = object of E_Base ## Abstract exception class for EAsynch* = object of E_Base ## Abstract exception class for
@ -129,16 +129,19 @@ type
## could not be fullfilled. ## could not be fullfilled.
EArithmetic* = object of ESynch ## raised if any kind of arithmetic EArithmetic* = object of ESynch ## raised if any kind of arithmetic
## error occured. ## error occured.
EDivByZero* = object of EArithmetic ## is the exception class for integer EDivByZero* {.compilerproc.} =
## divide-by-zero errors. object of EArithmetic ## is the exception class for integer divide-by-zero
EOverflow* = object of EArithmetic ## is the exception class for integer ## errors.
## calculations whose results are too EOverflow* {.compilerproc.} =
## large to fit in the provided bits. object of EArithmetic ## is the exception class for integer calculations
## whose results are too large to fit in the
## provided bits.
EAccessViolation* = object of ESynch ## the exception class for EAccessViolation* {.compilerproc.} =
## invalid memory access errors object of ESynch ## the exception class for invalid memory access errors
EAssertionFailed* = object of ESynch ## is the exception class for Assert EAssertionFailed* {.compilerproc.} =
object of ESynch ## is the exception class for Assert
## procedures that is raised if the ## procedures that is raised if the
## assertion proves wrong ## assertion proves wrong
@ -154,6 +157,9 @@ type
EInvalidIndex* = object of ESynch ## is raised if an array index is out EInvalidIndex* = object of ESynch ## is raised if an array index is out
## of bounds. ## of bounds.
EInvalidField* = object of ESynch ## is raised if a record field is not
## accessible because its dicriminant's
## value does not fit.
EOutOfRange* = object of ESynch ## is raised if a range check error EOutOfRange* = object of ESynch ## is raised if a range check error
## occured. ## occured.
@ -164,12 +170,12 @@ type
ENoExceptionToReraise* = object of ESynch ## is raised if there is no ENoExceptionToReraise* = object of ESynch ## is raised if there is no
## exception to reraise. ## exception to reraise.
EInvalidObjectAssignment* = object of ESynch ## is raised if an object EInvalidObjectAssignment* =
## gets assigned to its object of ESynch ## is raised if an object gets assigned to its
## farther's object. ## farther's object.
EInvalidObjectConversion* = object of ESynch ## is raised if an object is EInvalidObjectConversion* =
## converted to an incompatible object of ESynch ## is raised if an object is converted to an incompatible
## object type. ## object type.
TResult* = enum Failure, Success TResult* = enum Failure, Success
@ -394,7 +400,7 @@ proc in_Operator*[T](x: set[T], y: T): bool {.magic: "InSet", noSideEffect.}
## writeln(stdout, 'b' in s) ## writeln(stdout, 'b' in s)
## ##
## If ``in`` had been declared as ``[T](elem: T, s: set[T])`` then ``T`` would ## If ``in`` had been declared as ``[T](elem: T, s: set[T])`` then ``T`` would
## have been bound to ``char``. But ``s`` is not compatible with type ## have been bound to ``char``. But ``s`` is not compatible to type
## ``set[char]``! The solution is to bind ``T`` to ``range['a'..'z']``. This ## ``set[char]``! The solution is to bind ``T`` to ``range['a'..'z']``. This
## is achieved by reversing the parameters for ``in_operator``; ``in`` then ## is achieved by reversing the parameters for ``in_operator``; ``in`` then
## passes its arguments in reverse order. ## passes its arguments in reverse order.
@ -418,25 +424,31 @@ proc cmp*(x, y: string): int {.noSideEffect.}
## Compare proc for strings. More efficient than the generic version. ## Compare proc for strings. More efficient than the generic version.
# concat operator: # concat operator:
proc `&` * (x: string, y: char): string {. proc `&` * (x: string, y: char): string {.magic: "ConStrStr", noSideEffect.}
magic: "ConStrStr", noSideEffect, returnsNew.} proc `&` * (x: char, y: char): string {.magic: "ConStrStr", noSideEffect.}
proc `&` * (x: char, y: char): string {. proc `&` * (x, y: string): string {.magic: "ConStrStr", noSideEffect.}
magic: "ConStrStr", noSideEffect, returnsNew.} proc `&` * (x: char, y: string): string {.magic: "ConStrStr", noSideEffect.}
proc `&` * (x, y: string): string {. ## is the `concatenation operator`. It concatenates `x` and `y`.
magic: "ConStrStr", noSideEffect, returnsNew.}
proc `&` * (x: char, y: string): string {.
magic: "ConStrStr", noSideEffect, returnsNew.}
## is the `concatenation operator`. It
## concatenates `x` and `y`.
proc add * (x: var string, y: char) {.magic: "AppendStrCh".} proc add * (x: var string, y: char) {.magic: "AppendStrCh".}
proc add * (x: var string, y: string) {.magic: "AppendStrStr".} proc add * (x: var string, y: string) {.magic: "AppendStrStr".}
when not defined(ECMAScript):
proc add* (x: var string, y: cstring) = proc add* (x: var string, y: cstring) =
var i = 0 var i = 0
while y[i] != '\0': while y[i] != '\0':
add(x, y[i]) add(x, y[i])
inc(i) inc(i)
else:
proc add* (x: var string, y: cstring) {.pure.} =
asm """
var len = `x`[0].length-1;
for (var i = 0; i < `y`.length; ++i) {
`x`[0][len] = `y`.charCodeAt(i);
++len;
}
`x`[0][len] = 0
"""
proc add *[T](x: var seq[T], y: T) {.magic: "AppendSeqElem".} proc add *[T](x: var seq[T], y: T) {.magic: "AppendSeqElem".}
proc add *[T](x: var seq[T], y: seq[T]) {.magic: "AppendSeqSeq".} proc add *[T](x: var seq[T], y: seq[T]) {.magic: "AppendSeqSeq".}
@ -675,20 +687,27 @@ proc swap*[T](a, b: var T) {.magic: "Swap".}
## swaps the values `a` and `b`. This is often more efficient than ## swaps the values `a` and `b`. This is often more efficient than
## ``tmp = a; a = b; b = tmp``. Particularly useful for sorting algorithms. ## ``tmp = a; a = b; b = tmp``. Particularly useful for sorting algorithms.
proc ze*(x: int8): int {.magic: "Ze", noSideEffect.} proc ze*(x: int8): int {.magic: "Ze8ToI", noSideEffect.}
## zero extends a smaller integer type to ``int``. This treats `x` as ## zero extends a smaller integer type to ``int``. This treats `x` as
## unsigned. ## unsigned.
proc ze*(x: int16): int {.magic: "Ze", noSideEffect.} proc ze*(x: int16): int {.magic: "Ze16ToI", noSideEffect.}
## zero extends a smaller integer type to ``int``. This treats `x` as ## zero extends a smaller integer type to ``int``. This treats `x` as
## unsigned. ## unsigned.
proc ze64*(x: int32): int64 {.magic: "Ze64", noSideEffect.} proc ze64*(x: int8): int64 {.magic: "Ze8ToI64", noSideEffect.}
## zero extends a smaller integer type to ``int64``. This treats `x` as ## zero extends a smaller integer type to ``int64``. This treats `x` as
## unsigned. ## unsigned.
proc ze*(x: int): int64 {.magic: "Ze", noDecl, noSideEffect.} proc ze64*(x: int16): int64 {.magic: "Ze16ToI64", noSideEffect.}
## zero extends a smaller integer type to ``int64``. This treats `x` as
## unsigned.
proc ze64*(x: int32): int64 {.magic: "Ze32ToI64", noSideEffect.}
## zero extends a smaller integer type to ``int64``. This treats `x` as
## unsigned.
proc ze64*(x: int): int64 {.magic: "ZeIToI64", noDecl, noSideEffect.}
## zero extends a smaller integer type to ``int64``. This treats `x` as ## zero extends a smaller integer type to ``int64``. This treats `x` as
## unsigned. Does nothing if the size of an ``int`` is the same as ``int64``. ## unsigned. Does nothing if the size of an ``int`` is the same as ``int64``.
## (This is the case an 64 bit processors.) ## (This is the case on 64 bit processors.)
proc toU8*(x: int): int8 {.magic: "ToU8", noSideEffect.} proc toU8*(x: int): int8 {.magic: "ToU8", noSideEffect.}
## treats `x` as unsigned and converts it to a byte by taking the last 8 bits ## treats `x` as unsigned and converts it to a byte by taking the last 8 bits
@ -749,34 +768,34 @@ template `>%` *(x, y: expr): expr = y <% x
## treats `x` and `y` as unsigned and compares them. ## treats `x` and `y` as unsigned and compares them.
## Returns true iff ``unsigned(x) > unsigned(y)``. ## Returns true iff ``unsigned(x) > unsigned(y)``.
proc `$` *(x: int): string {.noSideEffect.} proc `$` *(x: int): string {.magic: "IntToStr", noSideEffect.}
## The stingify operator for an integer argument. Returns `x` ## The stingify operator for an integer argument. Returns `x`
## converted to a decimal string. ## converted to a decimal string.
proc `$` *(x: int64): string {.noSideEffect.} proc `$` *(x: int64): string {.magic: "Int64ToStr", noSideEffect.}
## The stingify operator for an integer argument. Returns `x` ## The stingify operator for an integer argument. Returns `x`
## converted to a decimal string. ## converted to a decimal string.
proc `$` *(x: float): string {.noSideEffect.} proc `$` *(x: float): string {.magic: "FloatToStr", noSideEffect.}
## The stingify operator for a float argument. Returns `x` ## The stingify operator for a float argument. Returns `x`
## converted to a decimal string. ## converted to a decimal string.
proc `$` *(x: bool): string {.noSideEffect.} proc `$` *(x: bool): string {.magic: "BoolToStr", noSideEffect.}
## The stingify operator for a boolean argument. Returns `x` ## The stingify operator for a boolean argument. Returns `x`
## converted to the string "false" or "true". ## converted to the string "false" or "true".
proc `$` *(x: char): string {.noSideEffect.} proc `$` *(x: char): string {.magic: "CharToStr", noSideEffect.}
## The stingify operator for a character argument. Returns `x` ## The stingify operator for a character argument. Returns `x`
## converted to a string. ## converted to a string.
proc `$` *(x: Cstring): string {.noSideEffect, importc: "cstrToNimstr".} proc `$` *(x: Cstring): string {.magic: "CStrToStr", noSideEffect.}
## The stingify operator for a CString argument. Returns `x` ## The stingify operator for a CString argument. Returns `x`
## converted to a string. ## converted to a string.
proc `$` *(x: string): string {.noSideEffect.} proc `$` *(x: string): string {.magic: "StrToStr", noSideEffect.}
## The stingify operator for a string argument. Returns `x` ## The stingify operator for a string argument. Returns `x`
## as it is. This operator is useful for generic code, so ## as it is. This operator is useful for generic code, so
## that ``$expr`` works if ``expr`` is already a string. ## that ``$expr`` also works if ``expr`` is already a string.
# undocumented: # undocumented:
proc getRefcount*[T](x: ref T): int {.importc: "getRefcount".} proc getRefcount*[T](x: ref T): int {.importc: "getRefcount".}
@ -790,10 +809,12 @@ proc getCurrentExceptionMsg*(): string {.exportc.}
# new constants: # new constants:
const const
inf* = 1.0 / 0.0 inf* {.magic: "Inf".} = 0.0
## contains the IEEE floating point value of positive infinity. ## contains the IEEE floating point value of positive infinity.
nan* = 0.0 / 0.0 neginf* {.magic: "NegInf".} = 0.0
## contains the IEEE floating point value of *Not A Number*. Note ## contains the IEEE floating point value of negative infinity.
nan* {.magic: "NaN".} = 0.0
## contains an IEEE floating point value of *Not A Number*. Note
## that you cannot compare a floating point value to this value ## that you cannot compare a floating point value to this value
## and expect a reasonable result - use the `classify` procedure ## and expect a reasonable result - use the `classify` procedure
## in the module ``math`` for checking for NaN. ## in the module ``math`` for checking for NaN.
@ -885,11 +906,22 @@ iterator items*(a: cstring): char {.inline.} =
yield a[i] yield a[i]
inc(i) inc(i)
proc isNil*[T](x: seq[T]): bool {.noSideEffect, magic: "IsNil".}
proc isNil*[T](x: ref T): bool {.noSideEffect, magic: "IsNil".}
proc isNil*(x: string): bool {.noSideEffect, magic: "IsNil".}
proc isNil*[T](x: ptr T): bool {.noSideEffect, magic: "IsNil".}
proc isNil*(x: pointer): bool {.noSideEffect, magic: "IsNil".}
proc isNil*(x: cstring): bool {.noSideEffect, magic: "IsNil".}
## Fast check whether `x` is nil. This is sometimes more efficient than
## ``== nil``.
# Fixup some magic symbols here: # Fixup some magic symbols here:
{.fixup_system.} # This is an undocumented pragma that can only be used {.fixup_system.} # This is an undocumented pragma that can only be used
# once in the system module. # once in the system module.
proc `&` *[T](x, y: seq[T]): seq[T] {.noSideEffect, returnsNew.} = proc `&` *[T](x, y: seq[T]): seq[T] {.noSideEffect.} =
result = [] result = []
setLen(result, x.len + y.len) setLen(result, x.len + y.len)
for i in 0..x.len-1: for i in 0..x.len-1:
@ -897,41 +929,104 @@ proc `&` *[T](x, y: seq[T]): seq[T] {.noSideEffect, returnsNew.} =
for i in 0..y.len-1: for i in 0..y.len-1:
result[i] = y[i] result[i] = y[i]
proc `&` *[T](x: seq[T], y: T): seq[T] {.noSideEffect, returnsNew.} = proc `&` *[T](x: seq[T], y: T): seq[T] {.noSideEffect.} =
result = [] result = []
setLen(x.len + 1) setLen(x.len + 1)
for i in 0..x.len-1: for i in 0..x.len-1:
result[i] = x[i] result[i] = x[i]
result[x.len] = y result[x.len] = y
proc `&` *[T](x: T, y: seq[T]): seq[T] {.noSideEffect, returnsNew.} = proc `&` *[T](x: T, y: seq[T]): seq[T] {.noSideEffect.} =
result = [] result = []
setLen(y.len + 1) setLen(y.len + 1)
for i in 0..y.len-1: for i in 0..y.len-1:
result[i] = y[i] result[i] = y[i]
result[y.len] = x result[y.len] = x
proc `&` *[T](x, y: T): seq[T] {.noSideEffect, returnsNew.} = proc `&` *[T](x, y: T): seq[T] {.noSideEffect.} =
return [x, y] return [x, y]
when not defined(ECMAScript): # XXX make this local procs
proc seqToPtr*[T](x: seq[T]): pointer {.inline, nosideeffect.} =
result = cast[pointer](x)
else:
proc seqToPtr*[T](x: seq[T]): pointer {.pure, nosideeffect.} =
asm """return `x`"""
proc `==` *[T](x, y: seq[T]): bool {.noSideEffect.} = proc `==` *[T](x, y: seq[T]): bool {.noSideEffect.} =
## Generic equals operator for sequences: relies on a equals operator for ## Generic equals operator for sequences: relies on a equals operator for
## the element type `T`. ## the element type `T`.
if cast[pointer](x) == cast[pointer](y): if seqToPtr(x) == seqToPtr(y):
result = true result = true
elif cast[pointer](x) == nil or cast[pointer](y) == nil: elif seqToPtr(x) == nil or seqToPtr(y) == nil:
result = false result = false
elif x.len == y.len: elif x.len == y.len:
for i in 0..x.len-1: for i in 0..x.len-1:
if x[i] != y[i]: return false if x[i] != y[i]: return false
result = true result = true
# ----------------- FPU ------------------------------------------------------
#proc disableFPUExceptions*()
# disables all floating point unit exceptions
#proc enableFPUExceptions*()
# enables all floating point unit exceptions
# ----------------- GC interface ---------------------------------------------
proc GC_disable*()
## disables the GC. If called n-times, n calls to `GC_enable` are needed to
## reactivate the GC. Note that in most circumstances one should only disable
## the mark and sweep phase with `GC_disableMarkAndSweep`.
proc GC_enable*()
## enables the GC again.
proc GC_fullCollect*()
## forces a full garbage collection pass.
## Ordinary code does not need to call this.
type
TGC_Strategy* = enum ## the strategy the GC should use for the application
gcThroughput, ## optimize for throughput
gcResponsiveness, ## optimize for responsiveness (default)
gcOptimizeTime, ## optimize for speed
gcOptimizeSpace ## optimize for memory footprint
proc GC_setStrategy*(strategy: TGC_Strategy)
## tells the GC the desired strategy for the application.
proc GC_enableMarkAndSweep*()
proc GC_disableMarkAndSweep*()
## the current implementation uses a reference counting garbage collector
## with a seldomly run mark and sweep phase to free cycles. The mark and
## sweep phase may take a long time and is not needed if the application
## does not create cycles. Thus the mark and sweep phase can be deactivated
## and activated separately from the rest of the GC.
{.push checks: off, line_dir: off, debugger: off, {.push checks: off, line_dir: off, debugger: off,
assertions: on.} # obviously we cannot generate checking operations here :-) assertions: on.} # obviously we cannot generate checking operations here :-)
# because it would yield into an endless recursion # because it would yield into an endless recursion
# however, stack-traces are available for most parts # however, stack-traces are available for most parts
# of the code # of the code
proc echo*[Ty](x: Ty) {.inline.}
## equivalent to ``writeln(stdout, x); flush(stdout)``. BUT: This is
## available for the ECMAScript target too!
template newException(exceptn, message: expr): expr =
block: # open a new scope
var
e: ref exceptn
new(e)
e.msg = message
e
when not defined(EcmaScript):
include hti include hti
proc initGC() proc initGC()
@ -968,52 +1063,10 @@ when defined(windows):
when defined(endb): when defined(endb):
proc endbStep() proc endbStep()
template newException(exceptn, message: expr): expr =
block: # open a new scope
var
e: ref exceptn
new(e)
e.msg = message
e
# ----------------- GC interface ---------------------------------------------
proc GC_disable*()
## disables the GC. If called n-times, n calls to `GC_enable` are needed to
## reactivate the GC. Note that in most circumstances one should only disable
## the mark and sweep phase with `GC_disableMarkAndSweep`.
proc GC_enable*()
## enables the GC again.
proc GC_fullCollect*()
## forces a full garbage collection pass.
## Ordinary code does not need to call this.
type
TGC_Strategy* = enum ## the strategy the GC should use for the application
gcThroughput , ## optimize for throughput
gcResponsiveness, ## optimize for responsiveness (default)
gcOptimizeTime, ## optimize for speed
gcOptimizeSpace ## optimize for memory footprint
proc GC_setStrategy*(strategy: TGC_Strategy)
## tells the GC the desired strategy for the application.
proc GC_enableMarkAndSweep*()
proc GC_disableMarkAndSweep*()
## the current implementation uses a reference counting garbage collector
## with a seldomly run mark and sweep phase to free cycles. The mark and
## sweep phase may take a long time and is not needed if the application
## does not create cycles. Thus the mark and sweep phase can be deactivated
## and activated separately from the rest of the GC.
# ----------------- IO Part -------------------------------------------------- # ----------------- IO Part --------------------------------------------------
type type
CFile {.importc: "FILE", nodecl.} = record # empty record for CFile {.importc: "FILE", nodecl, final.} = object # empty record for
# data hiding # data hiding
TFile* = ptr CFile ## The type representing a file handle. TFile* = ptr CFile ## The type representing a file handle.
@ -1075,6 +1128,7 @@ proc write*(f: TFile, s: string)
proc write*(f: TFile, b: Bool) proc write*(f: TFile, b: Bool)
proc write*(f: TFile, c: char) proc write*(f: TFile, c: char)
proc write*(f: TFile, c: cstring) proc write*(f: TFile, c: cstring)
proc write*(f: TFile, a: openArray[string])
## Writes a value to the file `f`. May throw an IO exception. ## Writes a value to the file `f`. May throw an IO exception.
proc readLine*(f: TFile): string proc readLine*(f: TFile): string
@ -1084,9 +1138,12 @@ proc readLine*(f: TFile): string
## ``CRLF``. The newline character(s) are not part of the returned string. ## ``CRLF``. The newline character(s) are not part of the returned string.
proc writeln*[Ty](f: TFile, x: Ty) {.inline.} proc writeln*[Ty](f: TFile, x: Ty) {.inline.}
## writes a value `x` to `f` and then writes "\n". May throw an IO exception. ## writes a value `x` to `f` and then writes "\n".
proc echo*[Ty](x: Ty) {.inline.} ## May throw an IO exception.
## equivalent to ``writeln(stdout, x); flush(stdout)``.
proc writeln*[Ty](f: TFile, x: openArray[Ty]) {.inline.}
## writes a value `x` to `f` and then writes "\n".
## May throw an IO exception.
proc getFileSize*(f: TFile): int64 proc getFileSize*(f: TFile): int64
## retrieves the file size (in bytes) of `f`. ## retrieves the file size (in bytes) of `f`.
@ -1154,7 +1211,7 @@ include arithm
# sequence type declarations here because the GC needs them too: # sequence type declarations here because the GC needs them too:
type type
TGenericSeq {.importc, nodecl.} = record TGenericSeq {.importc, nodecl, final.} = object
len, space: int len, space: int
PGenericSeq {.importc, nodecl.} = ptr TGenericSeq PGenericSeq {.importc, nodecl.} = ptr TGenericSeq
@ -1179,6 +1236,11 @@ proc getCurrentExceptionMsg(): string =
when defined(endb): when defined(endb):
include debugger include debugger
{.pop.} # stacktrace {.pop.} # stacktrace
{.pop.} # checks
else:
include ecmasys
include macros
{.pop.} # checks
{.pop.} # hints {.pop.} # hints

View file

@ -1,7 +1,7 @@
# #
# #
# Nimrod's Runtime Library # Nimrod's Runtime Library
# (c) Copyright 2006 Andreas Rumpf # (c) Copyright 2008 Andreas Rumpf
# #
# See the file "copying.txt", included in this # See the file "copying.txt", included in this
# distribution, for details about the copyright. # distribution, for details about the copyright.
@ -9,6 +9,7 @@
## This module contains routines and types for dealing with time. ## This module contains routines and types for dealing with time.
## This module is available for the ECMAScript target.
{.push debugger:off .} # the user does not want to trace a part {.push debugger:off .} # the user does not want to trace a part
# of the standard library! # of the standard library!
@ -22,9 +23,49 @@ type
TWeekDay* = enum ## represents a weekday TWeekDay* = enum ## represents a weekday
dMon, dTue, dWed, dThu, dFri, dSat, dSun dMon, dTue, dWed, dThu, dFri, dSat, dSun
TTime* {.importc: "time_t".} = record ## abstract type that represents a time TTime* {.importc: "time_t", final.} = object ## abstract type that
## represents a time
when defined(ECMAScript):
getDay: proc (): int
getFullYear: proc (): int
getHours: proc (): int
getMilliseconds: proc (): int
getMinutes: proc (): int
getMonth: proc (): int
getSeconds: proc (): int
getTime: proc (): int
getTimezoneOffset: proc (): int
getUTCDate: proc (): int
getUTCFullYear: proc (): int
getUTCHours: proc (): int
getUTCMilliseconds: proc (): int
getUTCMinutes: proc (): int
getUTCMonth: proc (): int
getUTCSeconds: proc (): int
getYear: proc (): int
parse: proc (s: cstring): TTime
setDate: proc (x: int)
setFullYear: proc (x: int)
setHours: proc (x: int)
setMilliseconds: proc (x: int)
setMinutes: proc (x: int)
setMonth: proc (x: int)
setSeconds: proc (x: int)
setTime: proc (x: int)
setUTCDate: proc (x: int)
setUTCFullYear: proc (x: int)
setUTCHours: proc (x: int)
setUTCMilliseconds: proc (x: int)
setUTCMinutes: proc (x: int)
setUTCMonth: proc (x: int)
setUTCSeconds: proc (x: int)
setYear: proc (x: int)
toGMTString: proc (): cstring
toLocaleString: proc (): cstring
UTC: proc (): int
TTimeInfo* = record ## represents a time in different parts
TTimeInfo* = object of TObject ## represents a time in different parts
second*: range[0..61] ## The number of seconds after the minute, second*: range[0..61] ## The number of seconds after the minute,
## normally in the range 0 to 59, but can ## normally in the range 0 to 59, but can
## be up to 61 to allow for leap seconds. ## be up to 61 to allow for leap seconds.
@ -38,6 +79,7 @@ type
weekday*: TWeekDay ## The current day of the week. weekday*: TWeekDay ## The current day of the week.
yearday*: range[0..365] ## The number of days since January 1, yearday*: range[0..365] ## The number of days since January 1,
## in the range 0 to 365. ## in the range 0 to 365.
## Always 0 if the target is ECMAScript.
proc getTime*(): TTime ## gets the current calendar time proc getTime*(): TTime ## gets the current calendar time
proc getLocalTime*(t: TTime): TTimeInfo proc getLocalTime*(t: TTime): TTimeInfo
@ -54,7 +96,7 @@ proc TimeInfoToTime*(timeInfo: TTimeInfo): TTime
## them from the other information in the broken-down time structure. ## them from the other information in the broken-down time structure.
proc `$` *(timeInfo: TTimeInfo): string proc `$` *(timeInfo: TTimeInfo): string
## converts a `TTimeInfo` record to a ## converts a `TTimeInfo` object to a
## string representation. ## string representation.
proc `$` *(time: TTime): string proc `$` *(time: TTime): string
## converts a calendar time to a ## converts a calendar time to a
@ -72,11 +114,12 @@ proc `-` *(a, b: TTime): int64
proc getStartMilsecs*(): int proc getStartMilsecs*(): int
## get the miliseconds from the start of the program ## get the miliseconds from the start of the program
#implementation
when not defined(ECMAScript):
# C wrapper: # C wrapper:
type type
structTM {.importc: "struct tm".} = record structTM {.importc: "struct tm", final.} = object
second {.importc: "tm_sec".}, second {.importc: "tm_sec".},
minute {.importc: "tm_min".}, minute {.importc: "tm_min".},
hour {.importc: "tm_hour".}, hour {.importc: "tm_hour".},
@ -159,6 +202,62 @@ proc TimeInfoToTime(timeInfo: TTimeInfo): TTime =
# because the header of mktime is broken in my version of libc # because the header of mktime is broken in my version of libc
return mktime(timeInfoToTM(cTimeInfo)) return mktime(timeInfoToTM(cTimeInfo))
proc `$`(timeInfo: TTimeInfo): string =
return $asctime(timeInfoToTM(timeInfo))
proc `$`(time: TTime): string =
var a = time
return $ctime(addr(a))
else:
proc getTime(): TTime {.importc: "new Date", nodecl.}
const
weekDays: array [0..6, TWeekDay] = [
dSun, dMon, dTue, dWed, dThu, dFri, dSat]
proc getLocalTime(t: TTime): TTimeInfo =
result.second = t.getSeconds()
result.minute = t.getMinutes()
result.hour = t.getHours()
result.monthday = t.getDate()
result.month = TMonth(t.getMonth())
result.year = t.getFullYear()
result.weekday = weekDays[t.getDay()]
result.yearday = 0
proc getGMTime(t: TTime): TTimeInfo =
result.second = t.getUTCSeconds()
result.minute = t.getUTCMinutes()
result.hour = t.getUTCHours()
result.monthday = t.getUTCDate()
result.month = TMonth(t.getUTCMonth())
result.year = t.getUTCFullYear()
result.weekday = weekDays[t.getDay()]
result.yearday = 0
proc TimeInfoToTime*(timeInfo: TTimeInfo): TTime =
result = getTime()
result.setSeconds(timeInfo.second)
result.setMinutes(timeInfo.minute)
result.setHours(timeInfo.hour)
result.setMonth(ord(timeInfo.month))
result.setFullYear(timeInfo.year)
result.setDate(timeInfo.monthday)
proc `$`(timeInfo: TTimeInfo): string = return $(TimeInfoToTIme(timeInfo))
proc `$`(time: TTime): string = $time.toLocaleString()
proc `-` (a, b: TTime): int64 =
return a.getTime() - b.getTime()
var
startMilsecs = getTime()
proc getStartMilsecs(): int =
## get the miliseconds from the start of the program
return int(getTime() - startMilsecs)
proc getDateStr(): string = proc getDateStr(): string =
var ti = getLocalTime(getTime()) var ti = getLocalTime(getTime())
result = $ti.year & "-" & intToStr(ord(ti.month)+1, 2) & result = $ti.year & "-" & intToStr(ord(ti.month)+1, 2) &
@ -169,11 +268,4 @@ proc getClockStr(): string =
result = intToStr(ti.hour, 2) & ':' & intToStr(ti.minute, 2) & result = intToStr(ti.hour, 2) & ':' & intToStr(ti.minute, 2) &
':' & intToStr(ti.second, 2) ':' & intToStr(ti.second, 2)
proc `$`(timeInfo: TTimeInfo): string =
return $asctime(timeInfoToTM(timeInfo))
proc `$`(time: TTime): string =
var a = time
return $ctime(addr(a))
{.pop.} {.pop.}

View file

@ -1,221 +0,0 @@
#
#
# Nimrod's Runtime Library
# (c) Copyright 2006 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
# type-info module for Nimrod
include hti
proc typeid(x: any): PNimType
type
Variant = opaque record
# contains the address and a typeinfo
a: pointer # an address
k: TNimTypeKind
# conversions to any and from any are inserted by the compiler!
# x.attr is supported, as well as x[]!
# here is a special iterator for variants:
iterator fields(x: variant): (fieldname: string, value: variant) =
proc setField(structure: variant, fieldname: string, value: variant)
proc getField(structure: variant, fieldname: string)
# any is implemented as a pair (val: pointer, info: PTypeInfo)
# val is for:
# an array - its address
# a record - its address
# an object - its address
# a string - the address of the pointer to the string data
# a sequence - the address of the pointer to the sequence data
# a float - the address of a memory location where the float is stored
# this is a given address; storage comes from compiler or is
# already there (in a container)
# an int - the address of a memory location where the int is stored
# storage comes from compiler or is
# already there (in a container)
# a cstring - the address of an address of an array of chars
# a ref - the address of the ref! (not the ref itself!)
# But this does not work too well...
# Better: any is a ref to Object; than we define intObj, floatObj,
# etc.; for strings this not needed as they already fit into the
# scheme!
#
type
TAnyImpl {.exportc: "TAnyImpl".} = record
typ {.exportc: "info".}: PNimType
val {.exportc: "val".}: pointer
proc
typeKind(p: PNimType): TTypeKind {.inline.}
getAnyLength(x: any): int
isContainer(x: any): bool
writeAny(container: any, index: int, val: any)
readAny(container: any, index: int): any
writeAny(container: any, name: string, val: any)
readAny(container: any, name: string): any
getAttr(container: any, index: int, out name: string, out val: any)
getEnumStrings(enumeration: any): sequence of string
anyToInt(x: any): biggestint
anyToFloat(x: any): biggestfloat
anyToString(x: any): string
anyToChar(x: any): char
anyToBool(x: any): bool
#anyToT{T}(x: any, out result: T)
# etc...
#write(a: array of any) # also possible!
#generic proc
# deepCopy{T}(x: T): T
import
strutils
proc anyToImpl(a: any): TAnyImpl {.inline.} =
result = cast{TAnyImpl}(a)
proc typeKind(p: PNimType): TTypeKind =
result = p.typeKind
type
Pint = untraced ref int
Pint8 = untraced ref int8
Pint16 = untraced ref int16
Pint32 = untraced ref int32
Pint64 = untraced ref int64
Puint = untraced ref uint
Puint8 = untraced ref uint8
Puint16 = untraced ref uint16
Puint32 = untraced ref uint32
Puint64 = untraced ref uint64
Pfloat = untraced ref float
Pfloat32 = untraced ref float32
Pfloat64 = untraced ref float64
Pstring = untraced ref string
Pbool = untraced ref bool
Pchar = untraced ref char
proc anyToInt(x: any): biggestint =
var impl = anyToImpl(x)
case impl.typ.typeKind
of tyInt, tyEnum: result = cast{pint}(x.val)^
of tySInt8: result = cast{pint8}(x.val)^
of tySInt16: result = cast{pint16}(x.val)^
of tySInt32: result = cast{pint32}(x.val)^
of tySInt64: result = cast{pint64}(x.val)^
of tyUInt: result = cast{puint}(x.val)^
of tyUInt8: result = cast{puint8}(x.val)^
of tyUInt16: result = cast{puint16}(x.val)^
of tyUInt32: result = cast{puint32}(x.val)^
of tyUInt64: result = cast{puint64}(x.val)^
else: raise EConvertError
proc anyToFloat(x: any): biggestfloat =
var impl = anyToImpl(x)
case impl.typ.typeKind
of tyReal: result = cast{pfloat}(x.val)^
of tyReal32: result = cast{pfloat32}(x.val)^
of tyReal64: result = cast{pfloat64}(x.val)^
# of tyReal128:
else: raise EConvertError
proc anyToString(x: any): string =
var impl = anyToImpl(x)
case impl.typ.typeKind
of tyString: result = cast{pstring}(x.val)^
else: raise EConvertError
proc anyToChar(x: any): char =
var impl = anyToImpl(x)
case impl.typ.typeKind
of tyChar: result = cast{pchar}(x.val)^
else: raise EConvertError
proc anyToBool(x: any): bool =
var impl = anyToImpl(x)
case impl.typ.typeKind
of tyBool: result = cast{pbool}(x.val)^
else: raise EConvertError
proc getAnyLength(x: any): int =
result = anyToImpl(x).typ.len
const
ContainerSet = {tyArray, tyRecord, tyObject, tyOpenArray, tySequence, tyTable}
proc isContainer(x: any): bool =
result = anyToImpl(x).typ.typeKind in ContainerSet
proc strcmp(a, b: cstring): int {.external: "strcmp", nodecl.}
proc strToIndex(info: PTypeInfo, str: string): int =
for i in 0..typ.len-1:
if strcmp(info.slots[i].name, str) == 0:
return i
raise EConvertError
proc writeAny(container: any, index: int, val: any) =
var x = anyToImpl(container)
if index >= 0 and index < container.len:
case x.typ.typeKind
of tySequence:
var u = cast{TAddress}(x.val)
genericAssignAux(cast{pointer}(u) +% x.typ.slots[index].offset +%
GenericSeqSize,
anyToImpl(val).val, u.typ.baseType)
of tyArray:
of tyRecord, tyObject:
else: raise EConvertError
else:
raise EIndexError
proc readAny(container: any, index: int): any =
var x = anyToImpl(container)
if x.typ.typeKind in ContainerSet:
if index >= 0 and index < container.len:
# XXX
else:
raise EIndexError
else:
raise EConvertError
proc writeAny(container: any, name: string, val: any) =
result = writeAny(container, strToIndex(anyToImpl(container).typ), val)
proc readAny(container: any, name: string): any =
result = readAny(container, strToIndex(anyToImpl(container).typ))
proc getAttr(container: any, index: int, out name: string, out val: any) =
var x = anyToImpl(container)
if x.typ.typeKind in ContainerSet:
val = readAny(container, index)
name = $x.typ.slots[index].name
else:
raise EConvertError
proc getEnumStrings(enumeration: any): sequence of string =
result = []
var x = anyToImpl(enumeration)
if x.typ.typekind == tyEnum:
for i in 0 .. x.typ.len-1:
result &= $x.typ.slots[i].name
else:
raise EConvertError

View file

@ -980,7 +980,7 @@ const
#///////////////////////////////////////////////////////// #/////////////////////////////////////////////////////////
type type
mmtime* = record mmtime* {.final.} = object
wType*: UINT wType*: UINT
hour*, min*, sec*, frame*, fps*, dummy*: int8 hour*, min*, sec*, frame*, fps*, dummy*: int8
pad*: array[0..1, int8] pad*: array[0..1, int8]
@ -990,7 +990,7 @@ type
LPMMTIME* = ptr mmtime LPMMTIME* = ptr mmtime
PWAVEHDR* = ptr wavehdr PWAVEHDR* = ptr wavehdr
TMMTime* = mmtime TMMTime* = mmtime
wavehdr* = record wavehdr* {.final.} = object
lpData*: cstring lpData*: cstring
dwBufferLength*: DWORD dwBufferLength*: DWORD
dwBytesRecorded*: DWORD dwBytesRecorded*: DWORD
@ -1003,7 +1003,7 @@ type
TWAVEHDR* = WAVEHDR TWAVEHDR* = WAVEHDR
NPWAVEHDR* = ptr wavehdr NPWAVEHDR* = ptr wavehdr
LPWAVEHDR* = ptr wavehdr LPWAVEHDR* = ptr wavehdr
WAVEOUTCAPSA* = record WAVEOUTCAPSA* {.final.} = object
wMid*: int16 wMid*: int16
wPid*: int16 wPid*: int16
vDriverVersion*: MMVERSION vDriverVersion*: MMVERSION
@ -1017,7 +1017,7 @@ type
PWAVEOUTCAPSA* = ptr WAVEOUTCAPSA PWAVEOUTCAPSA* = ptr WAVEOUTCAPSA
NPWAVEOUTCAPSA* = ptr WAVEOUTCAPSA NPWAVEOUTCAPSA* = ptr WAVEOUTCAPSA
LPWAVEOUTCAPSA* = ptr WAVEOUTCAPSA LPWAVEOUTCAPSA* = ptr WAVEOUTCAPSA
WAVEOUTCAPSW* = record WAVEOUTCAPSW* {.final.} = object
wMid*: int16 wMid*: int16
wPid*: int16 wPid*: int16
vDriverVersion*: MMVERSION vDriverVersion*: MMVERSION
@ -1046,7 +1046,7 @@ else:
LPWAVEOUTCAPS* = LPWAVEOUTCAPSA LPWAVEOUTCAPS* = LPWAVEOUTCAPSA
type type
TWAVEOUTCAPS* = WAVEOUTCAPS TWAVEOUTCAPS* = WAVEOUTCAPS
WAVEINCAPSA* = record WAVEINCAPSA* {.final.} = object
wMid*: int16 wMid*: int16
wPid*: int16 wPid*: int16
vDriverVersion*: MMVERSION vDriverVersion*: MMVERSION
@ -1059,7 +1059,7 @@ type
NPWAVEINCAPSA* = ptr WAVEINCAPSA NPWAVEINCAPSA* = ptr WAVEINCAPSA
LPWAVEINCAPSA* = ptr WAVEINCAPSA LPWAVEINCAPSA* = ptr WAVEINCAPSA
TWAVEINCAPSA* = WAVEINCAPSA TWAVEINCAPSA* = WAVEINCAPSA
WAVEINCAPSW* = record WAVEINCAPSW* {.final.} = object
wMid*: int16 wMid*: int16
wPid*: int16 wPid*: int16
vDriverVersion*: MMVERSION vDriverVersion*: MMVERSION
@ -1087,7 +1087,7 @@ else:
LPWAVEINCAPS* = LPWAVEINCAPSA LPWAVEINCAPS* = LPWAVEINCAPSA
type type
TWAVEINCAPS* = WAVEINCAPS TWAVEINCAPS* = WAVEINCAPS
waveformat* = record waveformat* {.final.} = object
wFormatTag*: int16 wFormatTag*: int16
nChannels*: int16 nChannels*: int16
nSamplesPerSec*: DWORD nSamplesPerSec*: DWORD
@ -1103,7 +1103,7 @@ const
WAVE_FORMAT_PCM* = 1 WAVE_FORMAT_PCM* = 1
type type
pcmwaveformat* = record pcmwaveformat* {.final.} = object
wf*: WAVEFORMAT wf*: WAVEFORMAT
wBitsPerSample*: int16 wBitsPerSample*: int16
@ -1111,7 +1111,7 @@ type
NPPCMWAVEFORMAT* = ptr pcmwaveformat NPPCMWAVEFORMAT* = ptr pcmwaveformat
LPPCMWAVEFORMAT* = ptr pcmwaveformat LPPCMWAVEFORMAT* = ptr pcmwaveformat
TPCMWAVEFORMAT* = PCMWAVEFORMAT TPCMWAVEFORMAT* = PCMWAVEFORMAT
WAVEFORMATEX* = record WAVEFORMATEX* {.final.} = object
wFormatTag*: int16 wFormatTag*: int16
nChannels*: int16 nChannels*: int16
nSamplesPerSec*: DWORD nSamplesPerSec*: DWORD
@ -1143,7 +1143,7 @@ type
LPPATCHARRAY* = ptr int16 LPPATCHARRAY* = ptr int16
KEYARRAY* = array[0..Pred(MIDIPATCHSIZE), int16] KEYARRAY* = array[0..Pred(MIDIPATCHSIZE), int16]
LPKEYARRAY* = ptr int16 LPKEYARRAY* = ptr int16
MIDIOUTCAPSA* = record MIDIOUTCAPSA* {.final.} = object
wMid*: int16 wMid*: int16
wPid*: int16 wPid*: int16
vDriverVersion*: MMVERSION vDriverVersion*: MMVERSION
@ -1158,7 +1158,7 @@ type
NPMIDIOUTCAPSA* = ptr MIDIOUTCAPSA NPMIDIOUTCAPSA* = ptr MIDIOUTCAPSA
LPMIDIOUTCAPSA* = ptr MIDIOUTCAPSA LPMIDIOUTCAPSA* = ptr MIDIOUTCAPSA
TMIDIOUTCAPSA* = MIDIOUTCAPSA TMIDIOUTCAPSA* = MIDIOUTCAPSA
MIDIOUTCAPSW* = record MIDIOUTCAPSW* {.final.} = object
wMid*: int16 wMid*: int16
wPid*: int16 wPid*: int16
vDriverVersion*: MMVERSION vDriverVersion*: MMVERSION
@ -1173,7 +1173,7 @@ type
NPMIDIOUTCAPSW* = ptr MIDIOUTCAPSW NPMIDIOUTCAPSW* = ptr MIDIOUTCAPSW
LPMIDIOUTCAPSW* = ptr MIDIOUTCAPSW LPMIDIOUTCAPSW* = ptr MIDIOUTCAPSW
TMIDIOUTCAPSW* = MIDIOUTCAPSW TMIDIOUTCAPSW* = MIDIOUTCAPSW
MIDIINCAPSA* = record MIDIINCAPSA* {.final.} = object
wMid*: int16 wMid*: int16
wPid*: int16 wPid*: int16
vDriverVersion*: MMVERSION vDriverVersion*: MMVERSION
@ -1184,7 +1184,7 @@ type
NPMIDIINCAPSA* = ptr MIDIINCAPSA NPMIDIINCAPSA* = ptr MIDIINCAPSA
LPMIDIINCAPSA* = ptr MIDIINCAPSA LPMIDIINCAPSA* = ptr MIDIINCAPSA
TMIDIINCAPSA* = MIDIINCAPSA TMIDIINCAPSA* = MIDIINCAPSA
MIDIINCAPSW* = record MIDIINCAPSW* {.final.} = object
wMid*: int16 wMid*: int16
wPid*: int16 wPid*: int16
vDriverVersion*: MMVERSION vDriverVersion*: MMVERSION
@ -1219,7 +1219,7 @@ else:
type type
TMIDIINCAPS* = MIDIINCAPS TMIDIINCAPS* = MIDIINCAPS
PMIDIHDR* = ptr midihdr PMIDIHDR* = ptr midihdr
midihdr* = record midihdr* {.final.} = object
lpData*: cstring lpData*: cstring
dwBufferLength*: DWORD dwBufferLength*: DWORD
dwBytesRecorded*: DWORD dwBytesRecorded*: DWORD
@ -1233,30 +1233,30 @@ type
NPMIDIHDR* = ptr midihdr NPMIDIHDR* = ptr midihdr
LPMIDIHDR* = ptr midihdr LPMIDIHDR* = ptr midihdr
TMIDIHDR* = MIDIHDR TMIDIHDR* = MIDIHDR
midievent* = record midievent* {.final.} = object
dwDeltaTime*: DWORD dwDeltaTime*: DWORD
dwStreamID*: DWORD dwStreamID*: DWORD
dwEvent*: DWORD dwEvent*: DWORD
dwParms*: array[0..Pred(1), DWORD] dwParms*: array[0..Pred(1), DWORD]
TMIDIEVENT* = MIDIEVENT TMIDIEVENT* = MIDIEVENT
midistrmbuffver* = record midistrmbuffver* {.final.} = object
dwVersion*: DWORD dwVersion*: DWORD
dwMid*: DWORD dwMid*: DWORD
dwOEMVersion*: DWORD dwOEMVersion*: DWORD
TMIDISTRMBUFFVER* = MIDISTRMBUFFVER TMIDISTRMBUFFVER* = MIDISTRMBUFFVER
Tmidiproptimediv* = record Tmidiproptimediv* {.final.} = object
cbStruct*: DWORD cbStruct*: DWORD
dwTimeDiv*: DWORD dwTimeDiv*: DWORD
LPMIDIPROPTIMEDIV* = ptr Tmidiproptimediv LPMIDIPROPTIMEDIV* = ptr Tmidiproptimediv
Tmidiproptempo* = record Tmidiproptempo* {.final.} = object
cbStruct*: DWORD cbStruct*: DWORD
dwTempo*: DWORD dwTempo*: DWORD
LPMIDIPROPTEMPO* = ptr Tmidiproptempo LPMIDIPROPTEMPO* = ptr Tmidiproptempo
AUXCAPSA* = record AUXCAPSA* {.final.} = object
wMid*: int16 wMid*: int16
wPid*: int16 wPid*: int16
vDriverVersion*: MMVERSION vDriverVersion*: MMVERSION
@ -1269,7 +1269,7 @@ type
NPAUXCAPSA* = ptr AUXCAPSA NPAUXCAPSA* = ptr AUXCAPSA
LPAUXCAPSA* = ptr AUXCAPSA LPAUXCAPSA* = ptr AUXCAPSA
TAUXCAPSA* = AUXCAPSA TAUXCAPSA* = AUXCAPSA
AUXCAPSW* = record AUXCAPSW* {.final.} = object
wMid*: int16 wMid*: int16
wPid*: int16 wPid*: int16
vDriverVersion*: MMVERSION vDriverVersion*: MMVERSION
@ -1305,7 +1305,7 @@ type
proc mixerGetNumDevs*(): UINT{.stdcall, dynlib: "winmm.dll", proc mixerGetNumDevs*(): UINT{.stdcall, dynlib: "winmm.dll",
importc: "mixerGetNumDevs".} importc: "mixerGetNumDevs".}
type type
MIXERCAPSA* = record MIXERCAPSA* {.final.} = object
wMid*: int16 wMid*: int16
wPid*: int16 wPid*: int16
vDriverVersion*: MMVERSION vDriverVersion*: MMVERSION
@ -1316,7 +1316,7 @@ type
PMIXERCAPSA* = ptr MIXERCAPSA PMIXERCAPSA* = ptr MIXERCAPSA
LPMIXERCAPSA* = ptr MIXERCAPSA LPMIXERCAPSA* = ptr MIXERCAPSA
TMIXERCAPSA* = MIXERCAPSA TMIXERCAPSA* = MIXERCAPSA
MIXERCAPSW* = record MIXERCAPSW* {.final.} = object
wMid*: int16 wMid*: int16
wPid*: int16 wPid*: int16
vDriverVersion*: MMVERSION vDriverVersion*: MMVERSION
@ -1340,7 +1340,7 @@ else:
LPMIXERCAPS* = LPMIXERCAPSA LPMIXERCAPS* = LPMIXERCAPSA
type type
TMIXERCAPS* = MIXERCAPS TMIXERCAPS* = MIXERCAPS
MIXERLINEA* = record MIXERLINEA* {.final.} = object
cbStruct*: DWORD cbStruct*: DWORD
dwDestination*: DWORD dwDestination*: DWORD
dwSource*: DWORD dwSource*: DWORD
@ -1361,7 +1361,7 @@ type
PMIXERLINEA* = ptr MIXERLINEA PMIXERLINEA* = ptr MIXERLINEA
LPMIXERLINEA* = ptr MIXERLINEA LPMIXERLINEA* = ptr MIXERLINEA
TMIXERLINEA* = MIXERLINEA TMIXERLINEA* = MIXERLINEA
MIXERLINEW* = record MIXERLINEW* {.final.} = object
cbStruct*: DWORD cbStruct*: DWORD
dwDestination*: DWORD dwDestination*: DWORD
dwSource*: DWORD dwSource*: DWORD
@ -1395,7 +1395,7 @@ else:
LPMIXERLINE* = LPMIXERLINEA LPMIXERLINE* = LPMIXERLINEA
type type
TMIXERLINE* = MIXERLINE TMIXERLINE* = MIXERLINE
MIXERCONTROLA* = record MIXERCONTROLA* {.final.} = object
cbStruct*: DWORD cbStruct*: DWORD
dwControlID*: DWORD dwControlID*: DWORD
dwControlType*: DWORD dwControlType*: DWORD
@ -1411,7 +1411,7 @@ type
PMIXERCONTROLA* = ptr MIXERCONTROLA PMIXERCONTROLA* = ptr MIXERCONTROLA
LPMIXERCONTROLA* = ptr MIXERCONTROLA LPMIXERCONTROLA* = ptr MIXERCONTROLA
TMIXERCONTROLA* = MIXERCONTROLA TMIXERCONTROLA* = MIXERCONTROLA
MIXERCONTROLW* = record MIXERCONTROLW* {.final.} = object
cbStruct*: DWORD cbStruct*: DWORD
dwControlID*: DWORD dwControlID*: DWORD
dwControlType*: DWORD dwControlType*: DWORD
@ -1440,7 +1440,7 @@ else:
LPMIXERCONTROL* = LPMIXERCONTROLA LPMIXERCONTROL* = LPMIXERCONTROLA
type type
TMIXERCONTROL* = MIXERCONTROL TMIXERCONTROL* = MIXERCONTROL
MIXERLINECONTROLSA* = record MIXERLINECONTROLSA* {.final.} = object
cbStruct*: DWORD cbStruct*: DWORD
dwLineID*: DWORD dwLineID*: DWORD
dwControlType*, cControls*, cbmxctrl*: DWORD dwControlType*, cControls*, cbmxctrl*: DWORD
@ -1449,7 +1449,7 @@ type
PMIXERLINECONTROLSA* = ptr MIXERLINECONTROLSA PMIXERLINECONTROLSA* = ptr MIXERLINECONTROLSA
LPMIXERLINECONTROLSA* = ptr MIXERLINECONTROLSA LPMIXERLINECONTROLSA* = ptr MIXERLINECONTROLSA
TMIXERLINECONTROLSA* = MIXERLINECONTROLSA TMIXERLINECONTROLSA* = MIXERLINECONTROLSA
MIXERLINECONTROLSW* = record MIXERLINECONTROLSW* {.final.} = object
cbStruct*: DWORD cbStruct*: DWORD
dwLineID*: DWORD dwLineID*: DWORD
dwControlType*, cControls*, cbmxctrl*: DWORD dwControlType*, cControls*, cbmxctrl*: DWORD
@ -1471,7 +1471,7 @@ else:
LPMIXERLINECONTROLS* = LPMIXERLINECONTROLSA LPMIXERLINECONTROLS* = LPMIXERLINECONTROLSA
type type
TMIXERLINECONTROLS* = MIXERLINECONTROLS TMIXERLINECONTROLS* = MIXERLINECONTROLS
TMIXERCONTROLDETAILS* = record TMIXERCONTROLDETAILS* {.final.} = object
cbStruct*: DWORD cbStruct*: DWORD
dwControlID*: DWORD dwControlID*: DWORD
cChannels*: DWORD cChannels*: DWORD
@ -1481,7 +1481,7 @@ type
MIXERCONTROLDETAILS* = tMIXERCONTROLDETAILS MIXERCONTROLDETAILS* = tMIXERCONTROLDETAILS
PMIXERCONTROLDETAILS* = ptr tMIXERCONTROLDETAILS PMIXERCONTROLDETAILS* = ptr tMIXERCONTROLDETAILS
LPMIXERCONTROLDETAILS* = ptr tMIXERCONTROLDETAILS LPMIXERCONTROLDETAILS* = ptr tMIXERCONTROLDETAILS
MIXERCONTROLDETAILS_LISTTEXTA* = record MIXERCONTROLDETAILS_LISTTEXTA* {.final.} = object
dwParam1*: DWORD dwParam1*: DWORD
dwParam2*: DWORD dwParam2*: DWORD
szName*: array[0..Pred(MIXER_LONG_NAME_CHARS), CHAR] szName*: array[0..Pred(MIXER_LONG_NAME_CHARS), CHAR]
@ -1489,7 +1489,7 @@ type
PMIXERCONTROLDETAILS_LISTTEXTA* = ptr MIXERCONTROLDETAILS_LISTTEXTA PMIXERCONTROLDETAILS_LISTTEXTA* = ptr MIXERCONTROLDETAILS_LISTTEXTA
LPMIXERCONTROLDETAILS_LISTTEXTA* = ptr MIXERCONTROLDETAILS_LISTTEXTA LPMIXERCONTROLDETAILS_LISTTEXTA* = ptr MIXERCONTROLDETAILS_LISTTEXTA
TMIXERCONTROLDETAILS_LISTTEXTA* = MIXERCONTROLDETAILS_LISTTEXTA TMIXERCONTROLDETAILS_LISTTEXTA* = MIXERCONTROLDETAILS_LISTTEXTA
MIXERCONTROLDETAILS_LISTTEXTW* = record MIXERCONTROLDETAILS_LISTTEXTW* {.final.} = object
dwParam1*: DWORD dwParam1*: DWORD
dwParam2*: DWORD dwParam2*: DWORD
szName*: array[0..Pred(MIXER_LONG_NAME_CHARS), WCHAR] szName*: array[0..Pred(MIXER_LONG_NAME_CHARS), WCHAR]
@ -1510,19 +1510,19 @@ else:
LPMIXERCONTROLDETAILS_LISTTEXT* = LPMIXERCONTROLDETAILS_LISTTEXTA LPMIXERCONTROLDETAILS_LISTTEXT* = LPMIXERCONTROLDETAILS_LISTTEXTA
type type
TMIXERCONTROLDETAILS_LISTTEXT* = MIXERCONTROLDETAILS_LISTTEXT TMIXERCONTROLDETAILS_LISTTEXT* = MIXERCONTROLDETAILS_LISTTEXT
MIXERCONTROLDETAILS_BOOLEAN* = record MIXERCONTROLDETAILS_BOOLEAN* {.final.} = object
fValue*: int32 fValue*: int32
PMIXERCONTROLDETAILS_BOOLEAN* = ptr MIXERCONTROLDETAILS_BOOLEAN PMIXERCONTROLDETAILS_BOOLEAN* = ptr MIXERCONTROLDETAILS_BOOLEAN
LPMIXERCONTROLDETAILS_BOOLEAN* = ptr MIXERCONTROLDETAILS_BOOLEAN LPMIXERCONTROLDETAILS_BOOLEAN* = ptr MIXERCONTROLDETAILS_BOOLEAN
TMIXERCONTROLDETAILS_BOOLEAN* = MIXERCONTROLDETAILS_BOOLEAN TMIXERCONTROLDETAILS_BOOLEAN* = MIXERCONTROLDETAILS_BOOLEAN
MIXERCONTROLDETAILS_SIGNED* = record MIXERCONTROLDETAILS_SIGNED* {.final.} = object
lValue*: int32 lValue*: int32
PMIXERCONTROLDETAILS_SIGNED* = ptr MIXERCONTROLDETAILS_SIGNED PMIXERCONTROLDETAILS_SIGNED* = ptr MIXERCONTROLDETAILS_SIGNED
LPMIXERCONTROLDETAILS_SIGNED* = ptr MIXERCONTROLDETAILS_SIGNED LPMIXERCONTROLDETAILS_SIGNED* = ptr MIXERCONTROLDETAILS_SIGNED
TMIXERCONTROLDETAILS_SIGNED* = MIXERCONTROLDETAILS_SIGNED TMIXERCONTROLDETAILS_SIGNED* = MIXERCONTROLDETAILS_SIGNED
MIXERCONTROLDETAILS_UNSIGNED* = record MIXERCONTROLDETAILS_UNSIGNED* {.final.} = object
dwValue*: DWORD dwValue*: DWORD
PMIXERCONTROLDETAILS_UNSIGNED* = ptr MIXERCONTROLDETAILS_UNSIGNED PMIXERCONTROLDETAILS_UNSIGNED* = ptr MIXERCONTROLDETAILS_UNSIGNED
@ -1531,7 +1531,7 @@ type
LPTIMECALLBACK* = proc (uTimerID, uMsg: UINT, dwUser, dw1, dw2: DWORD){. LPTIMECALLBACK* = proc (uTimerID, uMsg: UINT, dwUser, dw1, dw2: DWORD){.
stdcall.} stdcall.}
TTIMECALLBACK* = LPTIMECALLBACK TTIMECALLBACK* = LPTIMECALLBACK
timecaps* = record timecaps* {.final.} = object
wPeriodMin*: UINT wPeriodMin*: UINT
wPeriodMax*: UINT wPeriodMax*: UINT
@ -1539,7 +1539,7 @@ type
NPTIMECAPS* = ptr timecaps NPTIMECAPS* = ptr timecaps
LPTIMECAPS* = ptr timecaps LPTIMECAPS* = ptr timecaps
TTIMECAS* = TIMECAPS TTIMECAS* = TIMECAPS
JOYCAPSA* = record JOYCAPSA* {.final.} = object
wMid*: int16 wMid*: int16
wPid*: int16 wPid*: int16
szPname*: array[0..Pred(MAXPNAMELEN), CHAR] szPname*: array[0..Pred(MAXPNAMELEN), CHAR]
@ -1569,7 +1569,7 @@ type
NPJOYCAPSA* = ptr JOYCAPSA NPJOYCAPSA* = ptr JOYCAPSA
LPJOYCAPSA* = ptr JOYCAPSA LPJOYCAPSA* = ptr JOYCAPSA
TJOYCAPSA* = JOYCAPSA TJOYCAPSA* = JOYCAPSA
JOYCAPSW* = record JOYCAPSW* {.final.} = object
wMid*: int16 wMid*: int16
wPid*: int16 wPid*: int16
szPname*: array[0..Pred(MAXPNAMELEN), WCHAR] szPname*: array[0..Pred(MAXPNAMELEN), WCHAR]
@ -1614,7 +1614,7 @@ else:
LPJOYCAPS* = LPJOYCAPSA LPJOYCAPS* = LPJOYCAPSA
type type
TJOYCAPS* = JOYCAPS TJOYCAPS* = JOYCAPS
joyinfo* = record joyinfo* {.final.} = object
wXpos*: UINT wXpos*: UINT
wYpos*: UINT wYpos*: UINT
wZpos*: UINT wZpos*: UINT
@ -1624,7 +1624,7 @@ type
NPJOYINFO* = ptr joyinfo NPJOYINFO* = ptr joyinfo
LPJOYINFO* = ptr joyinfo LPJOYINFO* = ptr joyinfo
TJOYINFO* = JOYINFO TJOYINFO* = JOYINFO
joyinfoex* = record joyinfoex* {.final.} = object
dwSize*: DWORD dwSize*: DWORD
dwFlags*: DWORD dwFlags*: DWORD
wXpos*: UINT wXpos*: UINT
@ -1648,7 +1648,7 @@ type
HMMIO* = THandle HMMIO* = THandle
LPMMIOPROC* = proc (x1: LPSTR, x2: UINT, x3, x4: LPARAM): LRESULT{.stdcall.} LPMMIOPROC* = proc (x1: LPSTR, x2: UINT, x3, x4: LPARAM): LRESULT{.stdcall.}
TMMIOPROC* = LPMMIOPROC TMMIOPROC* = LPMMIOPROC
MMIOINFO* = record MMIOINFO* {.final.} = object
dwFlags*: DWORD dwFlags*: DWORD
fccIOProc*: FOURCC fccIOProc*: FOURCC
pIOProc*: LPMMIOPROC pIOProc*: LPMMIOPROC
@ -1671,7 +1671,7 @@ type
LPMMIOINFO* = ptr MMIOINFO LPMMIOINFO* = ptr MMIOINFO
LPCMMIOINFO* = ptr MMIOINFO LPCMMIOINFO* = ptr MMIOINFO
TMMIOINFO* = MMIOINFO TMMIOINFO* = MMIOINFO
MMCKINFO* = record MMCKINFO* {.final.} = object
ckid*: FOURCC ckid*: FOURCC
cksize*: DWORD cksize*: DWORD
fccType*: FOURCC fccType*: FOURCC
@ -1687,13 +1687,13 @@ type
MCIDEVICEID* = UINT MCIDEVICEID* = UINT
YIELDPROC* = proc (mciId: MCIDEVICEID, dwYieldData: DWORD): UINT{.stdcall.} YIELDPROC* = proc (mciId: MCIDEVICEID, dwYieldData: DWORD): UINT{.stdcall.}
TYIELDPROC* = YIELDPROC TYIELDPROC* = YIELDPROC
MCI_GENERIC_PARMS* = record MCI_GENERIC_PARMS* {.final.} = object
dwCallback*: DWORD dwCallback*: DWORD
PMCI_GENERIC_PARMS* = ptr MCI_GENERIC_PARMS PMCI_GENERIC_PARMS* = ptr MCI_GENERIC_PARMS
LPMCI_GENERIC_PARMS* = ptr MCI_GENERIC_PARMS LPMCI_GENERIC_PARMS* = ptr MCI_GENERIC_PARMS
TMCI_GENERIC_PARMS* = MCI_GENERIC_PARMS TMCI_GENERIC_PARMS* = MCI_GENERIC_PARMS
MCI_OPEN_PARMSA* = record MCI_OPEN_PARMSA* {.final.} = object
dwCallback*: DWORD dwCallback*: DWORD
wDeviceID*: MCIDEVICEID wDeviceID*: MCIDEVICEID
lpstrDeviceType*: LPCSTR lpstrDeviceType*: LPCSTR
@ -1703,7 +1703,7 @@ type
PMCI_OPEN_PARMSA* = ptr MCI_OPEN_PARMSA PMCI_OPEN_PARMSA* = ptr MCI_OPEN_PARMSA
LPMCI_OPEN_PARMSA* = ptr MCI_OPEN_PARMSA LPMCI_OPEN_PARMSA* = ptr MCI_OPEN_PARMSA
TMCI_OPEN_PARMSA* = MCI_OPEN_PARMSA TMCI_OPEN_PARMSA* = MCI_OPEN_PARMSA
MCI_OPEN_PARMSW* = record MCI_OPEN_PARMSW* {.final.} = object
dwCallback*: DWORD dwCallback*: DWORD
wDeviceID*: MCIDEVICEID wDeviceID*: MCIDEVICEID
lpstrDeviceType*: LPCWSTR lpstrDeviceType*: LPCWSTR
@ -1726,7 +1726,7 @@ else:
LPMCI_OPEN_PARMS* = LPMCI_OPEN_PARMSA LPMCI_OPEN_PARMS* = LPMCI_OPEN_PARMSA
type type
TMCI_OPEN_PARMS* = MCI_OPEN_PARMS TMCI_OPEN_PARMS* = MCI_OPEN_PARMS
MCI_PLAY_PARMS* = record MCI_PLAY_PARMS* {.final.} = object
dwCallback*: DWORD dwCallback*: DWORD
dwFrom*: DWORD dwFrom*: DWORD
dwTo*: DWORD dwTo*: DWORD
@ -1734,14 +1734,14 @@ type
PMCI_PLAY_PARMS* = ptr MCI_PLAY_PARMS PMCI_PLAY_PARMS* = ptr MCI_PLAY_PARMS
LPMCI_PLAY_PARMS* = ptr MCI_PLAY_PARMS LPMCI_PLAY_PARMS* = ptr MCI_PLAY_PARMS
TMCI_PLAY_PARMS* = MCI_PLAY_PARMS TMCI_PLAY_PARMS* = MCI_PLAY_PARMS
MCI_SEEK_PARMS* = record MCI_SEEK_PARMS* {.final.} = object
dwCallback*: DWORD dwCallback*: DWORD
dwTo*: DWORD dwTo*: DWORD
PMCI_SEEK_PARMS* = ptr MCI_SEEK_PARMS PMCI_SEEK_PARMS* = ptr MCI_SEEK_PARMS
LPMCI_SEEK_PARMS* = ptr MCI_SEEK_PARMS LPMCI_SEEK_PARMS* = ptr MCI_SEEK_PARMS
TMCI_SEEK_PARMS* = MCI_SEEK_PARMS TMCI_SEEK_PARMS* = MCI_SEEK_PARMS
MCI_STATUS_PARMS* = record MCI_STATUS_PARMS* {.final.} = object
dwCallback*: DWORD dwCallback*: DWORD
dwReturn*: DWORD dwReturn*: DWORD
dwItem*: DWORD dwItem*: DWORD
@ -1750,14 +1750,14 @@ type
PMCI_STATUS_PARMS* = ptr MCI_STATUS_PARMS PMCI_STATUS_PARMS* = ptr MCI_STATUS_PARMS
LPMCI_STATUS_PARMS* = ptr MCI_STATUS_PARMS LPMCI_STATUS_PARMS* = ptr MCI_STATUS_PARMS
TMCI_STATUS_PARMS* = MCI_STATUS_PARMS TMCI_STATUS_PARMS* = MCI_STATUS_PARMS
MCI_INFO_PARMSA* = record MCI_INFO_PARMSA* {.final.} = object
dwCallback*: DWORD dwCallback*: DWORD
lpstrReturn*: cstring lpstrReturn*: cstring
dwRetSize*: DWORD dwRetSize*: DWORD
LPMCI_INFO_PARMSA* = ptr MCI_INFO_PARMSA LPMCI_INFO_PARMSA* = ptr MCI_INFO_PARMSA
TMCI_INFO_PARMSA* = MCI_INFO_PARMSA TMCI_INFO_PARMSA* = MCI_INFO_PARMSA
MCI_INFO_PARMSW* = record MCI_INFO_PARMSW* {.final.} = object
dwCallback*: DWORD dwCallback*: DWORD
lpstrReturn*: LPWSTR lpstrReturn*: LPWSTR
dwRetSize*: DWORD dwRetSize*: DWORD
@ -1775,7 +1775,7 @@ else:
LPMCI_INFO_PARMS* = LPMCI_INFO_PARMSA LPMCI_INFO_PARMS* = LPMCI_INFO_PARMSA
type type
TMCI_INFO_PARMS* = MCI_INFO_PARMS TMCI_INFO_PARMS* = MCI_INFO_PARMS
MCI_GETDEVCAPS_PARMS* = record MCI_GETDEVCAPS_PARMS* {.final.} = object
dwCallback*: DWORD dwCallback*: DWORD
dwReturn*: DWORD dwReturn*: DWORD
dwItem*: DWORD dwItem*: DWORD
@ -1783,7 +1783,7 @@ type
PMCI_GETDEVCAPS_PARMS* = ptr MCI_GETDEVCAPS_PARMS PMCI_GETDEVCAPS_PARMS* = ptr MCI_GETDEVCAPS_PARMS
LPMCI_GETDEVCAPS_PARMS* = ptr MCI_GETDEVCAPS_PARMS LPMCI_GETDEVCAPS_PARMS* = ptr MCI_GETDEVCAPS_PARMS
TMCI_GETDEVCAPS_PARMS* = MCI_GETDEVCAPS_PARMS TMCI_GETDEVCAPS_PARMS* = MCI_GETDEVCAPS_PARMS
MCI_SYSINFO_PARMSA* = record MCI_SYSINFO_PARMSA* {.final.} = object
dwCallback*: DWORD dwCallback*: DWORD
lpstrReturn*: cstring lpstrReturn*: cstring
dwRetSize*: DWORD dwRetSize*: DWORD
@ -1793,7 +1793,7 @@ type
PMCI_SYSINFO_PARMSA* = ptr MCI_SYSINFO_PARMSA PMCI_SYSINFO_PARMSA* = ptr MCI_SYSINFO_PARMSA
LPMCI_SYSINFO_PARMSA* = ptr MCI_SYSINFO_PARMSA LPMCI_SYSINFO_PARMSA* = ptr MCI_SYSINFO_PARMSA
TMCI_SYSINFO_PARMSA* = MCI_SYSINFO_PARMSA TMCI_SYSINFO_PARMSA* = MCI_SYSINFO_PARMSA
MCI_SYSINFO_PARMSW* = record MCI_SYSINFO_PARMSW* {.final.} = object
dwCallback*: DWORD dwCallback*: DWORD
lpstrReturn*: LPWSTR lpstrReturn*: LPWSTR
dwRetSize*: DWORD dwRetSize*: DWORD
@ -1816,7 +1816,7 @@ else:
LPMCI_SYSINFO_PARMS* = LPMCI_SYSINFO_PARMSA LPMCI_SYSINFO_PARMS* = LPMCI_SYSINFO_PARMSA
type type
TMCI_SYSINFO_PARMS* = MCI_SYSINFO_PARMS TMCI_SYSINFO_PARMS* = MCI_SYSINFO_PARMS
MCI_SET_PARMS* = record MCI_SET_PARMS* {.final.} = object
dwCallback*: DWORD dwCallback*: DWORD
dwTimeFormat*: DWORD dwTimeFormat*: DWORD
dwAudio*: DWORD dwAudio*: DWORD
@ -1824,7 +1824,7 @@ type
PMCI_SET_PARMS* = ptr MCI_SET_PARMS PMCI_SET_PARMS* = ptr MCI_SET_PARMS
LPMCI_SET_PARMS* = ptr MCI_SET_PARMS LPMCI_SET_PARMS* = ptr MCI_SET_PARMS
TMCI_SET_PARMS* = MCI_SET_PARMS TMCI_SET_PARMS* = MCI_SET_PARMS
MCI_BREAK_PARMS* = record MCI_BREAK_PARMS* {.final.} = object
dwCallback*: DWORD dwCallback*: DWORD
nVirtKey*: int32 nVirtKey*: int32
hwndBreak*: HWND hwndBreak*: HWND
@ -1832,14 +1832,14 @@ type
PMCI_BREAK_PARMS* = ptr MCI_BREAK_PARMS PMCI_BREAK_PARMS* = ptr MCI_BREAK_PARMS
LPMCI_BREAK_PARMS* = ptr MCI_BREAK_PARMS LPMCI_BREAK_PARMS* = ptr MCI_BREAK_PARMS
TMCI_BREAK_PARMS* = MCI_BREAK_PARMS TMCI_BREAK_PARMS* = MCI_BREAK_PARMS
MCI_SAVE_PARMSA* = record MCI_SAVE_PARMSA* {.final.} = object
dwCallback*: DWORD dwCallback*: DWORD
lpfilename*: LPCSTR lpfilename*: LPCSTR
PMCI_SAVE_PARMSA* = ptr MCI_SAVE_PARMSA PMCI_SAVE_PARMSA* = ptr MCI_SAVE_PARMSA
LPMCI_SAVE_PARMSA* = ptr MCI_SAVE_PARMSA LPMCI_SAVE_PARMSA* = ptr MCI_SAVE_PARMSA
TMCI_SAVE_PARMSA* = MCI_SAVE_PARMSA TMCI_SAVE_PARMSA* = MCI_SAVE_PARMSA
MCI_SAVE_PARMSW* = record MCI_SAVE_PARMSW* {.final.} = object
dwCallback*: DWORD dwCallback*: DWORD
lpfilename*: LPCWSTR lpfilename*: LPCWSTR
@ -1859,14 +1859,14 @@ else:
LPMCI_SAVE_PARMS* = LPMCI_SAVE_PARMSA LPMCI_SAVE_PARMS* = LPMCI_SAVE_PARMSA
type type
TMCI_SAVE_PARMS* = MCI_SAVE_PARMS TMCI_SAVE_PARMS* = MCI_SAVE_PARMS
MCI_LOAD_PARMSA* = record MCI_LOAD_PARMSA* {.final.} = object
dwCallback*: DWORD dwCallback*: DWORD
lpfilename*: LPCSTR lpfilename*: LPCSTR
PMCI_LOAD_PARMSA* = ptr MCI_LOAD_PARMSA PMCI_LOAD_PARMSA* = ptr MCI_LOAD_PARMSA
LPMCI_LOAD_PARMSA* = ptr MCI_LOAD_PARMSA LPMCI_LOAD_PARMSA* = ptr MCI_LOAD_PARMSA
TMCI_LOAD_PARMSA* = MCI_LOAD_PARMSA TMCI_LOAD_PARMSA* = MCI_LOAD_PARMSA
MCI_LOAD_PARMSW* = record MCI_LOAD_PARMSW* {.final.} = object
dwCallback*: DWORD dwCallback*: DWORD
lpfilename*: LPCWSTR lpfilename*: LPCWSTR
@ -1886,14 +1886,14 @@ else:
LPMCI_LOAD_PARMS* = LPMCI_LOAD_PARMSA LPMCI_LOAD_PARMS* = LPMCI_LOAD_PARMSA
type type
TMCI_LOAD_PARMS* = MCI_LOAD_PARMS TMCI_LOAD_PARMS* = MCI_LOAD_PARMS
MCI_RECORD_PARMS* = record MCI_RECORD_PARMS* {.final.} = object
dwCallback*: DWORD dwCallback*: DWORD
dwFrom*: DWORD dwFrom*: DWORD
dwTo*: DWORD dwTo*: DWORD
LPMCI_RECORD_PARMS* = ptr MCI_RECORD_PARMS LPMCI_RECORD_PARMS* = ptr MCI_RECORD_PARMS
TMCI_RECORD_PARMS* = MCI_RECORD_PARMS TMCI_RECORD_PARMS* = MCI_RECORD_PARMS
MCI_VD_PLAY_PARMS* = record MCI_VD_PLAY_PARMS* {.final.} = object
dwCallback*: DWORD dwCallback*: DWORD
dwFrom*: DWORD dwFrom*: DWORD
dwTo*: DWORD dwTo*: DWORD
@ -1902,20 +1902,20 @@ type
PMCI_VD_PLAY_PARMS* = ptr MCI_VD_PLAY_PARMS PMCI_VD_PLAY_PARMS* = ptr MCI_VD_PLAY_PARMS
LPMCI_VD_PLAY_PARMS* = ptr MCI_VD_PLAY_PARMS LPMCI_VD_PLAY_PARMS* = ptr MCI_VD_PLAY_PARMS
TMCI_VD_PLAY_PARMS* = MCI_VD_PLAY_PARMS TMCI_VD_PLAY_PARMS* = MCI_VD_PLAY_PARMS
MCI_VD_STEP_PARMS* = record MCI_VD_STEP_PARMS* {.final.} = object
dwCallback*: DWORD dwCallback*: DWORD
dwFrames*: DWORD dwFrames*: DWORD
PMCI_VD_STEP_PARMS* = ptr MCI_VD_STEP_PARMS PMCI_VD_STEP_PARMS* = ptr MCI_VD_STEP_PARMS
LPMCI_VD_STEP_PARMS* = ptr MCI_VD_STEP_PARMS LPMCI_VD_STEP_PARMS* = ptr MCI_VD_STEP_PARMS
MCI_VD_ESCAPE_PARMSA* = record MCI_VD_ESCAPE_PARMSA* {.final.} = object
dwCallback*: DWORD dwCallback*: DWORD
lpstrCommand*: LPCSTR lpstrCommand*: LPCSTR
PMCI_VD_ESCAPE_PARMSA* = ptr MCI_VD_ESCAPE_PARMSA PMCI_VD_ESCAPE_PARMSA* = ptr MCI_VD_ESCAPE_PARMSA
LPMCI_VD_ESCAPE_PARMSA* = ptr MCI_VD_ESCAPE_PARMSA LPMCI_VD_ESCAPE_PARMSA* = ptr MCI_VD_ESCAPE_PARMSA
TMCI_VD_ESCAPE_PARMSA* = MCI_VD_ESCAPE_PARMSA TMCI_VD_ESCAPE_PARMSA* = MCI_VD_ESCAPE_PARMSA
MCI_VD_ESCAPE_PARMSW* = record MCI_VD_ESCAPE_PARMSW* {.final.} = object
dwCallback*: DWORD dwCallback*: DWORD
lpstrCommand*: LPCWSTR lpstrCommand*: LPCWSTR
@ -1935,7 +1935,7 @@ else:
LPMCI_VD_ESCAPE_PARMS* = LPMCI_VD_ESCAPE_PARMSA LPMCI_VD_ESCAPE_PARMS* = LPMCI_VD_ESCAPE_PARMSA
type type
TMCI_VD_ESCAPE_PARMS* = MCI_VD_ESCAPE_PARMS TMCI_VD_ESCAPE_PARMS* = MCI_VD_ESCAPE_PARMS
MCI_WAVE_OPEN_PARMSA* = record MCI_WAVE_OPEN_PARMSA* {.final.} = object
dwCallback*: DWORD dwCallback*: DWORD
wDeviceID*: MCIDEVICEID wDeviceID*: MCIDEVICEID
lpstrDeviceType*: LPCSTR lpstrDeviceType*: LPCSTR
@ -1946,7 +1946,7 @@ type
PMCI_WAVE_OPEN_PARMSA* = ptr MCI_WAVE_OPEN_PARMSA PMCI_WAVE_OPEN_PARMSA* = ptr MCI_WAVE_OPEN_PARMSA
LPMCI_WAVE_OPEN_PARMSA* = ptr MCI_WAVE_OPEN_PARMSA LPMCI_WAVE_OPEN_PARMSA* = ptr MCI_WAVE_OPEN_PARMSA
TMCI_WAVE_OPEN_PARMSA* = MCI_WAVE_OPEN_PARMSA TMCI_WAVE_OPEN_PARMSA* = MCI_WAVE_OPEN_PARMSA
MCI_WAVE_OPEN_PARMSW* = record MCI_WAVE_OPEN_PARMSW* {.final.} = object
dwCallback*: DWORD dwCallback*: DWORD
wDeviceID*: MCIDEVICEID wDeviceID*: MCIDEVICEID
lpstrDeviceType*: LPCWSTR lpstrDeviceType*: LPCWSTR
@ -1970,7 +1970,7 @@ else:
LPMCI_WAVE_OPEN_PARMS* = LPMCI_WAVE_OPEN_PARMSA LPMCI_WAVE_OPEN_PARMS* = LPMCI_WAVE_OPEN_PARMSA
type type
TMCI_WAVE_OPEN_PARMS* = MCI_WAVE_OPEN_PARMS TMCI_WAVE_OPEN_PARMS* = MCI_WAVE_OPEN_PARMS
MCI_WAVE_DELETE_PARMS* = record MCI_WAVE_DELETE_PARMS* {.final.} = object
dwCallback*: DWORD dwCallback*: DWORD
dwFrom*: DWORD dwFrom*: DWORD
dwTo*: DWORD dwTo*: DWORD
@ -1978,7 +1978,7 @@ type
PMCI_WAVE_DELETE_PARMS* = ptr MCI_WAVE_DELETE_PARMS PMCI_WAVE_DELETE_PARMS* = ptr MCI_WAVE_DELETE_PARMS
LPMCI_WAVE_DELETE_PARMS* = ptr MCI_WAVE_DELETE_PARMS LPMCI_WAVE_DELETE_PARMS* = ptr MCI_WAVE_DELETE_PARMS
TMCI_WAVE_DELETE_PARMS* = MCI_WAVE_DELETE_PARMS TMCI_WAVE_DELETE_PARMS* = MCI_WAVE_DELETE_PARMS
MCI_WAVE_SET_PARMS* = record MCI_WAVE_SET_PARMS* {.final.} = object
dwCallback*: DWORD dwCallback*: DWORD
dwTimeFormat*: DWORD dwTimeFormat*: DWORD
dwAudio*: DWORD dwAudio*: DWORD
@ -1998,7 +1998,7 @@ type
PMCI_WAVE_SET_PARMS* = ptr MCI_WAVE_SET_PARMS PMCI_WAVE_SET_PARMS* = ptr MCI_WAVE_SET_PARMS
LPMCI_WAVE_SET_PARMS* = ptr MCI_WAVE_SET_PARMS LPMCI_WAVE_SET_PARMS* = ptr MCI_WAVE_SET_PARMS
TMCI_WAVE_SET_PARMS* = MCI_WAVE_SET_PARMS TMCI_WAVE_SET_PARMS* = MCI_WAVE_SET_PARMS
MCI_SEQ_SET_PARMS* = record MCI_SEQ_SET_PARMS* {.final.} = object
dwCallback*: DWORD dwCallback*: DWORD
dwTimeFormat*: DWORD dwTimeFormat*: DWORD
dwAudio*: DWORD dwAudio*: DWORD
@ -2011,7 +2011,7 @@ type
PMCI_SEQ_SET_PARMS* = ptr MCI_SEQ_SET_PARMS PMCI_SEQ_SET_PARMS* = ptr MCI_SEQ_SET_PARMS
LPMCI_SEQ_SET_PARMS* = ptr MCI_SEQ_SET_PARMS LPMCI_SEQ_SET_PARMS* = ptr MCI_SEQ_SET_PARMS
TMCI_SEQ_SET_PARMS* = MCI_SEQ_SET_PARMS TMCI_SEQ_SET_PARMS* = MCI_SEQ_SET_PARMS
MCI_ANIM_OPEN_PARMSA* = record MCI_ANIM_OPEN_PARMSA* {.final.} = object
dwCallback*: DWORD dwCallback*: DWORD
wDeviceID*: MCIDEVICEID wDeviceID*: MCIDEVICEID
lpstrDeviceType*: LPCSTR lpstrDeviceType*: LPCSTR
@ -2023,7 +2023,7 @@ type
PMCI_ANIM_OPEN_PARMSA* = ptr MCI_ANIM_OPEN_PARMSA PMCI_ANIM_OPEN_PARMSA* = ptr MCI_ANIM_OPEN_PARMSA
LPMCI_ANIM_OPEN_PARMSA* = ptr MCI_ANIM_OPEN_PARMSA LPMCI_ANIM_OPEN_PARMSA* = ptr MCI_ANIM_OPEN_PARMSA
TMCI_ANIM_OPEN_PARMSA* = MCI_ANIM_OPEN_PARMSA TMCI_ANIM_OPEN_PARMSA* = MCI_ANIM_OPEN_PARMSA
MCI_ANIM_OPEN_PARMSW* = record MCI_ANIM_OPEN_PARMSW* {.final.} = object
dwCallback*: DWORD dwCallback*: DWORD
wDeviceID*: MCIDEVICEID wDeviceID*: MCIDEVICEID
lpstrDeviceType*: LPCWSTR lpstrDeviceType*: LPCWSTR
@ -2047,7 +2047,7 @@ else:
LPMCI_ANIM_OPEN_PARMS* = LPMCI_ANIM_OPEN_PARMSA LPMCI_ANIM_OPEN_PARMS* = LPMCI_ANIM_OPEN_PARMSA
type type
TMCI_ANIM_OPEN_PARMS* = MCI_ANIM_OPEN_PARMS TMCI_ANIM_OPEN_PARMS* = MCI_ANIM_OPEN_PARMS
MCI_ANIM_WINDOW_PARMSW* = record MCI_ANIM_WINDOW_PARMSW* {.final.} = object
dwCallback*: DWORD dwCallback*: DWORD
hWnd*: HWND hWnd*: HWND
nCmdShow*: UINT nCmdShow*: UINT
@ -2056,14 +2056,14 @@ type
PMCI_ANIM_WINDOW_PARMSW* = ptr MCI_ANIM_WINDOW_PARMSW PMCI_ANIM_WINDOW_PARMSW* = ptr MCI_ANIM_WINDOW_PARMSW
LPMCI_ANIM_WINDOW_PARMSW* = ptr MCI_ANIM_WINDOW_PARMSW LPMCI_ANIM_WINDOW_PARMSW* = ptr MCI_ANIM_WINDOW_PARMSW
TMCI_ANIM_WINDOW_PARMSW* = MCI_ANIM_WINDOW_PARMSW TMCI_ANIM_WINDOW_PARMSW* = MCI_ANIM_WINDOW_PARMSW
MCI_ANIM_STEP_PARMS* = record MCI_ANIM_STEP_PARMS* {.final.} = object
dwCallback*: DWORD dwCallback*: DWORD
dwFrames*: DWORD dwFrames*: DWORD
PMCI_ANIM_STEP_PARMS* = ptr MCI_ANIM_STEP_PARMS PMCI_ANIM_STEP_PARMS* = ptr MCI_ANIM_STEP_PARMS
LPMCI_ANIM_STEP_PARMS* = ptr MCI_ANIM_STEP_PARMS LPMCI_ANIM_STEP_PARMS* = ptr MCI_ANIM_STEP_PARMS
TMCI_ANIM_STEP_PARMS* = MCI_ANIM_STEP_PARMS TMCI_ANIM_STEP_PARMS* = MCI_ANIM_STEP_PARMS
MCI_ANIM_WINDOW_PARMSA* = record MCI_ANIM_WINDOW_PARMSA* {.final.} = object
dwCallback*: DWORD dwCallback*: DWORD
hWnd*: HWND hWnd*: HWND
nCmdShow*: UINT nCmdShow*: UINT
@ -2072,7 +2072,7 @@ type
PMCI_ANIM_WINDOW_PARMSA* = ptr MCI_ANIM_WINDOW_PARMSA PMCI_ANIM_WINDOW_PARMSA* = ptr MCI_ANIM_WINDOW_PARMSA
LPMCI_ANIM_WINDOW_PARMSA* = ptr MCI_ANIM_WINDOW_PARMSA LPMCI_ANIM_WINDOW_PARMSA* = ptr MCI_ANIM_WINDOW_PARMSA
TMCI_ANIM_WINDOW_PARMSA* = MCI_ANIM_WINDOW_PARMSA TMCI_ANIM_WINDOW_PARMSA* = MCI_ANIM_WINDOW_PARMSA
MCI_ANIM_PLAY_PARMS* = record MCI_ANIM_PLAY_PARMS* {.final.} = object
dwCallback*: DWORD dwCallback*: DWORD
dwFrom*: DWORD dwFrom*: DWORD
dwTo*: DWORD dwTo*: DWORD
@ -2092,14 +2092,14 @@ else:
PMCI_ANIM_WINDOW_PARMS* = PMCI_ANIM_WINDOW_PARMSA PMCI_ANIM_WINDOW_PARMS* = PMCI_ANIM_WINDOW_PARMSA
LPMCI_ANIM_WINDOW_PARMS* = LPMCI_ANIM_WINDOW_PARMSA LPMCI_ANIM_WINDOW_PARMS* = LPMCI_ANIM_WINDOW_PARMSA
type type
MCI_ANIM_RECT_PARMS* = record MCI_ANIM_RECT_PARMS* {.final.} = object
dwCallback*: DWORD dwCallback*: DWORD
rc*: TRECT rc*: TRECT
PMCI_ANIM_RECT_PARMS* = ptr MCI_ANIM_RECT_PARMS PMCI_ANIM_RECT_PARMS* = ptr MCI_ANIM_RECT_PARMS
LPMCI_ANIM_RECT_PARMS* = ptr MCI_ANIM_RECT_PARMS LPMCI_ANIM_RECT_PARMS* = ptr MCI_ANIM_RECT_PARMS
TMCI_ANIM_RECT_PARMS* = MCI_ANIM_RECT_PARMS TMCI_ANIM_RECT_PARMS* = MCI_ANIM_RECT_PARMS
MCI_ANIM_UPDATE_PARMS* = record MCI_ANIM_UPDATE_PARMS* {.final.} = object
dwCallback*: DWORD dwCallback*: DWORD
rc*: TRECT rc*: TRECT
hDC*: HDC hDC*: HDC
@ -2107,7 +2107,7 @@ type
PMCI_ANIM_UPDATE_PARMS* = ptr MCI_ANIM_UPDATE_PARMS PMCI_ANIM_UPDATE_PARMS* = ptr MCI_ANIM_UPDATE_PARMS
LPMCI_ANIM_UPDATE_PARMS* = ptr MCI_ANIM_UPDATE_PARMS LPMCI_ANIM_UPDATE_PARMS* = ptr MCI_ANIM_UPDATE_PARMS
TMCI_ANIM_UPDATE_PARMS* = MCI_ANIM_UPDATE_PARMS TMCI_ANIM_UPDATE_PARMS* = MCI_ANIM_UPDATE_PARMS
MCI_OVLY_OPEN_PARMSA* = record MCI_OVLY_OPEN_PARMSA* {.final.} = object
dwCallback*: DWORD dwCallback*: DWORD
wDeviceID*: MCIDEVICEID wDeviceID*: MCIDEVICEID
lpstrDeviceType*: LPCSTR lpstrDeviceType*: LPCSTR
@ -2119,7 +2119,7 @@ type
PMCI_OVLY_OPEN_PARMSA* = ptr MCI_OVLY_OPEN_PARMSA PMCI_OVLY_OPEN_PARMSA* = ptr MCI_OVLY_OPEN_PARMSA
LPMCI_OVLY_OPEN_PARMSA* = ptr MCI_OVLY_OPEN_PARMSA LPMCI_OVLY_OPEN_PARMSA* = ptr MCI_OVLY_OPEN_PARMSA
TMCI_OVLY_OPEN_PARMSA* = MCI_OVLY_OPEN_PARMSA TMCI_OVLY_OPEN_PARMSA* = MCI_OVLY_OPEN_PARMSA
MCI_OVLY_OPEN_PARMSW* = record MCI_OVLY_OPEN_PARMSW* {.final.} = object
dwCallback*: DWORD dwCallback*: DWORD
wDeviceID*: MCIDEVICEID wDeviceID*: MCIDEVICEID
lpstrDeviceType*: LPCWSTR lpstrDeviceType*: LPCWSTR
@ -2144,7 +2144,7 @@ else:
LPMCI_OVLY_OPEN_PARMS* = LPMCI_OVLY_OPEN_PARMSA LPMCI_OVLY_OPEN_PARMS* = LPMCI_OVLY_OPEN_PARMSA
type type
TMCI_OVLY_OPEN_PARMS* = MCI_OVLY_OPEN_PARMS TMCI_OVLY_OPEN_PARMS* = MCI_OVLY_OPEN_PARMS
MCI_OVLY_WINDOW_PARMSA* = record MCI_OVLY_WINDOW_PARMSA* {.final.} = object
dwCallback*: DWORD dwCallback*: DWORD
hWnd*: HWND hWnd*: HWND
nCmdShow*: UINT nCmdShow*: UINT
@ -2153,7 +2153,7 @@ type
PMCI_OVLY_WINDOW_PARMSA* = ptr MCI_OVLY_WINDOW_PARMSA PMCI_OVLY_WINDOW_PARMSA* = ptr MCI_OVLY_WINDOW_PARMSA
LPMCI_OVLY_WINDOW_PARMSA* = ptr MCI_OVLY_WINDOW_PARMSA LPMCI_OVLY_WINDOW_PARMSA* = ptr MCI_OVLY_WINDOW_PARMSA
TMCI_OVLY_WINDOW_PARMSA* = MCI_OVLY_WINDOW_PARMSA TMCI_OVLY_WINDOW_PARMSA* = MCI_OVLY_WINDOW_PARMSA
MCI_OVLY_WINDOW_PARMSW* = record MCI_OVLY_WINDOW_PARMSW* {.final.} = object
dwCallback*: DWORD dwCallback*: DWORD
hWnd*: HWND hWnd*: HWND
nCmdShow*: UINT nCmdShow*: UINT
@ -2175,14 +2175,14 @@ else:
LPMCI_OVLY_WINDOW_PARMS* = LPMCI_OVLY_WINDOW_PARMSA LPMCI_OVLY_WINDOW_PARMS* = LPMCI_OVLY_WINDOW_PARMSA
type type
TMCI_OVLY_WINDOW_PARMS* = MCI_OVLY_WINDOW_PARMSW TMCI_OVLY_WINDOW_PARMS* = MCI_OVLY_WINDOW_PARMSW
MCI_OVLY_RECT_PARMS* = record MCI_OVLY_RECT_PARMS* {.final.} = object
dwCallback*: DWORD dwCallback*: DWORD
rc*: TRECT rc*: TRECT
PMCI_OVLY_RECT_PARMS* = ptr MCI_OVLY_RECT_PARMS PMCI_OVLY_RECT_PARMS* = ptr MCI_OVLY_RECT_PARMS
LPMCI_OVLY_RECT_PARMS* = ptr MCI_OVLY_RECT_PARMS LPMCI_OVLY_RECT_PARMS* = ptr MCI_OVLY_RECT_PARMS
TMCI_OVLY_RECT_PARMS* = MCI_OVLY_RECT_PARMS TMCI_OVLY_RECT_PARMS* = MCI_OVLY_RECT_PARMS
MCI_OVLY_SAVE_PARMSA* = record MCI_OVLY_SAVE_PARMSA* {.final.} = object
dwCallback*: DWORD dwCallback*: DWORD
lpfilename*: LPCSTR lpfilename*: LPCSTR
rc*: TRECT rc*: TRECT
@ -2190,7 +2190,7 @@ type
PMCI_OVLY_SAVE_PARMSA* = ptr MCI_OVLY_SAVE_PARMSA PMCI_OVLY_SAVE_PARMSA* = ptr MCI_OVLY_SAVE_PARMSA
LPMCI_OVLY_SAVE_PARMSA* = ptr MCI_OVLY_SAVE_PARMSA LPMCI_OVLY_SAVE_PARMSA* = ptr MCI_OVLY_SAVE_PARMSA
TMCI_OVLY_SAVE_PARMSA* = MCI_OVLY_SAVE_PARMSA TMCI_OVLY_SAVE_PARMSA* = MCI_OVLY_SAVE_PARMSA
MCI_OVLY_SAVE_PARMSW* = record MCI_OVLY_SAVE_PARMSW* {.final.} = object
dwCallback*: DWORD dwCallback*: DWORD
lpfilename*: LPCWSTR lpfilename*: LPCWSTR
rc*: TRECT rc*: TRECT
@ -2211,7 +2211,7 @@ else:
LPMCI_OVLY_SAVE_PARMS* = LPMCI_OVLY_SAVE_PARMSA LPMCI_OVLY_SAVE_PARMS* = LPMCI_OVLY_SAVE_PARMSA
type type
TMCI_OVLY_SAVE_PARMS* = MCI_OVLY_SAVE_PARMS TMCI_OVLY_SAVE_PARMS* = MCI_OVLY_SAVE_PARMS
MCI_OVLY_LOAD_PARMSA* = record MCI_OVLY_LOAD_PARMSA* {.final.} = object
dwCallback*: DWORD dwCallback*: DWORD
lpfilename*: LPCSTR lpfilename*: LPCSTR
rc*: TRECT rc*: TRECT
@ -2219,7 +2219,7 @@ type
PMCI_OVLY_LOAD_PARMSA* = ptr MCI_OVLY_LOAD_PARMSA PMCI_OVLY_LOAD_PARMSA* = ptr MCI_OVLY_LOAD_PARMSA
LPMCI_OVLY_LOAD_PARMSA* = ptr MCI_OVLY_LOAD_PARMSA LPMCI_OVLY_LOAD_PARMSA* = ptr MCI_OVLY_LOAD_PARMSA
TMCI_OVLY_LOAD_PARMSA* = MCI_OVLY_LOAD_PARMSA TMCI_OVLY_LOAD_PARMSA* = MCI_OVLY_LOAD_PARMSA
MCI_OVLY_LOAD_PARMSW* = record MCI_OVLY_LOAD_PARMSW* {.final.} = object
dwCallback*: DWORD dwCallback*: DWORD
lpfilename*: LPCWSTR lpfilename*: LPCWSTR
rc*: TRECT rc*: TRECT

View file

@ -8,7 +8,7 @@
# #
# NetBIOS 3.0 interface unit # NetBIOS 3.0 interface unit
# This unit contains the definitions for portable NetBIOS 3.0 support. # This module contains the definitions for portable NetBIOS 3.0 support.
import # Data structure templates import # Data structure templates
Windows Windows
@ -20,7 +20,7 @@ const
type # Network Control Block type # Network Control Block
PNCB* = ptr TNCB PNCB* = ptr TNCB
TNCBPostProc* = proc (P: PNCB) TNCBPostProc* = proc (P: PNCB)
TNCB* = record # Structure returned to the NCB command NCBASTAT is ADAPTER_STATUS followed TNCB* {.final.} = object # Structure returned to the NCB command NCBASTAT is ADAPTER_STATUS followed
# by an array of NAME_BUFFER structures. # by an array of NAME_BUFFER structures.
ncb_command*: Char # command code ncb_command*: Char # command code
ncb_retcode*: Char # return code ncb_retcode*: Char # return code
@ -42,7 +42,7 @@ type # Network Control Block
# completes # completes
PAdapterStatus* = ptr TAdapterStatus PAdapterStatus* = ptr TAdapterStatus
TAdapterStatus* = record TAdapterStatus* {.final.} = object
adapter_address*: array[0..5, Char] adapter_address*: array[0..5, Char]
rev_major*: Char rev_major*: Char
reserved0*: Char reserved0*: Char
@ -72,7 +72,7 @@ type # Network Control Block
name_count*: int16 name_count*: int16
PNameBuffer* = ptr TNameBuffer PNameBuffer* = ptr TNameBuffer
TNameBuffer* = record TNameBuffer* {.final.} = object
name*: array[0..NCBNAMSZ - 1, Char] name*: array[0..NCBNAMSZ - 1, Char]
name_num*: Char name_num*: Char
name_flags*: Char name_flags*: Char
@ -93,14 +93,14 @@ type # Structure returned to the NCB command NCBSSTAT is SESSION_HEADER followed
# asterisk then an array of these structures is returned containing the # asterisk then an array of these structures is returned containing the
# status for all names. # status for all names.
PSessionHeader* = ptr TSessionHeader PSessionHeader* = ptr TSessionHeader
TSessionHeader* = record TSessionHeader* {.final.} = object
sess_name*: Char sess_name*: Char
num_sess*: Char num_sess*: Char
rcv_dg_outstanding*: Char rcv_dg_outstanding*: Char
rcv_any_outstanding*: Char rcv_any_outstanding*: Char
PSessionBuffer* = ptr TSessionBuffer PSessionBuffer* = ptr TSessionBuffer
TSessionBuffer* = record TSessionBuffer* {.final.} = object
lsn*: Char lsn*: Char
state*: Char state*: Char
local_name*: array[0..NCBNAMSZ - 1, Char] local_name*: array[0..NCBNAMSZ - 1, Char]
@ -121,19 +121,19 @@ type # Structure returned to the NCB command NCBENUM.
# On a system containing lana's 0, 2 and 3, a structure with # On a system containing lana's 0, 2 and 3, a structure with
# length =3, lana[0]=0, lana[1]=2 and lana[2]=3 will be returned. # length =3, lana[0]=0, lana[1]=2 and lana[2]=3 will be returned.
PLanaEnum* = ptr TLanaEnum PLanaEnum* = ptr TLanaEnum
TLanaEnum* = record # Structure returned to the NCB command NCBFINDNAME is FIND_NAME_HEADER followed TLanaEnum* {.final.} = object # Structure returned to the NCB command NCBFINDNAME is FIND_NAME_HEADER followed
# by an array of FIND_NAME_BUFFER structures. # by an array of FIND_NAME_BUFFER structures.
len*: Char # Number of valid entries in lana[] len*: Char # Number of valid entries in lana[]
lana*: array[0..MAX_LANA, Char] lana*: array[0..MAX_LANA, Char]
PFindNameHeader* = ptr TFindNameHeader PFindNameHeader* = ptr TFindNameHeader
TFindNameHeader* = record TFindNameHeader* {.final.} = object
node_count*: int16 node_count*: int16
reserved*: Char reserved*: Char
unique_group*: Char unique_group*: Char
PFindNameBuffer* = ptr TFindNameBuffer PFindNameBuffer* = ptr TFindNameBuffer
TFindNameBuffer* = record # Structure provided with NCBACTION. The purpose of NCBACTION is to provide TFindNameBuffer* {.final.} = object # Structure provided with NCBACTION. The purpose of NCBACTION is to provide
# transport specific extensions to netbios. # transport specific extensions to netbios.
len*: Char len*: Char
access_control*: Char access_control*: Char
@ -143,7 +143,7 @@ type # Structure returned to the NCB command NCBENUM.
routing_info*: array[0..17, Char] routing_info*: array[0..17, Char]
PActionHeader* = ptr TActionHeader PActionHeader* = ptr TActionHeader
TActionHeader* = record TActionHeader* {.final.} = object
transport_id*: int32 transport_id*: int32
action_code*: int16 action_code*: int16
reserved*: int16 reserved*: int16

View file

@ -33,7 +33,7 @@ type
DWORD_PTR* = ptr DWORD DWORD_PTR* = ptr DWORD
pHICON* = ptr HICON pHICON* = ptr HICON
pBool* = ptr BOOL pBool* = ptr BOOL
STARTUPINFOW* = record # a guess. Omission should get fixed in Windows. STARTUPINFOW* {.final.} = object # a guess. Omission should get fixed in Windows.
cb*: DWORD cb*: DWORD
lpReserved*: LPTSTR lpReserved*: LPTSTR
lpDesktop*: LPTSTR lpDesktop*: LPTSTR
@ -122,7 +122,7 @@ proc ExtractIcon*(hInst: HINST, lpszExeFileName: LPCWSTR, nIconIndex: UINT): HIC
stdcall, dynlib: "shell32.dll", importc: "ExtractIconW".} stdcall, dynlib: "shell32.dll", importc: "ExtractIconW".}
# if(WINVER >= 0x0400) # if(WINVER >= 0x0400)
type # init with sizeof(DRAGINFO) type # init with sizeof(DRAGINFO)
DRAGINFOA* = record DRAGINFOA* {.final.} = object
uSize*: UINT uSize*: UINT
pt*: POINT pt*: POINT
fNC*: BOOL fNC*: BOOL
@ -131,7 +131,7 @@ type # init with sizeof(DRAGINFO)
TDRAGINFOA* = DRAGINFOA TDRAGINFOA* = DRAGINFOA
LPDRAGINFOA* = ptr DRAGINFOA # init with sizeof(DRAGINFO) LPDRAGINFOA* = ptr DRAGINFOA # init with sizeof(DRAGINFO)
DRAGINFOW* = record DRAGINFOW* {.final.} = object
uSize*: UINT uSize*: UINT
pt*: POINT pt*: POINT
fNC*: BOOL fNC*: BOOL
@ -178,7 +178,7 @@ const
ABE_BOTTOM* = 3 ABE_BOTTOM* = 3
type type
AppBarData* = record AppBarData* {.final.} = object
cbSize*: DWORD cbSize*: DWORD
hWnd*: HWND hWnd*: HWND
uCallbackMessage*: UINT uCallbackMessage*: UINT
@ -286,7 +286,7 @@ type
# only used if FOF_SIMPLEPROGRESS # only used if FOF_SIMPLEPROGRESS
type type
SHFILEOPSTRUCTA* = record SHFILEOPSTRUCTA* {.final.} = object
hwnd*: HWND hwnd*: HWND
wFunc*: UINT wFunc*: UINT
pFrom*: LPCSTR pFrom*: LPCSTR
@ -298,7 +298,7 @@ type
TSHFILEOPSTRUCTA* = SHFILEOPSTRUCTA TSHFILEOPSTRUCTA* = SHFILEOPSTRUCTA
LPSHFILEOPSTRUCTA* = ptr SHFILEOPSTRUCTA LPSHFILEOPSTRUCTA* = ptr SHFILEOPSTRUCTA
SHFILEOPSTRUCTW* = record SHFILEOPSTRUCTW* {.final.} = object
hwnd*: HWND hwnd*: HWND
wFunc*: UINT wFunc*: UINT
pFrom*: LPCWSTR pFrom*: LPCWSTR
@ -332,7 +332,7 @@ proc SHFileOperation*(lpFileOp: LPSHFILEOPSTRUCTW): int32{.stdcall,
proc SHFreeNameMappings*(hNameMappings: THandle){.stdcall, proc SHFreeNameMappings*(hNameMappings: THandle){.stdcall,
dynlib: "shell32.dll", importc: "SHFreeNameMappings".} dynlib: "shell32.dll", importc: "SHFreeNameMappings".}
type type
SHNAMEMAPPINGA* = record SHNAMEMAPPINGA* {.final.} = object
pszOldPath*: LPSTR pszOldPath*: LPSTR
pszNewPath*: LPSTR pszNewPath*: LPSTR
cchOldPath*: int32 cchOldPath*: int32
@ -340,7 +340,7 @@ type
TSHNAMEMAPPINGA* = SHNAMEMAPPINGA TSHNAMEMAPPINGA* = SHNAMEMAPPINGA
LPSHNAMEMAPPINGA* = ptr SHNAMEMAPPINGA LPSHNAMEMAPPINGA* = ptr SHNAMEMAPPINGA
SHNAMEMAPPINGW* = record SHNAMEMAPPINGW* {.final.} = object
pszOldPath*: LPWSTR pszOldPath*: LPWSTR
pszNewPath*: LPWSTR pszNewPath*: LPWSTR
cchOldPath*: int32 cchOldPath*: int32
@ -404,7 +404,7 @@ const
# (_WIN32_IE >= 0x560) # (_WIN32_IE >= 0x560)
type type
SHELLEXECUTEINFOA* = record SHELLEXECUTEINFOA* {.final.} = object
cbSize*: DWORD cbSize*: DWORD
fMask*: ULONG fMask*: ULONG
hwnd*: HWND hwnd*: HWND
@ -423,7 +423,7 @@ type
TSHELLEXECUTEINFOA* = SHELLEXECUTEINFOA TSHELLEXECUTEINFOA* = SHELLEXECUTEINFOA
LPSHELLEXECUTEINFOA* = ptr SHELLEXECUTEINFOA LPSHELLEXECUTEINFOA* = ptr SHELLEXECUTEINFOA
SHELLEXECUTEINFOW* = record SHELLEXECUTEINFOW* {.final.} = object
cbSize*: DWORD cbSize*: DWORD
fMask*: ULONG fMask*: ULONG
hwnd*: HWND hwnd*: HWND
@ -474,7 +474,7 @@ proc WinExecError*(HWND: hwnd, error: int32, lpstrFileName: LPCWSTR,
lpstrTitle: LPCWSTR){.stdcall, dynlib: "shell32.dll", lpstrTitle: LPCWSTR){.stdcall, dynlib: "shell32.dll",
importc: "WinExecErrorW".} importc: "WinExecErrorW".}
type type
SHCREATEPROCESSINFOW* = record SHCREATEPROCESSINFOW* {.final.} = object
cbSize*: DWORD cbSize*: DWORD
fMask*: ULONG fMask*: ULONG
hwnd*: HWND hwnd*: HWND
@ -502,7 +502,7 @@ proc SHCreateProcessAsUserW*(pscpi: PSHCREATEPROCESSINFOW): Bool{.stdcall,
# #
# struct for query recycle bin info # struct for query recycle bin info
type type
SHQUERYRBINFO* = record SHQUERYRBINFO* {.final.} = object
cbSize*: DWORD cbSize*: DWORD
i64Size*: int64 i64Size*: int64
i64NumItems*: int64 i64NumItems*: int64
@ -538,7 +538,7 @@ proc SHEmptyRecycleBin*(hwnd: HWND, pszRootPath: LPCWSTR, dwFlags: DWORD): HRESU
# Tray notification definitions # Tray notification definitions
# #
type type
NOTIFYICONDATAA* = record NOTIFYICONDATAA* {.final.} = object
cbSize*: DWORD cbSize*: DWORD
hWnd*: HWND hWnd*: HWND
uID*: UINT uID*: UINT
@ -556,7 +556,7 @@ type
TNOTIFYICONDATAA* = NOTIFYICONDATAA TNOTIFYICONDATAA* = NOTIFYICONDATAA
PNOTIFYICONDATAA* = ptr NOTIFYICONDATAA PNOTIFYICONDATAA* = ptr NOTIFYICONDATAA
NOTIFYICONDATAW* = record NOTIFYICONDATAW* {.final.} = object
cbSize*: DWORD cbSize*: DWORD
hWnd*: HWND hWnd*: HWND
uID*: UINT uID*: UINT
@ -645,7 +645,7 @@ proc Shell_NotifyIcon*(dwMessage: Dword, lpData: PNOTIFYICONDATAW): Bool{.
# out: display name (or path) # out: display name (or path)
# out: type name # out: type name
type type
SHFILEINFOA* = record SHFILEINFOA* {.final.} = object
hIcon*: HICON # out: icon hIcon*: HICON # out: icon
iIcon*: int32 # out: icon index iIcon*: int32 # out: icon index
dwAttributes*: DWORD # out: SFGAO_ flags dwAttributes*: DWORD # out: SFGAO_ flags
@ -654,7 +654,7 @@ type
TSHFILEINFOA* = SHFILEINFOA TSHFILEINFOA* = SHFILEINFOA
pSHFILEINFOA* = ptr SHFILEINFOA pSHFILEINFOA* = ptr SHFILEINFOA
SHFILEINFOW* = record SHFILEINFOW* {.final.} = object
hIcon*: HICON # out: icon hIcon*: HICON # out: icon
iIcon*: int32 # out: icon index iIcon*: int32 # out: icon index
dwAttributes*: DWORD # out: SFGAO_ flags dwAttributes*: DWORD # out: SFGAO_ flags

File diff suppressed because it is too large Load diff

View file

@ -64,6 +64,135 @@ for key, val in enums.iteritems():
cog.out(a) cog.out(a)
cog.out(b) cog.out(b)
]]]*) ]]]*)
type
TNodeKind = (
nkNone, nkEmpty, nkIdent, nkSym,
nkType, nkCharLit, nkIntLit, nkInt8Lit,
nkInt16Lit, nkInt32Lit, nkInt64Lit, nkFloatLit,
nkFloat32Lit, nkFloat64Lit, nkStrLit, nkRStrLit,
nkTripleStrLit, nkMetaNode, nkNilLit, nkDotCall,
nkCommand, nkCall, nkGenericCall, nkExplicitTypeListCall,
nkExprEqExpr, nkExprColonExpr, nkIdentDefs, nkInfix,
nkPrefix, nkPostfix, nkPar, nkCurly,
nkBracket, nkBracketExpr, nkPragmaExpr, nkRange,
nkDotExpr, nkCheckedFieldExpr, nkDerefExpr, nkIfExpr,
nkElifExpr, nkElseExpr, nkLambda, nkAccQuoted,
nkHeaderQuoted, nkTableConstr, nkQualified, nkHiddenStdConv,
nkHiddenSubConv, nkHiddenCallConv, nkConv, nkCast,
nkAddr, nkHiddenAddr, nkHiddenDeref, nkObjDownConv,
nkObjUpConv, nkChckRangeF, nkChckRange64, nkChckRange,
nkStringToCString, nkCStringToString, nkPassAsOpenArray, nkAsgn,
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, nkAccessStmt, nkCommentStmt, nkStmtListExpr,
nkBlockExpr, nkVm, nkTypeOfExpr, nkObjectTy,
nkTupleTy, nkRecList, nkRecCase, nkRecWhen,
nkRefTy, nkPtrTy, nkVarTy, nkProcTy,
nkEnumTy, nkEnumFieldDef, nkReturnToken);
TNodeKinds = set of TNodeKind;
const
NodeKindToStr: array [TNodeKind] of string = (
'nkNone', 'nkEmpty', 'nkIdent', 'nkSym',
'nkType', 'nkCharLit', 'nkIntLit', 'nkInt8Lit',
'nkInt16Lit', 'nkInt32Lit', 'nkInt64Lit', 'nkFloatLit',
'nkFloat32Lit', 'nkFloat64Lit', 'nkStrLit', 'nkRStrLit',
'nkTripleStrLit', 'nkMetaNode', 'nkNilLit', 'nkDotCall',
'nkCommand', 'nkCall', 'nkGenericCall', 'nkExplicitTypeListCall',
'nkExprEqExpr', 'nkExprColonExpr', 'nkIdentDefs', 'nkInfix',
'nkPrefix', 'nkPostfix', 'nkPar', 'nkCurly',
'nkBracket', 'nkBracketExpr', 'nkPragmaExpr', 'nkRange',
'nkDotExpr', 'nkCheckedFieldExpr', 'nkDerefExpr', 'nkIfExpr',
'nkElifExpr', 'nkElseExpr', 'nkLambda', 'nkAccQuoted',
'nkHeaderQuoted', 'nkTableConstr', 'nkQualified', 'nkHiddenStdConv',
'nkHiddenSubConv', 'nkHiddenCallConv', 'nkConv', 'nkCast',
'nkAddr', 'nkHiddenAddr', 'nkHiddenDeref', 'nkObjDownConv',
'nkObjUpConv', 'nkChckRangeF', 'nkChckRange64', 'nkChckRange',
'nkStringToCString', 'nkCStringToString', 'nkPassAsOpenArray', 'nkAsgn',
'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', 'nkAccessStmt', 'nkCommentStmt', 'nkStmtListExpr',
'nkBlockExpr', 'nkVm', 'nkTypeOfExpr', 'nkObjectTy',
'nkTupleTy', 'nkRecList', 'nkRecCase', 'nkRecWhen',
'nkRefTy', 'nkPtrTy', 'nkVarTy', 'nkProcTy',
'nkEnumTy', 'nkEnumFieldDef', 'nkReturnToken');
type
TSymFlag = (
sfTypeCheck, sfForward, sfImportc, sfExportc,
sfVolatile, sfUsed, sfWrite, sfRegister,
sfPure, sfCodeGenerated, sfPrivate, sfGlobal,
sfResult, sfNoSideEffect, sfMainModule, sfSystemModule,
sfNoReturn, sfAddrTaken, sfInInterface, sfNoStatic,
sfCompilerProc, sfCppMethod, sfDiscriminant, sfDeprecated,
sfInClosure, sfIsCopy, sfStar, sfMinus);
TSymFlags = set of TSymFlag;
const
SymFlagToStr: array [TSymFlag] of string = (
'sfTypeCheck', 'sfForward', 'sfImportc', 'sfExportc',
'sfVolatile', 'sfUsed', 'sfWrite', 'sfRegister',
'sfPure', 'sfCodeGenerated', 'sfPrivate', 'sfGlobal',
'sfResult', 'sfNoSideEffect', 'sfMainModule', 'sfSystemModule',
'sfNoReturn', 'sfAddrTaken', 'sfInInterface', 'sfNoStatic',
'sfCompilerProc', 'sfCppMethod', 'sfDiscriminant', 'sfDeprecated',
'sfInClosure', 'sfIsCopy', 'sfStar', 'sfMinus');
type
TTypeKind = (
tyNone, tyBool, tyChar, tyEmptySet,
tyArrayConstr, tyNil, tyGeneric, tyGenericInst,
tyGenericParam, tyEnum, tyAnyEnum, tyArray,
tyObject, tyTuple, tySet, tyRange,
tyPtr, tyRef, tyVar, tySequence,
tyProc, tyPointer, tyOpenArray, tyString,
tyCString, tyForward, tyInt, tyInt8,
tyInt16, tyInt32, tyInt64, tyFloat,
tyFloat32, tyFloat64, tyFloat128);
TTypeKinds = set of TTypeKind;
const
TypeKindToStr: array [TTypeKind] of string = (
'tyNone', 'tyBool', 'tyChar', 'tyEmptySet',
'tyArrayConstr', 'tyNil', 'tyGeneric', 'tyGenericInst',
'tyGenericParam', 'tyEnum', 'tyAnyEnum', 'tyArray',
'tyObject', 'tyTuple', 'tySet', 'tyRange',
'tyPtr', 'tyRef', 'tyVar', 'tySequence',
'tyProc', 'tyPointer', 'tyOpenArray', 'tyString',
'tyCString', 'tyForward', 'tyInt', 'tyInt8',
'tyInt16', 'tyInt32', 'tyInt64', 'tyFloat',
'tyFloat32', 'tyFloat64', 'tyFloat128');
type
TNodeFlag = (
nfNone, nfBase2, nfBase8, nfBase16,
nfAllConst);
TNodeFlags = set of TNodeFlag;
const
NodeFlagToStr: array [TNodeFlag] of string = (
'nfNone', 'nfBase2', 'nfBase8', 'nfBase16',
'nfAllConst');
type
TTypeFlag = (
tfIsDistinct, tfGeneric, tfExternal, tfImported,
tfInfoGenerated, tfSemChecked, tfHasOutParams, tfEnumHasWholes,
tfVarargs, tfFinal);
TTypeFlags = set of TTypeFlag;
const
TypeFlagToStr: array [TTypeFlag] of string = (
'tfIsDistinct', 'tfGeneric', 'tfExternal', 'tfImported',
'tfInfoGenerated', 'tfSemChecked', 'tfHasOutParams', 'tfEnumHasWholes',
'tfVarargs', 'tfFinal');
type type
TSymKind = ( TSymKind = (
skUnknownSym, skConditional, skDynLib, skParam, skUnknownSym, skConditional, skDynLib, skParam,
@ -79,126 +208,6 @@ const
'skVar', 'skProc', 'skIterator', 'skConverter', 'skVar', 'skProc', 'skIterator', 'skConverter',
'skMacro', 'skTemplate', 'skField', 'skEnumField', 'skMacro', 'skTemplate', 'skField', 'skEnumField',
'skForVar', 'skModule', 'skLabel'); 'skForVar', 'skModule', 'skLabel');
type
TNodeKind = (
nkNone, nkEmpty, nkIdent, nkSym,
nkType, nkCharLit, nkRCharLit, nkIntLit,
nkInt8Lit, nkInt16Lit, nkInt32Lit, nkInt64Lit,
nkFloatLit, nkFloat32Lit, nkFloat64Lit, nkStrLit,
nkRStrLit, nkTripleStrLit, nkNilLit, nkDotCall,
nkCommand, nkCall, nkGenericCall, nkExplicitTypeListCall,
nkExprEqExpr, nkExprColonExpr, nkIdentDefs, nkInfix,
nkPrefix, nkPostfix, nkPar, nkCurly,
nkBracket, nkBracketExpr, nkPragmaExpr, nkRange,
nkDotExpr, nkCheckedFieldExpr, nkDerefExpr, nkIfExpr,
nkElifExpr, nkElseExpr, nkLambda, nkAccQuoted,
nkHeaderQuoted, nkSetConstr, nkConstSetConstr, nkArrayConstr,
nkConstArrayConstr, nkRecordConstr, nkConstRecordConstr, nkTableConstr,
nkConstTableConstr, nkQualified, nkHiddenStdConv, nkHiddenSubConv,
nkHiddenCallConv, nkConv, nkCast, nkAddr,
nkAsgn, 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,
nkGotoStmt, nkDiscardStmt, nkStmtList, nkImportStmt,
nkFromStmt, nkImportAs, nkIncludeStmt, nkAccessStmt,
nkCommentStmt, nkStmtListExpr, nkBlockExpr, nkVm,
nkTypeOfExpr, nkRecordTy, nkObjectTy, nkRecList,
nkRecCase, nkRecWhen, nkRefTy, nkPtrTy,
nkVarTy, nkProcTy, nkEnumTy, nkEnumFieldDef);
TNodeKinds = set of TNodeKind;
const
NodeKindToStr: array [TNodeKind] of string = (
'nkNone', 'nkEmpty', 'nkIdent', 'nkSym',
'nkType', 'nkCharLit', 'nkRCharLit', 'nkIntLit',
'nkInt8Lit', 'nkInt16Lit', 'nkInt32Lit', 'nkInt64Lit',
'nkFloatLit', 'nkFloat32Lit', 'nkFloat64Lit', 'nkStrLit',
'nkRStrLit', 'nkTripleStrLit', 'nkNilLit', 'nkDotCall',
'nkCommand', 'nkCall', 'nkGenericCall', 'nkExplicitTypeListCall',
'nkExprEqExpr', 'nkExprColonExpr', 'nkIdentDefs', 'nkInfix',
'nkPrefix', 'nkPostfix', 'nkPar', 'nkCurly',
'nkBracket', 'nkBracketExpr', 'nkPragmaExpr', 'nkRange',
'nkDotExpr', 'nkCheckedFieldExpr', 'nkDerefExpr', 'nkIfExpr',
'nkElifExpr', 'nkElseExpr', 'nkLambda', 'nkAccQuoted',
'nkHeaderQuoted', 'nkSetConstr', 'nkConstSetConstr', 'nkArrayConstr',
'nkConstArrayConstr', 'nkRecordConstr', 'nkConstRecordConstr', 'nkTableConstr',
'nkConstTableConstr', 'nkQualified', 'nkHiddenStdConv', 'nkHiddenSubConv',
'nkHiddenCallConv', 'nkConv', 'nkCast', 'nkAddr',
'nkAsgn', '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',
'nkGotoStmt', 'nkDiscardStmt', 'nkStmtList', 'nkImportStmt',
'nkFromStmt', 'nkImportAs', 'nkIncludeStmt', 'nkAccessStmt',
'nkCommentStmt', 'nkStmtListExpr', 'nkBlockExpr', 'nkVm',
'nkTypeOfExpr', 'nkRecordTy', 'nkObjectTy', 'nkRecList',
'nkRecCase', 'nkRecWhen', 'nkRefTy', 'nkPtrTy',
'nkVarTy', 'nkProcTy', 'nkEnumTy', 'nkEnumFieldDef');
type
TSymFlag = (
sfGeneric, sfForward, sfImportc, sfExportc,
sfVolatile, sfUsed, sfWrite, sfRegister,
sfPure, sfCodeGenerated, sfPrivate, sfGlobal,
sfResult, sfNoSideEffect, sfMainModule, sfSystemModule,
sfNoReturn, sfReturnsNew, sfInInterface, sfNoStatic,
sfCompilerProc, sfCppMethod, sfDiscriminant, sfDeprecated,
sfInClosure, sfIsCopy, sfStar, sfMinus);
TSymFlags = set of TSymFlag;
const
SymFlagToStr: array [TSymFlag] of string = (
'sfGeneric', 'sfForward', 'sfImportc', 'sfExportc',
'sfVolatile', 'sfUsed', 'sfWrite', 'sfRegister',
'sfPure', 'sfCodeGenerated', 'sfPrivate', 'sfGlobal',
'sfResult', 'sfNoSideEffect', 'sfMainModule', 'sfSystemModule',
'sfNoReturn', 'sfReturnsNew', 'sfInInterface', 'sfNoStatic',
'sfCompilerProc', 'sfCppMethod', 'sfDiscriminant', 'sfDeprecated',
'sfInClosure', 'sfIsCopy', 'sfStar', 'sfMinus');
type
TTypeKind = (
tyNone, tyBool, tyChar, tyEmptySet,
tyArrayConstr, tyNil, tyRecordConstr, tyGeneric,
tyGenericInst, tyGenericParam, tyEnum, tyAnyEnum,
tyArray, tyRecord, tyObject, tyTuple,
tySet, tyRange, tyPtr, tyRef,
tyVar, tySequence, tyProc, tyPointer,
tyOpenArray, tyString, tyCString, tyForward,
tyInt, tyInt8, tyInt16, tyInt32,
tyInt64, tyFloat, tyFloat32, tyFloat64,
tyFloat128);
TTypeKinds = set of TTypeKind;
const
TypeKindToStr: array [TTypeKind] of string = (
'tyNone', 'tyBool', 'tyChar', 'tyEmptySet',
'tyArrayConstr', 'tyNil', 'tyRecordConstr', 'tyGeneric',
'tyGenericInst', 'tyGenericParam', 'tyEnum', 'tyAnyEnum',
'tyArray', 'tyRecord', 'tyObject', 'tyTuple',
'tySet', 'tyRange', 'tyPtr', 'tyRef',
'tyVar', 'tySequence', 'tyProc', 'tyPointer',
'tyOpenArray', 'tyString', 'tyCString', 'tyForward',
'tyInt', 'tyInt8', 'tyInt16', 'tyInt32',
'tyInt64', 'tyFloat', 'tyFloat32', 'tyFloat64',
'tyFloat128');
type
TTypeFlag = (
tfIsDistinct, tfGeneric, tfExternal, tfImported,
tfInfoGenerated, tfSemChecked, tfHasOutParams, tfEnumHasWholes,
tfVarargs, tfAssignable);
TTypeFlags = set of TTypeFlag;
const
TypeFlagToStr: array [TTypeFlag] of string = (
'tfIsDistinct', 'tfGeneric', 'tfExternal', 'tfImported',
'tfInfoGenerated', 'tfSemChecked', 'tfHasOutParams', 'tfEnumHasWholes',
'tfVarargs', 'tfAssignable');
{[[[end]]]} {[[[end]]]}
type type
@ -228,20 +237,28 @@ type
mEqProc, mEqUntracedRef, mLePtr, mLtPtr, mEqCString, mXor, mEqProc, mEqUntracedRef, mLePtr, mLtPtr, mEqCString, mXor,
mUnaryMinusI, mUnaryMinusI64, mAbsI, mAbsI64, mNot, mUnaryPlusI, mUnaryMinusI, mUnaryMinusI64, mAbsI, mAbsI64, mNot, mUnaryPlusI,
mBitnotI, mUnaryPlusI64, mBitnotI64, mUnaryPlusF64, mUnaryMinusF64, mAbsF64, mBitnotI, mUnaryPlusI64, mBitnotI64, mUnaryPlusF64, mUnaryMinusF64, mAbsF64,
mZe, mZe64, mToU8, mToU16, mToU32, mToFloat, mZe8ToI, mZe8ToI64, mZe16ToI, mZe16ToI64, mZe32ToI64, mZeIToI64,
mToBiggestFloat, mToInt, mToBiggestInt, mAnd, mOr, mEqStr, mToU8, mToU16, mToU32, mToFloat, mToBiggestFloat, mToInt,
mLeStr, mLtStr, mEqSet, mLeSet, mLtSet, mMulSet, mToBiggestInt, mCharToStr, mBoolToStr, mIntToStr, mInt64ToStr, mFloatToStr,
mPlusSet, mMinusSet, mSymDiffSet, mConStrStr, mConArrArr, mConArrT, mCStrToStr, mStrToStr, mAnd, mOr, mEqStr, mLeStr,
mConTArr, mConTT, mSlice, mAppendStrCh, mAppendStrStr, mAppendSeqElem, mLtStr, mEqSet, mLeSet, mLtSet, mMulSet, mPlusSet,
mAppendSeqSeq, mInRange, mInSet, mIs, mAsgn, mRepr, mMinusSet, mSymDiffSet, mConStrStr, mConArrArr, mConArrT, mConTArr,
mExit, mSetLengthStr, mSetLengthSeq, mAssert, mSwap, mArray, mConTT, mSlice, mAppendStrCh, mAppendStrStr, mAppendSeqElem, mAppendSeqSeq,
mOpenArray, mRange, mTuple, mSet, mSeq, mCompileDate, mInRange, mInSet, mIs, mAsgn, mRepr, mExit,
mCompileTime, mNimrodVersion, mNimrodMajor, mNimrodMinor, mNimrodPatch, mCpuEndian mSetLengthStr, mSetLengthSeq, mAssert, mSwap, mIsNil, mArray,
mOpenArray, mRange, mSet, mSeq, mCompileDate, mCompileTime,
mNimrodVersion, mNimrodMajor, mNimrodMinor, mNimrodPatch, mCpuEndian, 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]]] //[[[end]]]
); );
type type
PNode = ^TNode; PNode = ^TNode;
PNodePtr = ^{@ptr}PNode;
TNodeSeq = array of PNode; TNodeSeq = array of PNode;
PType = ^TType; PType = ^TType;
@ -254,22 +271,22 @@ type
comment: string; comment: string;
sons: TNodeSeq; // else! sons: TNodeSeq; // else!
info: TLineInfo; info: TLineInfo;
base: TNumericalBase; // only valid for int or float literals flags: TNodeFlags;
case Kind: TNodeKind of case Kind: TNodeKind of
nkCharLit, nkRCharLit, nkCharLit, nkIntLit, nkInt8Lit, nkInt16Lit, nkInt32Lit, nkInt64Lit:
nkIntLit, nkInt8Lit, nkInt16Lit, nkInt32Lit, nkInt64Lit:
(intVal: biggestInt); (intVal: biggestInt);
nkFloatLit, nkFloat32Lit, nkFloat64Lit: nkFloatLit, nkFloat32Lit, nkFloat64Lit:
(floatVal: biggestFloat); (floatVal: biggestFloat);
nkSym: (sym: PSym); nkSym: (sym: PSym);
nkIdent: (ident: PIdent); nkIdent: (ident: PIdent);
nkMetaNode: (nodePtr: PNodePtr);
end; end;
{@emit {@emit
record // keep this below 32 bytes; otherwise the AST grows too much record // keep this below 32 bytes; otherwise the AST grows too much
typ: PType; typ: PType;
comment: string; comment: string;
info: TLineInfo; info: TLineInfo;
base: TNumericalBase; // only valid for int or float literals flags: TNodeFlags;
case Kind: TNodeKind of case Kind: TNodeKind of
nkCharLit..nkInt64Lit: nkCharLit..nkInt64Lit:
(intVal: biggestInt); (intVal: biggestInt);
@ -279,6 +296,7 @@ type
(strVal: string); (strVal: string);
nkSym: (sym: PSym); nkSym: (sym: PSym);
nkIdent: (ident: PIdent); nkIdent: (ident: PIdent);
nkMetaNode: (nodePtr: PNodePtr);
else (sons: TNodeSeq); else (sons: TNodeSeq);
end; } end; }
@ -307,27 +325,27 @@ type
); );
TLocFlag = ( TLocFlag = (
// lfIndirect, // location needs to be derefered lfIndirect, // backend introduced a pointer
lfOnStack, // location is on hardware stack
lfOnHeap, // location is on heap
lfOnData, // location is in the static constant data
lfOnUnknown, // location is unknown (stack, heap or static)
// other backend-flags:
lfNoDeepCopy, // no need for a deep copy lfNoDeepCopy, // no need for a deep copy
lfNoDecl, // do not declare it in C lfNoDecl, // do not declare it in C
lfDynamicLib, // link symbol to dynamic library lfDynamicLib, // link symbol to dynamic library
lfHeader // include header file for symbol lfHeader // include header file for symbol
); );
TStorageLoc = (
OnUnknown, // location is unknown (stack, heap or static)
OnStack, // location is on hardware stack
OnHeap // location is on heap or global (reference counting needed)
);
TLocFlags = set of TLocFlag; TLocFlags = set of TLocFlag;
TLoc = record TLoc = record
k: TLocKind; // kind of location k: TLocKind; // kind of location
t: PType; // type of location s: TStorageLoc;
r: PRope; // rope value of location (C code generator)
a: int; // location's "address", i.e. slot for temporaries
flags: TLocFlags; // location's flags flags: TLocFlags; // location's flags
indirect: int; // count the number of dereferences needed to access the t: PType; // type of location
// location r: PRope; // rope value of location (code generators)
a: int; // location's "address", i.e. slot for temporaries
end; end;
// ---------------- end of backend information ------------------------------ // ---------------- end of backend information ------------------------------
@ -447,7 +465,7 @@ type
PLib = ^TLib; PLib = ^TLib;
const const
OverloadableSyms = {@set}[skProc, skIterator, skEnumField]; OverloadableSyms = {@set}[skProc, skIterator, skConverter];
const // "MagicToStr" array: const // "MagicToStr" array:
MagicToStr: array [TMagic] of string = ( MagicToStr: array [TMagic] of string = (
@ -474,15 +492,22 @@ const // "MagicToStr" array:
'EqProc', 'EqUntracedRef', 'LePtr', 'LtPtr', 'EqCString', 'Xor', 'EqProc', 'EqUntracedRef', 'LePtr', 'LtPtr', 'EqCString', 'Xor',
'UnaryMinusI', 'UnaryMinusI64', 'AbsI', 'AbsI64', 'Not', 'UnaryPlusI', 'UnaryMinusI', 'UnaryMinusI64', 'AbsI', 'AbsI64', 'Not', 'UnaryPlusI',
'BitnotI', 'UnaryPlusI64', 'BitnotI64', 'UnaryPlusF64', 'UnaryMinusF64', 'AbsF64', 'BitnotI', 'UnaryPlusI64', 'BitnotI64', 'UnaryPlusF64', 'UnaryMinusF64', 'AbsF64',
'Ze', 'Ze64', 'ToU8', 'ToU16', 'ToU32', 'ToFloat', 'Ze8ToI', 'Ze8ToI64', 'Ze16ToI', 'Ze16ToI64', 'Ze32ToI64', 'ZeIToI64',
'ToBiggestFloat', 'ToInt', 'ToBiggestInt', 'And', 'Or', 'EqStr', 'ToU8', 'ToU16', 'ToU32', 'ToFloat', 'ToBiggestFloat', 'ToInt',
'LeStr', 'LtStr', 'EqSet', 'LeSet', 'LtSet', 'MulSet', 'ToBiggestInt', 'CharToStr', 'BoolToStr', 'IntToStr', 'Int64ToStr', 'FloatToStr',
'PlusSet', 'MinusSet', 'SymDiffSet', 'ConStrStr', 'ConArrArr', 'ConArrT', 'CStrToStr', 'StrToStr', 'And', 'Or', 'EqStr', 'LeStr',
'ConTArr', 'ConTT', 'Slice', 'AppendStrCh', 'AppendStrStr', 'AppendSeqElem', 'LtStr', 'EqSet', 'LeSet', 'LtSet', 'MulSet', 'PlusSet',
'AppendSeqSeq', 'InRange', 'InSet', 'Is', 'Asgn', 'Repr', 'MinusSet', 'SymDiffSet', 'ConStrStr', 'ConArrArr', 'ConArrT', 'ConTArr',
'Exit', 'SetLengthStr', 'SetLengthSeq', 'Assert', 'Swap', 'Array', 'ConTT', 'Slice', 'AppendStrCh', 'AppendStrStr', 'AppendSeqElem', 'AppendSeqSeq',
'OpenArray', 'Range', 'Tuple', 'Set', 'Seq', 'CompileDate', 'InRange', 'InSet', 'Is', 'Asgn', 'Repr', 'Exit',
'CompileTime', 'NimrodVersion', 'NimrodMajor', 'NimrodMinor', 'NimrodPatch', 'CpuEndian' 'SetLengthStr', 'SetLengthSeq', 'Assert', 'Swap', 'IsNil', 'Array',
'OpenArray', 'Range', 'Set', 'Seq', 'CompileDate', 'CompileTime',
'NimrodVersion', 'NimrodMajor', 'NimrodMinor', 'NimrodPatch', 'CpuEndian', '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]]] //[[[end]]]
); );
@ -490,7 +515,7 @@ const
GenericTypes: TTypeKinds = {@set}[tyGeneric, tyGenericParam]; GenericTypes: TTypeKinds = {@set}[tyGeneric, tyGenericParam];
StructuralEquivTypes: TTypeKinds = {@set}[ StructuralEquivTypes: TTypeKinds = {@set}[
tyEmptySet, tyArrayConstr, tyNil, tyRecordConstr, tyTuple, tyEmptySet, tyArrayConstr, tyNil, tyTuple,
tyArray, tyArray,
tySet, tySet,
tyRange, tyRange,
@ -503,16 +528,16 @@ const
ConcreteTypes: TTypeKinds = {@set}[ ConcreteTypes: TTypeKinds = {@set}[
// types of the expr that may occur in:: // types of the expr that may occur in::
// var x = expr // var x = expr
tyBool, tyChar, tyEnum, tyArray, tyRecord, tyObject, tySet, tyTuple, tyBool, tyChar, tyEnum, tyArray, tyObject, tySet, tyTuple,
tyRange, tyPtr, tyRef, tyVar, tySequence, tyProc, tyRange, tyPtr, tyRef, tyVar, tySequence, tyProc,
tyPointer, tyOpenArray, tyPointer, tyOpenArray,
tyString, tyCString, tyString, tyCString,
tyInt..tyInt64, tyInt..tyInt64,
tyFloat..tyFloat128 tyFloat..tyFloat128
]; ];
ConstantDataTypes: TTypeKinds = {@set}[tyArray, tyRecord, tySet, tyTuple]; ConstantDataTypes: TTypeKinds = {@set}[tyArray, tySet, tyTuple];
ExportableSymKinds = {@set}[skVar, skConst, skProc, skType, skEnumField, ExportableSymKinds = {@set}[skVar, skConst, skProc, skType,
skIterator, skMacro, skTemplate]; skIterator, skMacro, skTemplate, skConverter];
namePos = 0; namePos = 0;
genericParamsPos = 1; genericParamsPos = 1;
paramsPos = 2; paramsPos = 2;
@ -534,7 +559,7 @@ function newIntTypeNode(kind: TNodeKind; const intVal: BiggestInt;
typ: PType): PNode; typ: PType): PNode;
function newFloatNode(kind: TNodeKind; const floatVal: BiggestFloat): PNode; function newFloatNode(kind: TNodeKind; const floatVal: BiggestFloat): PNode;
function newStrNode(kind: TNodeKind; const strVal: string): PNode; function newStrNode(kind: TNodeKind; const strVal: string): PNode;
function newIdentNode(ident: PIdent): PNode; function newIdentNode(ident: PIdent; const info: TLineInfo): PNode;
function newSymNode(sym: PSym): PNode; function newSymNode(sym: PSym): PNode;
function newNodeI(kind: TNodeKind; const info: TLineInfo): PNode; function newNodeI(kind: TNodeKind; const info: TLineInfo): PNode;
function newNodeIT(kind: TNodeKind; const info: TLineInfo; typ: PType): PNode; function newNodeIT(kind: TNodeKind; const info: TLineInfo; typ: PType): PNode;
@ -548,7 +573,7 @@ procedure initNodeTable(out x: TNodeTable);
// copy procs: // copy procs:
function copyType(t: PType; owner: PSym): PType; function copyType(t: PType; owner: PSym): PType;
function copySym(s: PSym; owner: PSym): PSym; function copySym(s: PSym; keepId: bool = false): PSym;
procedure assignType(dest, src: PType); procedure assignType(dest, src: PType);
procedure copyStrTable(out dest: TStrTable; const src: TStrTable); procedure copyStrTable(out dest: TStrTable; const src: TStrTable);
@ -620,7 +645,7 @@ begin
if b.kind in [nkStrLit..nkTripleStrLit] then if b.kind in [nkStrLit..nkTripleStrLit] then
result := a.strVal <= b.strVal; result := a.strVal <= b.strVal;
end end
else assert(false); else InternalError(a.info, 'leValue');
end end
end; end;
@ -638,7 +663,7 @@ begin
if b.kind in [nkStrLit..nkTripleStrLit] then if b.kind in [nkStrLit..nkTripleStrLit] then
result := a.strVal = b.strVal; result := a.strVal = b.strVal;
end end
else assert(false); else InternalError(a.info, 'SameValue');
end end
end; end;
@ -652,7 +677,7 @@ begin
nkStrLit..nkTripleStrLit: nkStrLit..nkTripleStrLit:
result := a.strVal; result := a.strVal;
else begin else begin
assert(false); InternalError(a.info, 'valueToString');
result := '' result := ''
end end
end end
@ -663,6 +688,9 @@ var
i: int; i: int;
begin begin
dest.counter := src.counter; dest.counter := src.counter;
{@emit
if isNil(src.data) then exit;
}
setLength(dest.data, length(src.data)); setLength(dest.data, length(src.data));
for i := 0 to high(src.data) do for i := 0 to high(src.data) do
dest.data[i] := src.data[i]; dest.data[i] := src.data[i];
@ -673,6 +701,9 @@ var
i: int; i: int;
begin begin
dest.counter := src.counter; dest.counter := src.counter;
{@emit
if isNil(src.data) then exit;
}
setLength(dest.data, length(src.data)); setLength(dest.data, length(src.data));
for i := 0 to high(src.data) do for i := 0 to high(src.data) do
dest.data[i] := src.data[i]; dest.data[i] := src.data[i];
@ -683,6 +714,9 @@ var
i: int; i: int;
begin begin
dest.counter := src.counter; dest.counter := src.counter;
{@emit
if isNil(src.data) then exit;
}
setLength(dest.data, length(src.data)); setLength(dest.data, length(src.data));
for i := 0 to high(src.data) do for i := 0 to high(src.data) do
dest.data[i] := src.data[i]; dest.data[i] := src.data[i];
@ -700,7 +734,7 @@ begin
FillChar(result^, sizeof(result^), 0); FillChar(result^, sizeof(result^), 0);
{@emit} {@emit}
result.kind := kind; result.kind := kind;
result.info := UnknownLineInfo; result.info := UnknownLineInfo();
end; end;
function newIntNode(kind: TNodeKind; const intVal: BiggestInt): PNode; function newIntNode(kind: TNodeKind; const intVal: BiggestInt): PNode;
@ -728,10 +762,11 @@ begin
result.strVal := strVal result.strVal := strVal
end; end;
function newIdentNode(ident: PIdent): PNode; function newIdentNode(ident: PIdent; const info: TLineInfo): PNode;
begin begin
result := newNode(nkIdent); result := newNode(nkIdent);
result.ident := ident result.ident := ident;
result.info := info;
end; end;
function newSymNode(sym: PSym): PNode; function newSymNode(sym: PSym): PNode;
@ -778,6 +813,7 @@ begin
dest.n := src.n; dest.n := src.n;
dest.size := src.size; dest.size := src.size;
dest.align := src.align; dest.align := src.align;
dest.containerID := src.containerID;
newSons(dest, sonsLen(src)); newSons(dest, sonsLen(src));
for i := 0 to sonsLen(src)-1 do for i := 0 to sonsLen(src)-1 do
dest.sons[i] := src.sons[i]; dest.sons[i] := src.sons[i];
@ -793,14 +829,13 @@ begin
// backend-info should not be copied // backend-info should not be copied
end; end;
function copySym(s: PSym; owner: PSym): PSym; function copySym(s: PSym; keepId: bool = false): PSym;
begin begin
result := newSym(s.kind, s.name, owner); result := newSym(s.kind, s.name, s.owner);
result.ast := nil; // BUGFIX; was: s.ast which made problems result.ast := nil; // BUGFIX; was: s.ast which made problems
result.info := s.info; result.info := s.info;
result.typ := s.typ; result.typ := s.typ;
if owner = s.owner then result.id := s.id if keepId then result.id := s.id else result.id := getID();
else result.id := getID();
result.flags := s.flags; result.flags := s.flags;
result.magic := s.magic; result.magic := s.magic;
copyStrTable(result.tab, s.tab); copyStrTable(result.tab, s.tab);
@ -820,7 +855,7 @@ begin
result.Name := Name; result.Name := Name;
result.Kind := symKind; result.Kind := symKind;
result.flags := {@set}[]; result.flags := {@set}[];
result.info := UnknownLineInfo; result.info := UnknownLineInfo();
result.options := gOptions; result.options := gOptions;
result.owner := owner; result.owner := owner;
result.offset := -1; result.offset := -1;
@ -972,7 +1007,7 @@ begin
result := newNode(src.kind); result := newNode(src.kind);
result.info := src.info; result.info := src.info;
result.typ := src.typ; result.typ := src.typ;
result.base := src.base; result.flags := src.flags;
case src.Kind of case src.Kind of
nkCharLit..nkInt64Lit: nkCharLit..nkInt64Lit:
result.intVal := src.intVal; result.intVal := src.intVal;
@ -984,6 +1019,8 @@ begin
result.ident := src.ident; result.ident := src.ident;
nkStrLit..nkTripleStrLit: nkStrLit..nkTripleStrLit:
result.strVal := src.strVal; result.strVal := src.strVal;
nkMetaNode:
result.nodePtr := src.nodePtr;
else begin end; else begin end;
end; end;
end; end;
@ -994,12 +1031,31 @@ var
i: int; i: int;
begin begin
if src = nil then begin result := nil; exit end; if src = nil then begin result := nil; exit end;
result := copyNode(src); result := newNode(src.kind);
result.sons := nil; // BUGFIX result.info := src.info;
result.typ := src.typ;
result.flags := src.flags;
case src.Kind of
nkCharLit..nkInt64Lit:
result.intVal := src.intVal;
nkFloatLit, nkFloat32Lit, nkFloat64Lit:
result.floatVal := src.floatVal;
nkSym:
result.sym := src.sym;
nkIdent:
result.ident := src.ident;
nkStrLit..nkTripleStrLit:
result.strVal := src.strVal;
nkMetaNode:
result.nodePtr := src.nodePtr;
else begin
result.sons := nil;
newSons(result, sonsLen(src)); newSons(result, sonsLen(src));
for i := 0 to sonsLen(src)-1 do for i := 0 to sonsLen(src)-1 do
result.sons[i] := copyTree(src.sons[i]); result.sons[i] := copyTree(src.sons[i]);
end; end;
end
end;
function lastSon(n: PNode): PNode; function lastSon(n: PNode): PNode;
begin begin

View file

@ -136,6 +136,10 @@ procedure debug(n: PNode); overload;
function IdTableGet(const t: TIdTable; key: PIdObj): PObject; function IdTableGet(const t: TIdTable; key: PIdObj): PObject;
procedure IdTablePut(var t: TIdTable; key: PIdObj; val: PObject); procedure IdTablePut(var t: TIdTable; key: PIdObj; val: PObject);
function IdTableHasObjectAsKey(const t: TIdTable; key: PIdObj): bool;
// checks if `t` contains the `key` (compared by the pointer value, not only
// `key`'s id)
function IdNodeTableGet(const t: TIdNodeTable; key: PIdObj): PNode; function IdNodeTableGet(const t: TIdNodeTable; key: PIdObj): PNode;
procedure IdNodeTablePut(var t: TIdNodeTable; key: PIdObj; val: PNode); procedure IdNodeTablePut(var t: TIdNodeTable; key: PIdObj; val: PNode);
@ -180,8 +184,6 @@ function nextTry(h, maxHash: THash): THash;
implementation implementation
function lookupInRecord(n: PNode; field: PIdent): PSym; function lookupInRecord(n: PNode; field: PIdent): PSym;
// XXX: transform in a node that contains the runtime check for the
// field, if it is in a case-part...
var var
i: int; i: int;
begin begin
@ -194,7 +196,7 @@ begin
end end
end; end;
nkRecCase: begin nkRecCase: begin
assert(n.sons[0].kind = nkSym); if (n.sons[0].kind <> nkSym) then InternalError(n.info, 'lookupInRecord');
result := lookupInRecord(n.sons[0], field); result := lookupInRecord(n.sons[0], field);
if result <> nil then exit; if result <> nil then exit;
for i := 1 to sonsLen(n)-1 do begin for i := 1 to sonsLen(n)-1 do begin
@ -203,7 +205,7 @@ begin
result := lookupInRecord(lastSon(n.sons[i]), field); result := lookupInRecord(lastSon(n.sons[i]), field);
if result <> nil then exit; if result <> nil then exit;
end; end;
else internalError('lookupInRecord(record case branch)'); else internalError(n.info, 'lookupInRecord(record case branch)');
end end
end end
end; end;
@ -226,7 +228,8 @@ var
i: int; i: int;
begin begin
for i := start to sonsLen(list)-1 do begin for i := start to sonsLen(list)-1 do begin
assert(list.sons[i].kind = nkSym); if list.sons[i].kind <> nkSym then
InternalError(list.info, 'getSymFromList');
result := list.sons[i].sym; result := list.sons[i].sym;
if result.name.id = ident.id then exit if result.name.id = ident.id then exit
end; end;
@ -342,7 +345,7 @@ end;
function lineInfoToStr(const info: TLineInfo): PRope; function lineInfoToStr(const info: TLineInfo): PRope;
begin begin
result := ropeFormat('[$1, $2, $3]', [makeYamlString(toFilename(info)), result := ropef('[$1, $2, $3]', [makeYamlString(toFilename(info)),
toRope(toLinenumber(info)), toRope(toColumn(info))]); toRope(toLinenumber(info)), toRope(toColumn(info))]);
end; end;
@ -367,11 +370,11 @@ begin
for i := 0 to high(n.data) do for i := 0 to high(n.data) do
if n.data[i] <> nil then begin if n.data[i] <> nil then begin
if mycount > 0 then app(result, ','+''); if mycount > 0 then app(result, ','+'');
appRopeFormat(result, '$n$1$2', appf(result, '$n$1$2',
[istr, symToYamlAux(n.data[i], marker, indent+2, maxRecDepth-1)]); [istr, symToYamlAux(n.data[i], marker, indent+2, maxRecDepth-1)]);
inc(mycount) inc(mycount)
end; end;
if mycount > 0 then appRopeFormat(result, '$n$1', [spaces(indent)]); if mycount > 0 then appf(result, '$n$1', [spaces(indent)]);
app(result, ']'+''); app(result, ']'+'');
assert(mycount = n.counter); assert(mycount = n.counter);
end; end;
@ -387,10 +390,10 @@ begin
i := 0; i := 0;
while i <= high(c) do begin while i <= high(c) do begin
if i > 0 then app(result, ','+''); if i > 0 then app(result, ','+'');
appRopeFormat(result, '$n$1"$2": $3', [istr, c[i], c[i+1]]); appf(result, '$n$1"$2": $3', [istr, c[i], c[i+1]]);
inc(i, 2) inc(i, 2)
end; end;
appRopeFormat(result, '$n$1}', [spaces(indent)]); appf(result, '$n$1}', [spaces(indent)]);
end; end;
function symToYamlAux(n: PSym; var marker: TObjectSet; function symToYamlAux(n: PSym; var marker: TObjectSet;
@ -401,7 +404,7 @@ begin
if n = nil then if n = nil then
result := toRope('null') result := toRope('null')
else if ObjectSetContainsOrIncl(marker, n) then else if ObjectSetContainsOrIncl(marker, n) then
result := ropeFormat('"$1 @$2"', [ result := ropef('"$1 @$2"', [
toRope(n.name.s), toRope(n.name.s),
toRope(strutils.toHex({@cast}TAddress(n), sizeof(n)*2))]) toRope(strutils.toHex({@cast}TAddress(n), sizeof(n)*2))])
else begin else begin
@ -427,7 +430,7 @@ begin
if n = nil then if n = nil then
result := toRope('null') result := toRope('null')
else if objectSetContainsOrIncl(marker, n) then else if objectSetContainsOrIncl(marker, n) then
result := ropeFormat('"$1 @$2"', [ result := ropef('"$1 @$2"', [
toRope(typeKindToStr[n.kind]), toRope(typeKindToStr[n.kind]),
toRope(strutils.toHex({@cast}TAddress(n), sizeof(n)*2))]) toRope(strutils.toHex({@cast}TAddress(n), sizeof(n)*2))])
else begin else begin
@ -453,48 +456,48 @@ begin
result := toRope('null') result := toRope('null')
else begin else begin
istr := spaces(indent+2); istr := spaces(indent+2);
result := ropeFormat('{$n$1"kind": $2', result := ropef('{$n$1"kind": $2',
[istr, makeYamlString(nodeKindToStr[n.kind])]); [istr, makeYamlString(nodeKindToStr[n.kind])]);
if maxRecDepth <> 0 then begin if maxRecDepth <> 0 then begin
appRopeFormat(result, ',$n$1"typ": $2', appf(result, ',$n$1"info": $2',
[istr, typeToYamlAux(n.typ, marker, indent+2, maxRecDepth)]);
appRopeFormat(result, ',$n$1"info": $2',
[istr, lineInfoToStr(n.info)]); [istr, lineInfoToStr(n.info)]);
case n.kind of case n.kind of
nkCharLit..nkInt64Lit: nkCharLit..nkInt64Lit:
appRopeFormat(result, '$n$1"intVal": $2', [istr, toRope(n.intVal)]); appf(result, '$n$1"intVal": $2', [istr, toRope(n.intVal)]);
nkFloatLit, nkFloat32Lit, nkFloat64Lit: nkFloatLit, nkFloat32Lit, nkFloat64Lit:
appRopeFormat(result, '$n$1"floatVal": $2', appf(result, '$n$1"floatVal": $2',
[istr, toRopeF(n.floatVal)]); [istr, toRopeF(n.floatVal)]);
nkStrLit..nkTripleStrLit: nkStrLit..nkTripleStrLit:
appRopeFormat(result, '$n$1"strVal": $2', appf(result, '$n$1"strVal": $2',
[istr, makeYamlString(n.strVal)]); [istr, makeYamlString(n.strVal)]);
nkSym: nkSym:
appRopeFormat(result, ',$n$1"sym": $2', appf(result, ',$n$1"sym": $2',
[istr, symToYamlAux(n.sym, marker, indent+2, maxRecDepth)]); [istr, symToYamlAux(n.sym, marker, indent+2, maxRecDepth)]);
nkIdent: begin nkIdent: begin
if n.ident <> nil then if n.ident <> nil then
appRopeFormat(result, '$n$1"ident": $2', appf(result, '$n$1"ident": $2',
[istr, makeYamlString(n.ident.s)]) [istr, makeYamlString(n.ident.s)])
else else
appRopeFormat(result, '$n$1"ident": null', [istr]) appf(result, '$n$1"ident": null', [istr])
end end
else begin else begin
if sonsLen(n) > 0 then begin if sonsLen(n) > 0 then begin
appRopeFormat(result, ',$n$1"sons": [', [istr]); appf(result, ',$n$1"sons": [', [istr]);
for i := 0 to sonsLen(n)-1 do begin for i := 0 to sonsLen(n)-1 do begin
if i > 0 then app(result, ','+''); if i > 0 then app(result, ','+'');
appRopeFormat(result, '$n$1$2', appf(result, '$n$1$2',
[spaces(indent+4), [spaces(indent+4),
treeToYamlAux(n.sons[i], marker, indent + 4, maxRecDepth-1)]); treeToYamlAux(n.sons[i], marker, indent + 4, maxRecDepth-1)]);
end; end;
appRopeFormat(result, '$n$1]', [istr]); appf(result, '$n$1]', [istr]);
end
end end
end end
end; end;
appRopeFormat(result, '$n$1}', [spaces(indent)]); appf(result, ',$n$1"typ": $2',
[istr, typeToYamlAux(n.typ, marker, indent+2, maxRecDepth)]);
end;
appf(result, '$n$1}', [spaces(indent)]);
end end
end; end;
@ -523,19 +526,88 @@ begin
end; end;
// these are for debugging only: // these are for debugging only:
function debugType(n: PType): PRope;
var
i: int;
begin
if n = nil then
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]);
end;
app(result, ')'+'');
end
end;
function debugTree(n: PNode; indent: int; maxRecDepth: int): PRope;
var
istr: PRope;
i: int;
begin
if n = nil then
result := toRope('null')
else begin
istr := spaces(indent+2);
result := ropef('{$n$1"kind": $2',
[istr, makeYamlString(nodeKindToStr[n.kind])]);
if maxRecDepth <> 0 then begin
case n.kind of
nkCharLit..nkInt64Lit:
appf(result, '$n$1"intVal": $2', [istr, toRope(n.intVal)]);
nkFloatLit, nkFloat32Lit, nkFloat64Lit:
appf(result, '$n$1"floatVal": $2',
[istr, toRopeF(n.floatVal)]);
nkStrLit..nkTripleStrLit:
appf(result, '$n$1"strVal": $2',
[istr, makeYamlString(n.strVal)]);
nkSym:
appf(result, ',$n$1"sym": $2_$3',
[istr, toRope(n.sym.name.s), toRope(n.sym.id)]);
nkIdent: begin
if n.ident <> nil then
appf(result, '$n$1"ident": $2',
[istr, makeYamlString(n.ident.s)])
else
appf(result, '$n$1"ident": null', [istr])
end
else begin
if sonsLen(n) > 0 then begin
appf(result, ',$n$1"sons": [', [istr]);
for i := 0 to sonsLen(n)-1 do begin
if i > 0 then app(result, ','+'');
appf(result, '$n$1$2',
[spaces(indent+4),
debugTree(n.sons[i], indent + 4, maxRecDepth-1)]);
end;
appf(result, '$n$1]', [istr]);
end
end
end;
end;
appf(result, '$n$1}', [spaces(indent)]);
end
end;
procedure debug(n: PSym); overload; procedure debug(n: PSym); overload;
begin begin
writeln(output, ropeToStr(symToYaml(n, 0, 3))); writeln(output, ropeToStr(ropef('$1_$2', [toRope(n.name.s), toRope(n.id)])));
end; end;
procedure debug(n: PType); overload; procedure debug(n: PType); overload;
begin begin
writeln(output, ropeToStr(typeToYaml(n, 0, 3))); writeln(output, ropeToStr(debugType(n)));
end; end;
procedure debug(n: PNode); overload; procedure debug(n: PNode); overload;
begin begin
writeln(output, ropeToStr(treeToYaml(n, 0, -1))); writeln(output, ropeToStr(debugTree(n, 0, 100)));
end; end;
// -------------------- node sets -------------------------------------------- // -------------------- node sets --------------------------------------------
@ -748,7 +820,8 @@ var
begin begin
h := n.name.h and high(data); h := n.name.h and high(data);
while data[h] <> nil do begin while data[h] <> nil do begin
assert(data[h] <> n); if data[h] = n then
InternalError(n.info, 'StrTableRawInsert: ' + n.name.s);
h := nextTry(h, high(data)) h := nextTry(h, high(data))
end; end;
assert(data[h] = nil); assert(data[h] = nil);
@ -963,6 +1036,15 @@ begin
result := -1 result := -1
end; end;
function IdTableHasObjectAsKey(const t: TIdTable; key: PIdObj): bool;
var
index: int;
begin
index := IdTableRawGet(t, key);
if index >= 0 then result := t.data[index].key = key
else result := false
end;
function IdTableGet(const t: TIdTable; key: PIdObj): PObject; function IdTableGet(const t: TIdTable; key: PIdObj): PObject;
var var
index: int; index: int;
@ -999,6 +1081,7 @@ begin
end end
else begin else begin
if mustRehash(length(t.data), t.counter) then begin if mustRehash(length(t.data), t.counter) then begin
{@emit n := [];}
setLength(n, length(t.data) * growthFactor); setLength(n, length(t.data) * growthFactor);
{@ignore} {@ignore}
fillChar(n[0], length(n)*sizeof(n[0]), 0); fillChar(n[0], length(n)*sizeof(n[0]), 0);
@ -1083,6 +1166,7 @@ begin
end end
else begin else begin
if mustRehash(length(t.data), t.counter) then begin if mustRehash(length(t.data), t.counter) then begin
{@emit n := [];}
setLength(n, length(t.data) * growthFactor); setLength(n, length(t.data) * growthFactor);
{@ignore} {@ignore}
fillChar(n[0], length(n)*sizeof(n[0]), 0); fillChar(n[0], length(n)*sizeof(n[0]), 0);

View file

@ -49,17 +49,20 @@ end;
procedure BitSetIncl(var x: TBitSet; const elem: BiggestInt); procedure BitSetIncl(var x: TBitSet; const elem: BiggestInt);
begin begin
x[int(elem div ElemSize)] := x[int(elem div ElemSize)] or (1 shl (elem mod ElemSize)) assert(elem >= 0);
x[int(elem div ElemSize)] := toU8(x[int(elem div ElemSize)] or
int(1 shl (elem mod ElemSize)))
end; end;
procedure BitSetExcl(var x: TBitSet; const elem: BiggestInt); procedure BitSetExcl(var x: TBitSet; const elem: BiggestInt);
begin begin
x[int(elem div ElemSize)] := x[int(elem div ElemSize)] and x[int(elem div ElemSize)] := toU8(x[int(elem div ElemSize)] and
not (1 shl (elem mod ElemSize)) not int(1 shl (elem mod ElemSize)))
end; end;
procedure BitSetInit(out b: TBitSet; len: int); procedure BitSetInit(out b: TBitSet; len: int);
begin begin
{@emit b := [];}
setLength(b, len); setLength(b, len);
{@ignore} {@ignore}
fillChar(b[0], length(b)*sizeof(b[0]), 0); fillChar(b[0], length(b)*sizeof(b[0]), 0);
@ -70,28 +73,28 @@ procedure BitSetUnion(var x: TBitSet; const y: TBitSet);
var var
i: int; i: int;
begin begin
for i := 0 to high(x) do x[i] := x[i] or int(y[i]) for i := 0 to high(x) do x[i] := toU8(x[i] or int(y[i]))
end; end;
procedure BitSetDiff(var x: TBitSet; const y: TBitSet); procedure BitSetDiff(var x: TBitSet; const y: TBitSet);
var var
i: int; i: int;
begin begin
for i := 0 to high(x) do x[i] := x[i] and not int(y[i]) for i := 0 to high(x) do x[i] := toU8(x[i] and not int(y[i]))
end; end;
procedure BitSetSymDiff(var x: TBitSet; const y: TBitSet); procedure BitSetSymDiff(var x: TBitSet; const y: TBitSet);
var var
i: int; i: int;
begin begin
for i := 0 to high(x) do x[i] := x[i] xor int(y[i]) for i := 0 to high(x) do x[i] := toU8(x[i] xor int(y[i]))
end; end;
procedure BitSetIntersect(var x: TBitSet; const y: TBitSet); procedure BitSetIntersect(var x: TBitSet; const y: TBitSet);
var var
i: int; i: int;
begin begin
for i := 0 to high(x) do x[i] := x[i] and int(y[i]) for i := 0 to high(x) do x[i] := toU8(x[i] and int(y[i]))
end; end;
function BitSetEquals(const x, y: TBitSet): Boolean; function BitSetEquals(const x, y: TBitSet): Boolean;

File diff suppressed because it is too large Load diff

View file

@ -18,17 +18,25 @@ begin
line := toLinenumber(t.info); // BUGFIX line := toLinenumber(t.info); // BUGFIX
if line < 0 then line := 0; // negative numbers are not allowed in #line if line < 0 then line := 0; // negative numbers are not allowed in #line
if optLineDir in p.Options then if optLineDir in p.Options then
appRopeFormat(p.s[cpsStmts], '#line $2 "$1"$n', appf(p.s[cpsStmts], '#line $2 "$1"$n',
[toRope(toFilename(t.info)), toRope(line)]); [toRope(toFilename(t.info)), toRope(line)]);
if ([optStackTrace, optEndb] * p.Options = [optStackTrace, optEndb]) and if ([optStackTrace, optEndb] * p.Options = [optStackTrace, optEndb]) and
((p.prc = nil) or not (sfPure in p.prc.flags)) then begin ((p.prc = nil) or not (sfPure in p.prc.flags)) then begin
useMagic('endb'); // new: endb support useMagic(p.module, 'endb'); // new: endb support
appRopeFormat(p.s[cpsStmts], 'endb($1);$n', [toRope(line)]) appf(p.s[cpsStmts], 'endb($1);$n', [toRope(line)])
end end
else if ([optLineTrace, optStackTrace] * p.Options = else if ([optLineTrace, optStackTrace] * p.Options =
[optLineTrace, optStackTrace]) and ((p.prc = nil) or [optLineTrace, optStackTrace]) and ((p.prc = nil) or
not (sfPure in p.prc.flags)) then not (sfPure in p.prc.flags)) then
appRopeFormat(p.s[cpsStmts], 'F.line = $1;$n', [toRope(line)]) appf(p.s[cpsStmts], 'F.line = $1;$n', [toRope(line)])
end;
procedure finishTryStmt(p: BProc; howMany: int);
var
i: int;
begin
for i := 1 to howMany do
app(p.s[cpsStmts], 'excHandler = excHandler->prev;' + tnl);
end; end;
procedure genReturnStmt(p: BProc; t: PNode); procedure genReturnStmt(p: BProc; t: PNode);
@ -36,15 +44,16 @@ begin
p.beforeRetNeeded := true; p.beforeRetNeeded := true;
genLineDir(p, t); genLineDir(p, t);
if (t.sons[0] <> nil) then genStmts(p, t.sons[0]); if (t.sons[0] <> nil) then genStmts(p, t.sons[0]);
finishTryStmt(p, p.nestedTryStmts);
app(p.s[cpsStmts], 'goto BeforeRet;' + tnl) app(p.s[cpsStmts], 'goto BeforeRet;' + tnl)
end; end;
procedure genObjectInit(p: BProc; sym: PSym); procedure genObjectInit(p: BProc; sym: PSym);
begin begin
if containsObject(sym.typ) then begin if containsObject(sym.typ) then begin
useMagic('objectInit'); useMagic(p.module, 'objectInit');
appRopeFormat(p.s[cpsInit], 'objectInit($1, $2);$n', appf(p.s[cpsInit], 'objectInit($1, $2);$n',
[addrLoc(sym.loc), genTypeInfo(currMod, sym.typ)]) [addrLoc(sym.loc), genTypeInfo(p.module, sym.typ)])
end end
end; end;
@ -52,11 +61,11 @@ procedure initVariable(p: BProc; v: PSym);
begin begin
if containsGarbageCollectedRef(v.typ) or (v.ast = nil) then if containsGarbageCollectedRef(v.typ) or (v.ast = nil) then
// Language change: always initialize variables if v.ast == nil! // Language change: always initialize variables if v.ast == nil!
if not (skipAbstract(v.typ).Kind in [tyArray, tyArrayConstr, tySet, if not (skipVarGenericRange(v.typ).Kind in [tyArray, tyArrayConstr, tySet,
tyRecord, tyTuple, tyObject]) then tyTuple, tyObject]) then
appRopeFormat(p.s[cpsInit], '$1 = 0;$n', [v.loc.r]) appf(p.s[cpsStmts], '$1 = 0;$n', [v.loc.r])
else else
appRopeFormat(p.s[cpsInit], 'memset((void*)&$1, 0, sizeof($1));$n', appf(p.s[cpsStmts], 'memset((void*)&$1, 0, sizeof($1));$n',
[v.loc.r]) [v.loc.r])
end; end;
@ -73,7 +82,7 @@ begin
assert(a.sons[0].kind = nkSym); assert(a.sons[0].kind = nkSym);
v := a.sons[0].sym; v := a.sons[0].sym;
if sfGlobal in v.flags then if sfGlobal in v.flags then
assignGlobalVar(v) assignGlobalVar(p.module, v)
else begin else begin
assignLocalVar(p, v); assignLocalVar(p, v);
initVariable(p, v) // XXX: this is not required if a.sons[2] != nil, initVariable(p, v) // XXX: this is not required if a.sons[2] != nil,
@ -95,19 +104,20 @@ var
begin begin
for i := 0 to sonsLen(t)-1 do begin for i := 0 to sonsLen(t)-1 do begin
if t.sons[i].kind = nkCommentStmt then continue; if t.sons[i].kind = nkCommentStmt then continue;
assert(t.sons[i].kind = nkConstDef); if t.sons[i].kind <> nkConstDef then InternalError(t.info, 'genConstStmt');
c := t.sons[i].sons[0].sym; c := t.sons[i].sons[0].sym;
// This can happen for forward consts: // This can happen for forward consts:
if (c.ast <> nil) and (c.typ.kind in ConstantDataTypes) and if (c.ast <> nil) and (c.typ.kind in ConstantDataTypes) and
not (lfNoDecl in c.loc.flags) then begin not (lfNoDecl in c.loc.flags) then begin
// generate the data: // generate the data:
fillLoc(c.loc, locData, c.typ, mangleName(c), {@set}[lfOnData]); fillLoc(c.loc, locData, c.typ, mangleName(c), OnUnknown);
if sfImportc in c.flags then if sfImportc in c.flags then
appRopeFormat(currMod.s[cfsData], 'extern $1$2 $3;$n', appf(p.module.s[cfsData], 'extern NIM_CONST $1 $2;$n',
[constTok, getTypeDesc(c.typ), c.loc.r]) [getTypeDesc(p.module, c.typ), c.loc.r])
else else
appRopeFormat(currMod.s[cfsData], '$1$2 $3 = $4;$n', appf(p.module.s[cfsData], 'NIM_CONST $1 $2 = $3;$n',
[constTok, getTypeDesc(c.typ), c.loc.r, genConstExpr(p, c.ast)]) [getTypeDesc(p.module, c.typ), c.loc.r,
genConstExpr(p, c.ast)])
end end
end end
end; end;
@ -139,11 +149,11 @@ begin
nkElifBranch: begin nkElifBranch: begin
a := initLocExpr(p, it.sons[0]); a := initLocExpr(p, it.sons[0]);
Lelse := getLabel(p); Lelse := getLabel(p);
appRopeFormat(p.s[cpsStmts], 'if (!$1) goto $2;$n', [rdLoc(a), Lelse]); appf(p.s[cpsStmts], 'if (!$1) goto $2;$n', [rdLoc(a), Lelse]);
freeTemp(p, a); freeTemp(p, a);
genStmts(p, it.sons[1]); genStmts(p, it.sons[1]);
if sonsLen(n) > 1 then if sonsLen(n) > 1 then
appRopeFormat(p.s[cpsStmts], 'goto $1;$n', [Lend]); appf(p.s[cpsStmts], 'goto $1;$n', [Lend]);
fixLabel(p, Lelse); fixLabel(p, Lelse);
end; end;
nkElse: begin nkElse: begin
@ -166,17 +176,18 @@ var
begin begin
genLineDir(p, t); genLineDir(p, t);
assert(sonsLen(t) = 2); assert(sonsLen(t) = 2);
inc(p.unique); inc(p.labels);
Labl := con('L'+'', toRope(p.unique)); Labl := con('L'+'', toRope(p.labels));
len := length(p.blocks); len := length(p.blocks);
setLength(p.blocks, len+1); setLength(p.blocks, len+1);
p.blocks[len] := p.unique; // positive because we use it right away: p.blocks[len].id := p.labels; // positive because we use it right away:
p.blocks[len].nestedTryStmts := p.nestedTryStmts;
app(p.s[cpsStmts], 'while (1) {' + tnl); app(p.s[cpsStmts], 'while (1) {' + tnl);
a := initLocExpr(p, t.sons[0]); a := initLocExpr(p, t.sons[0]);
appRopeFormat(p.s[cpsStmts], 'if (!$1) goto $2;$n', [rdLoc(a), Labl]); appf(p.s[cpsStmts], 'if (!$1) goto $2;$n', [rdLoc(a), Labl]);
freeTemp(p, a); freeTemp(p, a);
genStmts(p, t.sons[1]); genStmts(p, t.sons[1]);
appRopeFormat(p.s[cpsStmts], '} $1: ;$n', [Labl]); appf(p.s[cpsStmts], '} $1: ;$n', [Labl]);
setLength(p.blocks, length(p.blocks)-1) setLength(p.blocks, length(p.blocks)-1)
end; end;
@ -185,7 +196,7 @@ var
idx: int; idx: int;
sym: PSym; sym: PSym;
begin begin
inc(p.unique); inc(p.labels);
idx := length(p.blocks); idx := length(p.blocks);
if t.sons[0] <> nil then begin // named block? if t.sons[0] <> nil then begin // named block?
assert(t.sons[0].kind = nkSym); assert(t.sons[0].kind = nkSym);
@ -194,14 +205,22 @@ begin
sym.loc.a := idx sym.loc.a := idx
end; end;
setLength(p.blocks, idx+1); setLength(p.blocks, idx+1);
p.blocks[idx] := -p.unique; // negative because it isn't used yet p.blocks[idx].id := -p.labels; // negative because it isn't used yet
p.blocks[idx].nestedTryStmts := p.nestedTryStmts;
if t.kind = nkBlockExpr then genStmtListExpr(p, t.sons[1], d) if t.kind = nkBlockExpr then genStmtListExpr(p, t.sons[1], d)
else genStmts(p, t.sons[1]); else genStmts(p, t.sons[1]);
if p.blocks[idx] > 0 then // label has been used: if p.blocks[idx].id > 0 then // label has been used:
appRopeFormat(p.s[cpsStmts], 'L$1: ;$n', [toRope(p.blocks[idx])]); appf(p.s[cpsStmts], 'L$1: ;$n', [toRope(p.blocks[idx].id)]);
setLength(p.blocks, idx) setLength(p.blocks, idx)
end; end;
// try:
// while:
// try:
// if ...:
// break # we need to finish only one try statement here!
// finally:
procedure genBreakStmt(p: BProc; t: PNode); procedure genBreakStmt(p: BProc; t: PNode);
var var
idx: int; idx: int;
@ -215,8 +234,9 @@ begin
assert(sym.loc.k = locOther); assert(sym.loc.k = locOther);
idx := sym.loc.a idx := sym.loc.a
end; end;
p.blocks[idx] := abs(p.blocks[idx]); // label is used p.blocks[idx].id := abs(p.blocks[idx].id); // label is used
appRopeFormat(p.s[cpsStmts], 'goto L$1;$n', [toRope(p.blocks[idx])]) finishTryStmt(p, p.nestedTryStmts - p.blocks[idx].nestedTryStmts);
appf(p.s[cpsStmts], 'goto L$1;$n', [toRope(p.blocks[idx].id)])
end; end;
procedure genAsmStmt(p: BProc; t: PNode); procedure genAsmStmt(p: BProc; t: PNode);
@ -245,15 +265,15 @@ begin
InternalError(t.sons[i].info, 'genAsmStmt()') InternalError(t.sons[i].info, 'genAsmStmt()')
end end
end; end;
appRopeFormat(p.s[cpsStmts], CC[ccompiler].asmStmtFrmt, [s]); appf(p.s[cpsStmts], CC[ccompiler].asmStmtFrmt, [s]);
end; end;
function getRaiseFrmt(): string; function getRaiseFrmt(p: BProc): string;
begin begin
if gCmd = cmdCompileToCpp then if gCmd = cmdCompileToCpp then
result := 'throw nimException($1, $2);$n' result := 'throw nimException($1, $2);$n'
else begin else begin
useMagic('E_Base'); useMagic(p.module, 'E_Base');
result := 'raiseException((E_Base*)$1, $2);$n' result := 'raiseException((E_Base*)$1, $2);$n'
end end
end; end;
@ -266,14 +286,13 @@ var
begin begin
genLineDir(p, t); genLineDir(p, t);
if t.sons[0] <> nil then begin if t.sons[0] <> nil then begin
if gCmd <> cmdCompileToCpp then if gCmd <> cmdCompileToCpp then useMagic(p.module, 'raiseException');
useMagic('raiseException');
a := InitLocExpr(p, t.sons[0]); a := InitLocExpr(p, t.sons[0]);
e := rdLoc(a); e := rdLoc(a);
freeTemp(p, a); freeTemp(p, a);
typ := t.sons[0].typ; typ := t.sons[0].typ;
while typ.kind in [tyVar, tyRef, tyPtr] do typ := typ.sons[0]; while typ.kind in [tyVar, tyRef, tyPtr] do typ := typ.sons[0];
appRopeFormat(p.s[cpsStmts], getRaiseFrmt(), appf(p.s[cpsStmts], getRaiseFrmt(p),
[e, makeCString(typ.sym.name.s)]) [e, makeCString(typ.sym.name.s)])
end end
else begin else begin
@ -281,7 +300,7 @@ begin
if gCmd = cmdCompileToCpp then if gCmd = cmdCompileToCpp then
app(p.s[cpsStmts], 'throw;' + tnl) app(p.s[cpsStmts], 'throw;' + tnl)
else begin else begin
useMagic('reraiseException'); useMagic(p.module, 'reraiseException');
app(p.s[cpsStmts], 'reraiseException();' + tnl) app(p.s[cpsStmts], 'reraiseException();' + tnl)
end end
end end
@ -309,13 +328,13 @@ begin
y := initLocExpr(p, b.sons[i].sons[1]); y := initLocExpr(p, b.sons[i].sons[1]);
freeTemp(p, x); freeTemp(p, x);
freeTemp(p, y); freeTemp(p, y);
appRopeFormat(p.s[cpsStmts], rangeFormat, appf(p.s[cpsStmts], rangeFormat,
[rdCharLoc(e), rdCharLoc(x), rdCharLoc(y), labl]) [rdCharLoc(e), rdCharLoc(x), rdCharLoc(y), labl])
end end
else begin else begin
x := initLocExpr(p, b.sons[i]); x := initLocExpr(p, b.sons[i]);
freeTemp(p, x); freeTemp(p, x);
appRopeFormat(p.s[cpsStmts], eqFormat, appf(p.s[cpsStmts], eqFormat,
[rdCharLoc(e), rdCharLoc(x), labl]) [rdCharLoc(e), rdCharLoc(x), labl])
end end
end end
@ -328,11 +347,11 @@ var
begin begin
Lend := getLabel(p); Lend := getLabel(p);
for i := 1 to sonsLen(t) - 1 do begin for i := 1 to sonsLen(t) - 1 do begin
appRopeFormat(p.s[cpsStmts], 'L$1: ;$n', [toRope(labId+i)]); appf(p.s[cpsStmts], 'L$1: ;$n', [toRope(labId+i)]);
if t.sons[i].kind = nkOfBranch then begin if t.sons[i].kind = nkOfBranch then begin
len := sonsLen(t.sons[i]); len := sonsLen(t.sons[i]);
genStmts(p, t.sons[i].sons[len-1]); genStmts(p, t.sons[i].sons[len-1]);
appRopeFormat(p.s[cpsStmts], 'goto $1;$n', [Lend]) appf(p.s[cpsStmts], 'goto $1;$n', [Lend])
end end
else // else statement else // else statement
genStmts(p, t.sons[i].sons[0]) genStmts(p, t.sons[i].sons[0])
@ -349,15 +368,15 @@ var
begin begin
a := initLocExpr(p, t.sons[0]); a := initLocExpr(p, t.sons[0]);
// fist pass: gnerate ifs+goto: // fist pass: gnerate ifs+goto:
labId := p.unique; labId := p.labels;
for i := 1 to sonsLen(t) - 1 do begin for i := 1 to sonsLen(t) - 1 do begin
inc(p.unique); inc(p.labels);
if t.sons[i].kind = nkOfBranch then if t.sons[i].kind = nkOfBranch then
genCaseGenericBranch(p, t.sons[i], a, rangeFormat, eqFormat, genCaseGenericBranch(p, t.sons[i], a, rangeFormat, eqFormat,
con('L'+'', toRope(p.unique))) con('L'+'', toRope(p.labels)))
else else
// else statement // else statement
appRopeFormat(p.s[cpsStmts], 'goto L$1;$n', [toRope(p.unique)]); appf(p.s[cpsStmts], 'goto L$1;$n', [toRope(p.labels)]);
end; end;
// second pass: generate statements // second pass: generate statements
genCaseSecondPass(p, t, labId); genCaseSecondPass(p, t, labId);
@ -435,7 +454,7 @@ begin
freeTemp(p, x); freeTemp(p, x);
assert(b.sons[i].kind in [nkStrLit..nkTripleStrLit]); assert(b.sons[i].kind in [nkStrLit..nkTripleStrLit]);
j := int(hashString(b.sons[i].strVal) and high(branches)); j := int(hashString(b.sons[i].strVal) and high(branches));
appRopeFormat(branches[j], 'if (eqStrings($1, $2)) goto $3;$n', appf(branches[j], 'if (eqStrings($1, $2)) goto $3;$n',
[rdLoc(e), rdLoc(x), labl]) [rdLoc(e), rdLoc(x), labl])
end end
end; end;
@ -446,38 +465,39 @@ var
a: TLoc; a: TLoc;
branches: TRopeSeq; branches: TRopeSeq;
begin begin
useMagic('eqStrings'); useMagic(p.module, 'eqStrings');
// count how many constant strings there are in the case: // count how many constant strings there are in the case:
strings := 0; strings := 0;
for i := 1 to sonsLen(t)-1 do for i := 1 to sonsLen(t)-1 do
if t.sons[i].kind = nkOfBranch then inc(strings, sonsLen(t.sons[i])-1); if t.sons[i].kind = nkOfBranch then inc(strings, sonsLen(t.sons[i])-1);
if strings > stringCaseThreshold then begin if strings > stringCaseThreshold then begin
useMagic('hashString'); useMagic(p.module, 'hashString');
bitMask := nmath.nextPowerOfTwo(strings)-1; bitMask := nmath.nextPowerOfTwo(strings)-1;
setLength(branches, bitMask+1); setLength(branches, bitMask+1);
a := initLocExpr(p, t.sons[0]); a := initLocExpr(p, t.sons[0]);
// fist pass: gnerate ifs+goto: // fist pass: gnerate ifs+goto:
labId := p.unique; labId := p.labels;
for i := 1 to sonsLen(t) - 1 do begin for i := 1 to sonsLen(t) - 1 do begin
inc(p.unique); inc(p.labels);
if t.sons[i].kind = nkOfBranch then if t.sons[i].kind = nkOfBranch then
genCaseStringBranch(p, t.sons[i], a, con('L'+'', toRope(p.unique)), genCaseStringBranch(p, t.sons[i], a, con('L'+'', toRope(p.labels)),
branches) branches)
else begin end else begin
// else statement: nothing to do yet // else statement: nothing to do yet
// but we reserved a label, which we use later // but we reserved a label, which we use later
end
end; end;
// second pass: generate switch statement based on hash of string: // second pass: generate switch statement based on hash of string:
appRopeFormat(p.s[cpsStmts], 'switch (hashString($1) & $2) {$n', appf(p.s[cpsStmts], 'switch (hashString($1) & $2) {$n',
[rdLoc(a), toRope(bitMask)]); [rdLoc(a), toRope(bitMask)]);
for j := 0 to high(branches) do for j := 0 to high(branches) do
if branches[j] <> nil then if branches[j] <> nil then
appRopeFormat(p.s[cpsStmts], 'case $1: $n$2break;$n', appf(p.s[cpsStmts], 'case $1: $n$2break;$n',
[intLiteral(j), branches[j]]); [intLiteral(j), branches[j]]);
app(p.s[cpsStmts], '}' + tnl); app(p.s[cpsStmts], '}' + tnl);
// else statement: // else statement:
if t.sons[sonsLen(t)-1].kind <> nkOfBranch then if t.sons[sonsLen(t)-1].kind <> nkOfBranch then
appRopeFormat(p.s[cpsStmts], 'goto L$1;$n', [toRope(p.unique)]); appf(p.s[cpsStmts], 'goto L$1;$n', [toRope(p.labels)]);
// third pass: generate statements // third pass: generate statements
genCaseSecondPass(p, t, labId); genCaseSecondPass(p, t, labId);
freeTemp(p, a); freeTemp(p, a);
@ -521,7 +541,7 @@ begin
end; end;
if canGenerateSwitch then begin if canGenerateSwitch then begin
a := initLocExpr(p, t.sons[0]); a := initLocExpr(p, t.sons[0]);
appRopeFormat(p.s[cpsStmts], 'switch ($1) {$n', [rdCharLoc(a)]); appf(p.s[cpsStmts], 'switch ($1) {$n', [rdCharLoc(a)]);
freeTemp(p, a); freeTemp(p, a);
for i := 1 to sonsLen(t)-1 do begin for i := 1 to sonsLen(t)-1 do begin
if t.sons[i].kind = nkOfBranch then begin if t.sons[i].kind = nkOfBranch then begin
@ -529,19 +549,19 @@ begin
for j := 0 to len-2 do begin for j := 0 to len-2 do begin
if t.sons[i].sons[j].kind = nkRange then begin // a range if t.sons[i].sons[j].kind = nkRange then begin // a range
if hasSwitchRange in CC[ccompiler].props then if hasSwitchRange in CC[ccompiler].props then
appRopeFormat(p.s[cpsStmts], 'case $1 ... $2:$n', appf(p.s[cpsStmts], 'case $1 ... $2:$n',
[genLiteral(p, t.sons[i].sons[j].sons[0]), [genLiteral(p, t.sons[i].sons[j].sons[0]),
genLiteral(p, t.sons[i].sons[j].sons[1])]) genLiteral(p, t.sons[i].sons[j].sons[1])])
else begin else begin
v := copyNode(t.sons[i].sons[j].sons[0]); v := copyNode(t.sons[i].sons[j].sons[0]);
while (v.intVal <= t.sons[i].sons[j].sons[1].intVal) do begin while (v.intVal <= t.sons[i].sons[j].sons[1].intVal) do begin
appRopeFormat(p.s[cpsStmts], 'case $1:$n', [genLiteral(p, v)]); appf(p.s[cpsStmts], 'case $1:$n', [genLiteral(p, v)]);
Inc(v.intVal) Inc(v.intVal)
end end
end; end;
end end
else else
appRopeFormat(p.s[cpsStmts], 'case $1:$n', appf(p.s[cpsStmts], 'case $1:$n',
[genLiteral(p, t.sons[i].sons[j])]); [genLiteral(p, t.sons[i].sons[j])]);
end; end;
genStmts(p, t.sons[i].sons[len-1]) genStmts(p, t.sons[i].sons[len-1])
@ -563,7 +583,7 @@ end;
procedure genCaseStmt(p: BProc; t: PNode); procedure genCaseStmt(p: BProc; t: PNode);
begin begin
genLineDir(p, t); genLineDir(p, t);
case skipAbstract(t.sons[0].typ).kind of case skipVarGenericRange(t.sons[0].typ).kind of
tyString: genStringCase(p, t); tyString: genStringCase(p, t);
tyFloat..tyFloat128: tyFloat..tyFloat128:
genCaseGeneric(p, t, 'if ($1 >= $2 && $1 <= $3) goto $4;$n', genCaseGeneric(p, t, 'if ($1 >= $2 && $1 <= $3) goto $4;$n',
@ -622,21 +642,20 @@ begin
exc := getTempName(); exc := getTempName();
if not hasGeneralExceptSection(t) then begin if not hasGeneralExceptSection(t) then begin
rethrowFlag := getTempName(); rethrowFlag := getTempName();
appRopeFormat(p.s[cpsLocals], 'volatile NIM_BOOL $1 = NIM_FALSE;$n', appf(p.s[cpsLocals], 'volatile NIM_BOOL $1 = NIM_FALSE;$n',
[rethrowFlag]) [rethrowFlag])
end; end;
if optStackTrace in p.Options then if optStackTrace in p.Options then
app(p.s[cpsStmts], 'framePtr = (TFrame*)&F;' + tnl); app(p.s[cpsStmts], 'framePtr = (TFrame*)&F;' + tnl);
app(p.s[cpsStmts], 'try {' + tnl); app(p.s[cpsStmts], 'try {' + tnl);
inc(p.inTryStmt); inc(p.nestedTryStmts);
genStmts(p, t.sons[0]); genStmts(p, t.sons[0]);
dec(p.inTryStmt);
len := sonsLen(t); len := sonsLen(t);
if t.sons[1].kind = nkExceptBranch then begin if t.sons[1].kind = nkExceptBranch then begin
appRopeFormat(p.s[cpsStmts], '} catch (NimException& $1) {$n', [exc]); appf(p.s[cpsStmts], '} catch (NimException& $1) {$n', [exc]);
if rethrowFlag <> nil then if rethrowFlag <> nil then
appRopeFormat(p.s[cpsStmts], '$1 = NIM_TRUE;$n', [rethrowFlag]); appf(p.s[cpsStmts], '$1 = NIM_TRUE;$n', [rethrowFlag]);
appRopeFormat(p.s[cpsStmts], 'if ($1.sp.exc) {$n', [exc]) appf(p.s[cpsStmts], 'if ($1.sp.exc) {$n', [exc])
end; // XXX: this is not correct! end; // XXX: this is not correct!
i := 1; i := 1;
while (i < len) and (t.sons[i].kind = nkExceptBranch) do begin while (i < len) and (t.sons[i].kind = nkExceptBranch) do begin
@ -648,24 +667,25 @@ begin
else begin else begin
for j := 0 to blen - 2 do begin for j := 0 to blen - 2 do begin
assert(t.sons[i].sons[j].kind = nkType); assert(t.sons[i].sons[j].kind = nkType);
appRopeFormat(p.s[cpsStmts], 'case $1:$n', appf(p.s[cpsStmts], 'case $1:$n',
[toRope(t.sons[i].sons[j].typ.id)]) [toRope(t.sons[i].sons[j].typ.id)])
end; end;
genStmts(p, t.sons[i].sons[blen - 1]) genStmts(p, t.sons[i].sons[blen - 1])
end; end;
// code to clear the exception: // code to clear the exception:
if rethrowFlag <> nil then if rethrowFlag <> nil then
appRopeFormat(p.s[cpsStmts], '$1 = NIM_FALSE; ', [rethrowFlag]); appf(p.s[cpsStmts], '$1 = NIM_FALSE; ', [rethrowFlag]);
app(p.s[cpsStmts], 'break;' + tnl); app(p.s[cpsStmts], 'break;' + tnl);
inc(i); inc(i);
end; end;
if t.sons[1].kind = nkExceptBranch then // BUGFIX if t.sons[1].kind = nkExceptBranch then // BUGFIX
app(p.s[cpsStmts], '}}' + tnl); // end of catch-switch statement app(p.s[cpsStmts], '}}' + tnl); // end of catch-switch statement
dec(p.nestedTryStmts);
app(p.s[cpsStmts], 'excHandler = excHandler->prev;' + tnl); app(p.s[cpsStmts], 'excHandler = excHandler->prev;' + tnl);
if (i < len) and (t.sons[i].kind = nkFinally) then begin if (i < len) and (t.sons[i].kind = nkFinally) then begin
genStmts(p, t.sons[i].sons[0]); genStmts(p, t.sons[i].sons[0]);
if rethrowFlag <> nil then if rethrowFlag <> nil then
appRopeFormat(p.s[cpsStmts], 'if ($1) { throw; }$n', [rethrowFlag]) appf(p.s[cpsStmts], 'if ($1) { throw; }$n', [rethrowFlag])
end end
end; end;
@ -698,21 +718,21 @@ begin
genLineDir(p, t); genLineDir(p, t);
safePoint := getTempName(); safePoint := getTempName();
useMagic('TSafePoint'); useMagic(p.module, 'TSafePoint');
useMagic('E_Base'); useMagic(p.module, 'E_Base');
useMagic('excHandler'); useMagic(p.module, 'excHandler');
appRopeFormat(p.s[cpsLocals], 'volatile TSafePoint $1;$n', [safePoint]); appf(p.s[cpsLocals], 'TSafePoint $1;$n', [safePoint]);
appRopeFormat(p.s[cpsStmts], '$1.prev = excHandler;$n' + appf(p.s[cpsStmts], '$1.prev = excHandler;$n' +
'excHandler = &$1;$n' + 'excHandler = &$1;$n' +
'$1.status = setjmp($1.context);$n' + '$1.status = setjmp($1.context);$n',
'if ($1.status == 0) {$n', [safePoint]); [safePoint]);
if optStackTrace in p.Options then if optStackTrace in p.Options then
app(p.s[cpsStmts], 'framePtr = (TFrame*)&F;' + tnl); app(p.s[cpsStmts], 'framePtr = (TFrame*)&F;' + tnl);
appf(p.s[cpsStmts], 'if ($1.status == 0) {$n', [safePoint]);
len := sonsLen(t); len := sonsLen(t);
inc(p.inTryStmt); inc(p.nestedTryStmts);
genStmts(p, t.sons[0]); genStmts(p, t.sons[0]);
app(p.s[cpsStmts], '} else {' + tnl); app(p.s[cpsStmts], '} else {' + tnl);
dec(p.inTryStmt);
i := 1; i := 1;
while (i < len) and (t.sons[i].kind = nkExceptBranch) do begin while (i < len) and (t.sons[i].kind = nkExceptBranch) do begin
blen := sonsLen(t.sons[i]); blen := sonsLen(t.sons[i]);
@ -720,7 +740,7 @@ begin
// general except section: // general except section:
if i > 1 then app(p.s[cpsStmts], 'else {' + tnl); if i > 1 then app(p.s[cpsStmts], 'else {' + tnl);
genStmts(p, t.sons[i].sons[0]); genStmts(p, t.sons[i].sons[0]);
appRopeFormat(p.s[cpsStmts], '$1.status = 0;$n', [safePoint]); appf(p.s[cpsStmts], '$1.status = 0;$n', [safePoint]);
if i > 1 then app(p.s[cpsStmts], '}' + tnl); if i > 1 then app(p.s[cpsStmts], '}' + tnl);
end end
else begin else begin
@ -728,24 +748,25 @@ begin
for j := 0 to blen - 2 do begin for j := 0 to blen - 2 do begin
assert(t.sons[i].sons[j].kind = nkType); assert(t.sons[i].sons[j].kind = nkType);
if orExpr <> nil then app(orExpr, '||'); if orExpr <> nil then app(orExpr, '||');
appRopeFormat(orExpr, '($1.exc->Sup.m_type == $2)', appf(orExpr, '($1.exc->Sup.m_type == $2)',
[safePoint, genTypeInfo(currMod, t.sons[i].sons[j].typ)]) [safePoint, genTypeInfo(p.module, t.sons[i].sons[j].typ)])
end; end;
if i > 1 then app(p.s[cpsStmts], 'else '); if i > 1 then app(p.s[cpsStmts], 'else ');
appRopeFormat(p.s[cpsStmts], 'if ($1) {$n', [orExpr]); appf(p.s[cpsStmts], 'if ($1) {$n', [orExpr]);
genStmts(p, t.sons[i].sons[blen - 1]); genStmts(p, t.sons[i].sons[blen - 1]);
// code to clear the exception: // code to clear the exception:
appRopeFormat(p.s[cpsStmts], '$1.status = 0;}$n', [safePoint]); appf(p.s[cpsStmts], '$1.status = 0;}$n', [safePoint]);
end; end;
inc(i) inc(i)
end; end;
app(p.s[cpsStmts], '}' + tnl); // end of if statement app(p.s[cpsStmts], '}' + tnl); // end of if statement
app(p.s[cpsStmts], 'excHandler = excHandler->prev;' + tnl); finishTryStmt(p, p.nestedTryStmts);
dec(p.nestedTryStmts);
if (i < len) and (t.sons[i].kind = nkFinally) then begin if (i < len) and (t.sons[i].kind = nkFinally) then begin
genStmts(p, t.sons[i].sons[0]); genStmts(p, t.sons[i].sons[0]);
useMagic('raiseException'); useMagic(p.module, 'raiseException');
appRopeFormat(p.s[cpsStmts], 'if ($1.status != 0) { ' + appf(p.s[cpsStmts], 'if ($1.status != 0) { ' +
'raiseException($1.exc, $1.exc->Name); }$n', [safePoint]) 'raiseException($1.exc, $1.exc->name); }$n', [safePoint])
end end
end; end;
@ -767,7 +788,7 @@ begin
name := 'bp' + toString(breakPointId) name := 'bp' + toString(breakPointId)
end; end;
genLineDir(p, t); // BUGFIX genLineDir(p, t); // BUGFIX
appRopeFormat(gBreakpoints, appf(gBreakpoints,
'dbgRegisterBreakpoint($1, (NCSTRING)$2, (NCSTRING)$3);$n', 'dbgRegisterBreakpoint($1, (NCSTRING)$2, (NCSTRING)$3);$n',
[toRope(toLinenumber(t.info)), makeCString(toFilename(t.info)), [toRope(toLinenumber(t.info)), makeCString(toFilename(t.info)),
makeCString(name)]) makeCString(name)])
@ -852,15 +873,15 @@ begin
nkCommentStmt, nkNilLit, nkIteratorDef, nkIncludeStmt, nkImportStmt, nkCommentStmt, nkNilLit, nkIteratorDef, nkIncludeStmt, nkImportStmt,
nkFromStmt, nkTemplateDef, nkMacroDef: begin end; nkFromStmt, nkTemplateDef, nkMacroDef: begin end;
nkPragma: genPragma(p, t); nkPragma: genPragma(p, t);
nkProcDef: begin nkProcDef, nkConverterDef: begin
if (t.sons[genericParamsPos] = nil) then begin if (t.sons[genericParamsPos] = nil) then begin
prc := t.sons[namePos].sym; prc := t.sons[namePos].sym;
if (t.sons[codePos] <> nil) if (t.sons[codePos] <> nil)
or (lfDynamicLib in prc.loc.flags) then begin // BUGFIX or (lfDynamicLib in prc.loc.flags) then begin // BUGFIX
if IntSetContainsOrIncl(currMod.debugDeclared, prc.id) then begin if IntSetContainsOrIncl(p.module.debugDeclared, prc.id) then begin
internalError(t.info, 'genProc()'); // XXX: remove this check! internalError(t.info, 'genProc()'); // XXX: remove this check!
end; end;
genProc(prc) genProc(p.module, prc)
end end
//else if sfCompilerProc in prc.flags then genProcPrototype(prc); //else if sfCompilerProc in prc.flags then genProcPrototype(prc);
end end

View file

@ -9,12 +9,6 @@
// ------------------------- Name Mangling -------------------------------- // ------------------------- Name Mangling --------------------------------
function getUnique(p: BProc): PRope;
begin
inc(p.unique);
result := toRope(p.unique)
end;
function mangle(const name: string): string; function mangle(const name: string): string;
var var
i: int; i: int;
@ -23,7 +17,7 @@ begin
result := toUpper(name[strStart])+'' result := toUpper(name[strStart])+''
else else
result := 'HEX' + toHex(ord(name[strStart]), 2); result := 'HEX' + toHex(ord(name[strStart]), 2);
for i := 2 to length(name) - 1 + strStart do begin for i := strStart+1 to length(name) + strStart-1 do begin
case name[i] of case name[i] of
'A'..'Z': addChar(result, chr(ord(name[i]) - ord('A') + ord('a'))); 'A'..'Z': addChar(result, chr(ord(name[i]) - ord('A') + ord('a')));
'_': begin end; '_': begin end;
@ -35,22 +29,68 @@ end;
function mangleName(s: PSym): PRope; function mangleName(s: PSym): PRope;
begin begin
if s.owner <> nil then result := ropef('$1_$2', [toRope(mangle(s.name.s)), toRope(s.id)]);
result := ropeFormat('$1_$2_$3', [toRope(mangle(s.owner.name.s)),
toRope(mangle(s.name.s)),
toRope(s.id)])
else
result := ropeFormat('$1_$2', [toRope(mangle(s.name.s)),
toRope(s.id)]);
if optGenMapping in gGlobalOptions then if optGenMapping in gGlobalOptions then
if s.owner <> nil then if s.owner <> nil then
appRopeFormat(gMapping, '$1.$2 $3$n', appf(gMapping, '$1.$2 $3$n',
[toRope(s.owner.Name.s), toRope(s.name.s), result]) [toRope(s.owner.Name.s), toRope(s.name.s), result])
end; end;
// ------------------------------ C type generator ------------------------ // ------------------------------ C type generator ------------------------
function getTypeDesc(typ: PType): PRope; forward; function mapType(typ: PType): TCTypeKind;
begin
case typ.kind of
tyNone: result := ctVoid;
tyBool: result := ctBool;
tyChar: result := ctChar;
tyEmptySet, tySet: begin
case int(getSize(typ)) of
1: result := ctInt8;
2: result := ctInt16;
4: result := ctInt32;
8: result := ctInt64;
else result := ctArray
end
end;
tyOpenArray, tyArrayConstr, tyArray: result := ctArray;
tyObject, tyTuple: result := ctStruct;
tyGeneric, tyGenericInst, tyGenericParam: result := mapType(lastSon(typ));
tyEnum, tyAnyEnum: begin
if firstOrd(typ) < 0 then
result := ctInt32
else begin
case int(getSize(typ)) of
1: result := ctUInt8;
2: result := ctUInt16;
4: result := ctInt32;
else internalError('mapType');
end
end
end;
tyRange: result := mapType(typ.sons[0]);
tyPtr, tyVar, tyRef: begin
case typ.sons[0].kind of
tyOpenArray, tyArrayConstr, tyArray: result := ctArray;
(*tySet: begin
if mapType(typ.sons[0]) = ctArray then result := ctArray
else result := ctPtr
end*)
else result := ctPtr
end
end;
tyPointer: result := ctPtr;
tySequence: result := ctNimSeq;
tyProc: result := ctProc;
tyString: result := ctNimStr;
tyCString: result := ctCString;
tyInt..tyFloat128:
result := TCTypeKind(ord(typ.kind) - ord(tyInt) + ord(ctInt));
else InternalError('mapType');
end
end;
function getTypeDesc(m: BModule; typ: PType): PRope; forward;
function needsComplexAssignment(typ: PType): bool; function needsComplexAssignment(typ: PType): bool;
begin begin
@ -58,8 +98,6 @@ begin
end; end;
function isInvalidReturnType(rettype: PType): bool; function isInvalidReturnType(rettype: PType): bool;
var
t: PType;
begin begin
// Arrays and sets cannot be returned by a C procedure, because C is // Arrays and sets cannot be returned by a C procedure, because C is
// such a poor programming language. // such a poor programming language.
@ -68,16 +106,9 @@ begin
if rettype = nil then if rettype = nil then
result := true result := true
else begin else begin
t := skipAbstract(rettype); case mapType(rettype) of
case t.kind of ctArray: result := true;
tyArray, tyArrayConstr: result := true; ctStruct: result := needsComplexAssignment(skipGeneric(rettype));
tyObject, tyRecord: result := needsComplexAssignment(t);
tySet: begin
case int(getSize(t)) of
1, 2, 4, 8: result := false;
else result := true
end
end
else result := false; else result := false;
end end
end end
@ -96,65 +127,46 @@ begin
result := PRope(TableGetType(tab, key)) result := PRope(TableGetType(tab, key))
end; end;
var
gUnique: int;
function getTempName(): PRope; function getTempName(): PRope;
begin begin
inc(gUnique); inc(gUnique);
result := con('T'+'', toRope(gUnique)) result := con('T'+'', toRope(gUnique))
end; end;
function isCArray(typ: PType): bool; function ccgIntroducedPtr(s: PSym): bool;
var
t: PType;
begin
t := skipVarGeneric(typ);
case t.kind of
tyArray, tyArrayConstr, tyOpenArray: result := true;
tySet: result := getSize(t) > 8;
else result := false
end
end;
function UsePtrPassing(param: PSym): bool;
// this is pretty complicated ...
var var
pt: PType; pt: PType;
begin begin
pt := param.typ; pt := s.typ;
if (sfResult in param.flags) and not isInvalidReturnType(pt) then assert(not (sfResult in s.flags));
result := false // BUGFIX case pt.Kind of
else if pt.Kind = tyObject then begin tyObject: begin
// objects are always passed by reference, if (optByRef in s.options) or (getSize(pt) > platform.floatSize) then
// otherwise implicit casting doesn't work result := true // requested anyway
result := true; else if (tfFinal in pt.flags) and (pt.sons[0] = nil) then
end result := false // no need, because no subtyping possible
else if (pt.kind in [tyRecordConstr, tyRecord]) and else
((getSize(pt) > platform.floatSize) or result := true; // ordinary objects are always passed by reference,
(optByRef in param.options)) then begin // otherwise casting doesn't work
result := true; end;
end tyTuple:
else if isCArray(pt) then result := (getSize(pt) > platform.floatSize) or (optByRef in s.options);
result := false
else if (pt.kind = tyVar) or (getSize(pt) > platform.floatSize) then begin
result := true;
end
else else
result := false result := false
end
end; end;
const
PointerTypes = {@set}[tySequence, tyString, tyRef, tyPtr, tyPointer];
procedure fillResult(param: PSym); procedure fillResult(param: PSym);
begin begin
fillLoc(param.loc, locParam, param.typ, fillLoc(param.loc, locParam, param.typ, toRope('Result'), OnStack);
toRope('Result'), {@set}[lfOnUnknown]); if (mapType(param.typ) <> ctArray) and IsInvalidReturnType(param.typ) then
if UsePtrPassing(param) then param.loc.indirect := 1 begin
include(param.loc.flags, lfIndirect);
param.loc.s := OnUnknown
end
end; end;
procedure genProcParams(t: PType; out rettype, params: PRope); procedure genProcParams(m: BModule; t: PType; out rettype, params: PRope);
var var
i, j: int; i, j: int;
param: PSym; param: PSym;
@ -165,31 +177,25 @@ begin
// C cannot return arrays (what a poor language...) // C cannot return arrays (what a poor language...)
rettype := toRope('void') rettype := toRope('void')
else else
rettype := getTypeDesc(t.sons[0]); rettype := getTypeDesc(m, t.sons[0]);
for i := 1 to sonsLen(t.n)-1 do begin for i := 1 to sonsLen(t.n)-1 do begin
assert(t.n.sons[i].kind = nkSym); if t.n.sons[i].kind <> nkSym then InternalError(t.n.info, 'genProcParams');
param := t.n.sons[i].sym; param := t.n.sons[i].sym;
fillLoc(param.loc, locParam, param.typ, fillLoc(param.loc, locParam, param.typ, mangleName(param), OnStack);
con(toRope('Par'), toRope(i)), {@set}[lfOnStack]); app(params, getTypeDesc(m, param.typ));
if param.typ.kind = tyVar then begin if ccgIntroducedPtr(param) then begin
param.loc.flags := {@set}[lfOnUnknown]; // BUGFIX!
app(params, getTypeDesc(param.typ.sons[0]));
end
else
app(params, getTypeDesc(param.typ));
if UsePtrPassing(param) then begin
app(params, '*'+''); app(params, '*'+'');
param.loc.indirect := 1 include(param.loc.flags, lfIndirect);
param.loc.s := OnUnknown;
end; end;
app(params, ' '+''); app(params, ' '+'');
app(params, param.loc.r); app(params, param.loc.r);
// declare the len field for open arrays: // declare the len field for open arrays:
arr := param.typ; arr := param.typ;
if arr.kind = tyVar then arr := arr.sons[0]; if arr.kind = tyVar then arr := arr.sons[0];
j := 0; j := 0;
while arr.Kind = tyOpenArray do begin // need to pass hidden parameter: while arr.Kind = tyOpenArray do begin // need to pass hidden parameter:
appRopeFormat(params, ', const int $1Len$2', [param.loc.r, toRope(j)]); appf(params, ', NI $1Len$2', [param.loc.r, toRope(j)]);
inc(j); inc(j);
arr := arr.sons[0] arr := arr.sons[0]
end; end;
@ -197,8 +203,8 @@ begin
end; end;
if (t.sons[0] <> nil) and isInvalidReturnType(t.sons[0]) then begin if (t.sons[0] <> nil) and isInvalidReturnType(t.sons[0]) then begin
if params <> nil then app(params, ', '); if params <> nil then app(params, ', ');
app(params, getTypeDesc(t.sons[0])); app(params, getTypeDesc(m, t.sons[0]));
if not isCArray(t.sons[0]) then app(params, '*'+''); if mapType(t.sons[0]) <> ctArray then app(params, '*'+'');
app(params, ' Result'); app(params, ' Result');
end; end;
if t.callConv = ccClosure then begin if t.callConv = ccClosure then begin
@ -216,11 +222,6 @@ begin
params := con('('+'', params); params := con('('+'', params);
end; end;
function getLengthOfSet(s: PNode): int;
begin
result := int(getSize(s.typ))
end;
function isImportedType(t: PType): bool; function isImportedType(t: PType): bool;
begin begin
result := (t.sym <> nil) and (sfImportc in t.sym.flags) result := (t.sym <> nil) and (sfImportc in t.sym.flags)
@ -228,25 +229,10 @@ end;
function getTypeName(typ: PType): PRope; function getTypeName(typ: PType): PRope;
begin begin
if typ.sym <> nil then begin if (typ.sym <> nil) and ([sfImportc, sfExportc] * typ.sym.flags <> []) then
result := typ.sym.loc.r; result := typ.sym.loc.r
if result = nil then begin
assert(typ.owner <> nil);
result := toRope(mangle(typ.owner.Name.s) + '_' +{&}
mangle(typ.sym.name.s));
end
end
else begin else begin
// we must use a unique type id here because we don't store if typ.loc.r = nil then typ.loc.r := con('Ty', toRope(typ.id));
// whether a type has to be given a certain name because its
// forward declaration has already been given:
if typ.loc.r = nil then begin
inc(currMod.unique);
assert(typ.owner <> nil);
typ.loc.r := ropeFormat('$1_Ty$2', [
toRope(mangle(typ.owner.Name.s)),
toRope(currMod.unique)])
end;
result := typ.loc.r result := typ.loc.r
end end
end; end;
@ -262,18 +248,18 @@ end;
function getSimpleTypeDesc(typ: PType): PRope; function getSimpleTypeDesc(typ: PType): PRope;
const const
NumericalTypeToStr: array [tyInt..tyFloat128] of string = ( NumericalTypeToStr: array [tyInt..tyFloat128] of string = (
'NS', 'NS8', 'NS16', 'NS32', 'NS64', 'NF', 'NF32', 'NF64', 'NF128'); 'NI', 'NI8', 'NI16', 'NI32', 'NI64', 'NF', 'NF32', 'NF64', 'NF128');
begin begin
case typ.Kind of case typ.Kind of
tyPointer: result := typeNameOrLiteral(typ, 'void*'); tyPointer: result := typeNameOrLiteral(typ, 'void*');
tyEnum: begin tyEnum: begin
if firstOrd(typ) < 0 then if firstOrd(typ) < 0 then
result := typeNameOrLiteral(typ, 'NS32') result := typeNameOrLiteral(typ, 'NI32')
else begin else begin
case int(getSize(typ)) of case int(getSize(typ)) of
1: result := typeNameOrLiteral(typ, 'NU8'); 1: result := typeNameOrLiteral(typ, 'NU8');
2: result := typeNameOrLiteral(typ, 'NU16'); 2: result := typeNameOrLiteral(typ, 'NU16');
4: result := typeNameOrLiteral(typ, 'NS32'); 4: result := typeNameOrLiteral(typ, 'NI32');
else begin else begin
internalError('getSimpleTypeDesc()'); internalError('getSimpleTypeDesc()');
result := nil result := nil
@ -293,14 +279,14 @@ begin
end end
end; end;
function getTypePre(typ: PType): PRope; function getTypePre(m: BModule; typ: PType): PRope;
begin begin
if typ = nil then if typ = nil then
result := toRope('void') result := toRope('void')
else begin else begin
result := getSimpleTypeDesc(typ); result := getSimpleTypeDesc(typ);
if result = nil then if result = nil then
result := CacheGetType(currMod.typeCache, typ) result := CacheGetType(m.typeCache, typ)
end end
end; end;
@ -310,19 +296,18 @@ begin
else result := 'typedef struct $1 $1;$n' else result := 'typedef struct $1 $1;$n'
end; end;
function getTypeForward(typ: PType): PRope; function getTypeForward(m: BModule; typ: PType): PRope;
begin begin
result := CacheGetType(currMod.forwTypeCache, typ); result := CacheGetType(m.forwTypeCache, typ);
if result <> nil then exit; if result <> nil then exit;
result := getTypePre(typ); result := getTypePre(m, typ);
if result <> nil then exit; if result <> nil then exit;
case typ.kind of case typ.kind of
tySequence, tyRecord, tyObject: begin tySequence, tyTuple, tyObject: begin
result := getTypeName(typ); result := getTypeName(typ);
if not isImportedType(typ) then if not isImportedType(typ) then
appRopeFormat(currMod.s[cfsForwardTypes], appf(m.s[cfsForwardTypes], getForwardStructFormat(), [result]);
getForwardStructFormat(), [result]); IdTablePut(m.forwTypeCache, typ, result)
IdTablePut(currMod.forwTypeCache, typ, result)
end end
else else
InternalError('getTypeForward(' + typeKindToStr[typ.kind] + ')') InternalError('getTypeForward(' + typeKindToStr[typ.kind] + ')')
@ -333,205 +318,254 @@ function mangleRecFieldName(field: PSym; rectype: PType): PRope;
begin begin
if (rectype.sym <> nil) if (rectype.sym <> nil)
and ([sfImportc, sfExportc] * rectype.sym.flags <> []) then and ([sfImportc, sfExportc] * rectype.sym.flags <> []) then
result := toRope(field.name.s) result := field.loc.r
else else
result := toRope(mangle(field.name.s)) result := toRope(mangle(field.name.s));
if result = nil then InternalError(field.info, 'mangleRecFieldName');
end; end;
function genRecordFieldsAux(n: PNode; accessExpr: PRope; rectype: PType): PRope; function genRecordFieldsAux(m: BModule; n: PNode; accessExpr: PRope;
rectype: PType): PRope;
var var
i: int; i: int;
ae, uname, sname, a: PRope; ae, uname, sname, a: PRope;
m: PNode; k: PNode;
field: PSym; field: PSym;
begin begin
result := nil; result := nil;
case n.kind of case n.kind of
nkRecList: begin nkRecList: begin
for i := 0 to sonsLen(n)-1 do begin for i := 0 to sonsLen(n)-1 do begin
app(result, genRecordFieldsAux(n.sons[i], accessExpr, rectype)); app(result, genRecordFieldsAux(m, n.sons[i], accessExpr, rectype));
end end
end; end;
nkRecCase: begin nkRecCase: begin
assert(n.sons[0].kind = nkSym); if (n.sons[0].kind <> nkSym) then
app(result, genRecordFieldsAux(n.sons[0], accessExpr, rectype)); InternalError(n.info, 'genRecordFieldsAux');
app(result, genRecordFieldsAux(m, n.sons[0], accessExpr, rectype));
uname := toRope(mangle(n.sons[0].sym.name.s)+ 'U'); uname := toRope(mangle(n.sons[0].sym.name.s)+ 'U');
if accessExpr <> nil then ae := ropeFormat('$1.$2', [accessExpr, uname]) if accessExpr <> nil then ae := ropef('$1.$2', [accessExpr, uname])
else ae := uname; else ae := uname;
app(result, 'union {'+tnl); app(result, 'union {'+tnl);
for i := 1 to sonsLen(n)-1 do begin for i := 1 to sonsLen(n)-1 do begin
case n.sons[i].kind of case n.sons[i].kind of
nkOfBranch, nkElse: begin nkOfBranch, nkElse: begin
m := lastSon(n.sons[i]); k := lastSon(n.sons[i]);
if m.kind <> nkSym then begin if k.kind <> nkSym then begin
sname := con('S'+'', toRope(i)); sname := con('S'+'', toRope(i));
a := genRecordFieldsAux(m, ropeFormat('$1.$2', [ae, sname]), a := genRecordFieldsAux(m, k, ropef('$1.$2', [ae, sname]),
rectype); rectype);
if a <> nil then begin if a <> nil then begin
app(result, 'struct {'); app(result, 'struct {');
app(result, a); app(result, a);
appRopeFormat(result, '} $1;$n', [sname]); appf(result, '} $1;$n', [sname]);
end end
end end
else app(result, genRecordFieldsAux(m, ae, rectype)); else app(result, genRecordFieldsAux(m, k, ae, rectype));
end; end;
else internalError('genRecordFieldsAux(record case branch)'); else internalError('genRecordFieldsAux(record case branch)');
end; end;
end; end;
appRopeFormat(result, '} $1;$n', [uname]) appf(result, '} $1;$n', [uname])
end; end;
nkSym: begin nkSym: begin
field := n.sym; field := n.sym;
assert(field.ast = nil); assert(field.ast = nil);
sname := mangleRecFieldName(field, rectype); sname := mangleRecFieldName(field, rectype);
if accessExpr <> nil then ae := ropeFormat('$1.$2', [accessExpr, sname]) if accessExpr <> nil then ae := ropef('$1.$2', [accessExpr, sname])
else ae := sname; else ae := sname;
fillLoc(field.loc, locField, field.typ, ae, {@set}[]); fillLoc(field.loc, locField, field.typ, ae, OnUnknown);
appRopeFormat(result, '$1 $2;$n', [getTypeDesc(field.loc.t), sname]) appf(result, '$1 $2;$n', [getTypeDesc(m, field.loc.t), sname])
end; end;
else internalError(n.info, 'genRecordFieldsAux()'); else internalError(n.info, 'genRecordFieldsAux()');
end end
end; end;
function getRecordFields(typ: PType): PRope; function getRecordFields(m: BModule; typ: PType): PRope;
begin begin
result := genRecordFieldsAux(typ.n, nil, typ); result := genRecordFieldsAux(m, typ.n, nil, typ);
end; end;
function getRecordDesc(typ: PType; name: PRope): PRope; function getRecordDesc(m: BModule; typ: PType; name: PRope): PRope;
var var
desc: PRope; desc: PRope;
hasField: bool;
begin begin
// declare the record: // declare the record:
hasField := false;
if typ.kind = tyObject then begin if typ.kind = tyObject then begin
useMagic('TNimType'); useMagic(m, 'TNimType');
if typ.sons[0] = nil then begin if typ.sons[0] = nil then begin
if (typ.sym <> nil) and (sfPure in typ.sym.flags) then if (typ.sym <> nil) and (sfPure in typ.sym.flags)
result := ropeFormat('struct $1 {$n', [name]) or (tfFinal in typ.flags) then
else result := ropef('struct $1 {$n', [name])
result := ropeFormat('struct $1 {$nTNimType* m_type;$n', [name]) else begin
result := ropef('struct $1 {$nTNimType* m_type;$n', [name]);
hasField := true
end
end
else if gCmd = cmdCompileToCpp then begin
result := ropef('struct $1 : public $2 {$n',
[name, getTypeDesc(m, typ.sons[0])]);
hasField := true
end
else begin
result := ropef('struct $1 {$n $2 Sup;$n',
[name, getTypeDesc(m, typ.sons[0])]);
hasField := true
end end
else if gCmd = cmdCompileToCpp then
result := ropeFormat('struct $1 : public $2 {$n',
[name, getTypeDesc(typ.sons[0])])
else
result := ropeFormat('struct $1 {$n $2 Sup;$n',
[name, getTypeDesc(typ.sons[0])])
end end
else else
result := ropeFormat('struct $1 {$n', [name]); result := ropef('struct $1 {$n', [name]);
desc := getRecordFields(typ); desc := getRecordFields(m, typ);
if (typ.kind <> tyObject) and (desc = nil) and (gCmd <> cmdCompileToCpp) then if (desc = nil) and not hasField then
// no fields in struct are not valid in C, so generate a dummy: // no fields in struct are not valid in C, so generate a dummy:
appRopeFormat(result, 'char dummy;$n', []) appf(result, 'char dummy;$n', [])
else else
app(result, desc); app(result, desc);
app(result, '};' + tnl); app(result, '};' + tnl);
end; end;
function getTypeDesc(typ: PType): PRope; procedure pushType(m: BModule; typ: PType);
var
L: int;
begin
L := length(m.typeStack);
setLength(m.typeStack, L+1);
m.typeStack[L] := typ;
end;
function getTypeDesc(m: BModule; typ: PType): PRope;
// returns only the type's name // returns only the type's name
var var
name, rettype, desc, recdesc: PRope; name, rettype, desc, recdesc: PRope;
n: biggestInt; n: biggestInt;
t, et: PType;
begin begin
if typ.sym <> nil then useHeader(typ.sym); t := getUniqueType(typ);
result := getTypePre(typ); if t = nil then InternalError('getTypeDesc: t == nil');
if t.sym <> nil then useHeader(m, t.sym);
result := getTypePre(m, t);
if result <> nil then exit; if result <> nil then exit;
case typ.Kind of case t.Kind of
tyRef, tyPtr, tyVar, tyOpenArray: begin tyRef, tyPtr, tyVar, tyOpenArray: begin
case typ.sons[0].Kind of et := getUniqueType(t.sons[0]);
tyRecord, tyObject, tySequence: begin if et.kind in [tyArrayConstr, tyArray, tyOpenArray] then
// no restriction! et := getUniqueType(elemType(et));
// We have a forward declaration for structs case et.Kind of
name := getTypeForward(typ.sons[0]); tyObject, tyTuple: begin
// no restriction! We have a forward declaration for structs
name := getTypeForward(m, et);
result := con(name, '*'+''); result := con(name, '*'+'');
IdTablePut(currMod.typeCache, typ, result) IdTablePut(m.typeCache, t, result);
pushType(m, et);
end;
tySequence: begin
// no restriction! We have a forward declaration for structs
name := getTypeForward(m, et);
result := con(name, '**');
IdTablePut(m.typeCache, t, result);
pushType(m, et);
end; end;
else begin else begin
// else we have a strong dependency :-( // else we have a strong dependency :-(
result := con(getTypeDesc(typ.sons[0]), '*'+''); result := con(getTypeDesc(m, et), '*'+'');
IdTablePut(currMod.typeCache, typ, result) IdTablePut(m.typeCache, t, result)
end end
end end
end; end;
tyProc: begin tyProc: begin
result := getTypeName(typ); result := getTypeName(t);
IdTablePut(currMod.typeCache, typ, result); IdTablePut(m.typeCache, t, result);
genProcParams(typ, rettype, desc); genProcParams(m, t, rettype, desc);
if not isImportedType(typ) then begin if not isImportedType(t) then begin
if typ.callConv <> ccClosure then if t.callConv <> ccClosure then
appRopeFormat(currMod.s[cfsTypes], 'typedef $1_PTR($2, $3) $4;$n', appf(m.s[cfsTypes], 'typedef $1_PTR($2, $3) $4;$n',
[toRope(CallingConvToStr[typ.callConv]), rettype, result, desc]) [toRope(CallingConvToStr[t.callConv]), rettype, result, desc])
else // procedure vars may need a closure! else // procedure vars may need a closure!
appRopeFormat(currMod.s[cfsTypes], 'typedef struct $1 {$n' + appf(m.s[cfsTypes], 'typedef struct $1 {$n' +
'N_CDECL_PTR($2, PrcPart) $3;$n' + 'N_CDECL_PTR($2, PrcPart) $3;$n' +
'void* ClPart;$n};$n', 'void* ClPart;$n};$n',
[result, rettype, desc]); [result, rettype, desc]);
end end
end; end;
tySequence: begin tySequence: begin
// we cannot use getTypeForward here because then typ would be associated // we cannot use getTypeForward here because then t would be associated
// with the name of the struct, not with the pointer to the struct: // with the name of the struct, not with the pointer to the struct:
result := getTypeName(typ); result := CacheGetType(m.forwTypeCache, t);
IdTablePut(currMod.typeCache, typ, con(result, '*'+'')); if result = nil then begin
if not isImportedType(typ) then begin result := getTypeName(t);
appRopeFormat(currMod.s[cfsForwardTypes], if not isImportedType(t) then
getForwardStructFormat(), [result]); appf(m.s[cfsForwardTypes], getForwardStructFormat(), [result]);
appRopeFormat(currMod.s[cfsSeqTypes], IdTablePut(m.forwTypeCache, t, result);
// BUGFIX: needed to introduce cfsSeqTypes
'struct $2 {$n' +
' NS len, space;$n' +
' $1 data[SEQ_DECL_SIZE];$n' +
'};$n', [getTypeDesc(typ.sons[0]), result]);
end; end;
assert(CacheGetType(m.typeCache, t) = nil);
IdTablePut(m.typeCache, t, con(result, '*'+''));
if not isImportedType(t) then
appf(m.s[cfsSeqTypes],
'struct $2 {$n' +
' NI len, space;$n' +
' $1 data[SEQ_DECL_SIZE];$n' +
'};$n', [getTypeDesc(m, t.sons[0]), result]);
app(result, '*'+''); app(result, '*'+'');
end; end;
tyArrayConstr, tyArray: begin tyArrayConstr, tyArray: begin
n := lengthOrd(typ); n := lengthOrd(t);
if n <= 0 then n := 1; // make an array of at least one element if n <= 0 then n := 1; // make an array of at least one element
result := getTypeName(typ); result := getTypeName(t);
IdTablePut(currMod.typeCache, typ, result); IdTablePut(m.typeCache, t, result);
if not isImportedType(typ) then if not isImportedType(t) then
appRopeFormat(currMod.s[cfsTypes], 'typedef $1 $2[$3];$n', appf(m.s[cfsTypes], 'typedef $1 $2[$3];$n',
[getTypeDesc(typ.sons[1]), result, ToRope(n)]) [getTypeDesc(m, t.sons[1]), result, ToRope(n)])
end; end;
tyObject, tyRecord, tyRecordConstr: begin tyObject, tyTuple: begin
result := getTypeName(typ); result := CacheGetType(m.forwTypeCache, t);
IdTablePut(currMod.typeCache, typ, result); if result = nil then begin
recdesc := getRecordDesc(typ, result); // always compute for sideeffects result := getTypeName(t);
if not isImportedType(typ) then if not isImportedType(t) then
app(currMod.s[cfsTypes], recdesc); appf(m.s[cfsForwardTypes],
if CacheGetType(currMod.forwTypeCache, typ) = nil then begin
if not isImportedType(typ) then
appRopeFormat(currMod.s[cfsForwardTypes],
getForwardStructFormat(), [result]); getForwardStructFormat(), [result]);
IdTablePut(currMod.forwTypeCache, typ, result) IdTablePut(m.forwTypeCache, t, result)
end end;
IdTablePut(m.typeCache, t, result);
recdesc := getRecordDesc(m, t, result); // always call for sideeffects
if not isImportedType(t) then app(m.s[cfsTypes], recdesc);
end; end;
tySet: begin tySet: begin
case int(getSize(typ)) of case int(getSize(t)) of
1: result := toRope('NS8'); 1: result := toRope('NU8');
2: result := toRope('NS16'); 2: result := toRope('NU16');
4: result := toRope('NS32'); 4: result := toRope('NU32');
8: result := toRope('NS64'); 8: result := toRope('NU64');
else begin else begin
result := getTypeName(typ); result := getTypeName(t);
IdTablePut(currMod.typeCache, typ, result); IdTablePut(m.typeCache, t, result);
if not isImportedType(typ) then if not isImportedType(t) then
appRopeFormat(currMod.s[cfsTypes], 'typedef NS8 $1[$2];$n', appf(m.s[cfsTypes], 'typedef NU8 $1[$2];$n',
[result, toRope(getSize(typ))]) [result, toRope(getSize(t))])
end
end end
end end
end;
tyGenericInst: result := getTypeDesc(m, lastSon(t));
else begin else begin
InternalError('getTypeDesc(' + typeKindToStr[typ.kind] + ')'); InternalError('getTypeDesc(' + typeKindToStr[t.kind] + ')');
result := nil result := nil
end end
end end
end; end;
function genProcHeader(prc: PSym): PRope; procedure finishTypeDescriptions(m: BModule);
var
i: int;
begin
i := 0;
while i < length(m.typeStack) do begin
{@discard} getTypeDesc(m, m.typeStack[i]);
inc(i);
end;
end;
function genProcHeader(m: BModule; prc: PSym): PRope;
var var
rettype, params: PRope; rettype, params: PRope;
begin begin
@ -540,9 +574,9 @@ begin
result := toRope('static ') result := toRope('static ')
else else
result := nil; result := nil;
fillLoc(prc.loc, locProc, prc.typ, mangleName(prc), {@set}[]); fillLoc(prc.loc, locProc, prc.typ, mangleName(prc), OnUnknown);
genProcParams(prc.typ, rettype, params); genProcParams(m, prc.typ, rettype, params);
appRopeFormat(result, '$1($2, $3)$4', appf(result, '$1($2, $3)$4',
[toRope(CallingConvToStr[prc.typ.callConv]), [toRope(CallingConvToStr[prc.typ.callConv]),
rettype, prc.loc.r, params]) rettype, prc.loc.r, params])
end; end;
@ -559,19 +593,26 @@ var
tmp: PRope; tmp: PRope;
begin begin
tmp := getTempName(); tmp := getTempName();
appRopeFormat(m.s[cfsTypeInit1], 'static TNimType $1;$n', [tmp]); appf(m.s[cfsTypeInit1], 'static TNimType $1;$n', [tmp]);
appRopeFormat(m.s[cfsTypeInit2], '$2 = &$1;$n', [tmp, name]); appf(m.s[cfsTypeInit2], '$2 = &$1;$n', [tmp, name]);
end; end;
procedure genTypeInfoAuxBase(m: BModule; typ: PType; name, base: PRope); procedure genTypeInfoAuxBase(m: BModule; typ: PType; name, base: PRope);
var
nimtypeKind: int;
begin begin
allocMemTI(m, name); allocMemTI(m, name);
appRopeFormat(m.s[cfsTypeInit3], if (typ.kind = tyObject) and (tfFinal in typ.flags)
and (typ.sons[0] = nil) then
nimtypeKind := ord(high(TTypeKind))+1 // tyPureObject
else
nimtypeKind := ord(typ.kind);
appf(m.s[cfsTypeInit3],
'$1->size = sizeof($2);$n' + '$1->size = sizeof($2);$n' +
'$1->kind = $3;$n' + '$1->kind = $3;$n' +
'$1->base = $4;$n', [ '$1->base = $4;$n', [
name, getTypeDesc(typ), toRope(ord(typ.kind)), base]); name, getTypeDesc(m, typ), toRope(nimtypeKind), base]);
appRopeFormat(m.s[cfsVars], 'TNimType* $1;$n', [name]); appf(m.s[cfsVars], 'TNimType* $1;$n', [name]);
end; end;
procedure genTypeInfoAux(m: BModule; typ: PType; name: PRope); procedure genTypeInfoAux(m: BModule; typ: PType; name: PRope);
@ -599,21 +640,21 @@ begin
genObjectFields(m, typ, n.sons[0], expr) genObjectFields(m, typ, n.sons[0], expr)
else if len > 0 then begin else if len > 0 then begin
tmp := getTempName(); tmp := getTempName();
appRopeFormat(m.s[cfsTypeInit1], 'static TNimNode* $1[$2];$n', appf(m.s[cfsTypeInit1], 'static TNimNode* $1[$2];$n',
[tmp, toRope(len)]); [tmp, toRope(len)]);
for i := 0 to len-1 do begin for i := 0 to len-1 do begin
tmp2 := getTempName(); tmp2 := getTempName();
appRopeFormat(m.s[cfsTypeInit1], 'static TNimNode $1;$n', [tmp2]); appf(m.s[cfsTypeInit1], 'static TNimNode $1;$n', [tmp2]);
appRopeFormat(m.s[cfsTypeInit3], '$1[$2] = &$3;$n', appf(m.s[cfsTypeInit3], '$1[$2] = &$3;$n',
[tmp, toRope(i), tmp2]); [tmp, toRope(i), tmp2]);
genObjectFields(m, typ, n.sons[i], tmp2); genObjectFields(m, typ, n.sons[i], tmp2);
end; end;
appRopeFormat(m.s[cfsTypeInit3], appf(m.s[cfsTypeInit3],
'$1.len = $2; $1.kind = 2; $1.sons = &$3;$n', [ '$1.len = $2; $1.kind = 2; $1.sons = &$3[0];$n', [
expr, toRope(len), tmp]); expr, toRope(len), tmp]);
end end
else else
appRopeFormat(m.s[cfsTypeInit3], appf(m.s[cfsTypeInit3],
'$1.len = $2; $1.kind = 2;$n', [expr, toRope(len)]); '$1.len = $2; $1.kind = 2;$n', [expr, toRope(len)]);
end; end;
nkRecCase: begin nkRecCase: begin
@ -621,22 +662,22 @@ begin
assert(n.sons[0].kind = nkSym); assert(n.sons[0].kind = nkSym);
field := n.sons[0].sym; field := n.sons[0].sym;
tmp := getTempName(); tmp := getTempName();
appRopeFormat(m.s[cfsTypeInit3], '$1.kind = 3;$n' + appf(m.s[cfsTypeInit3], '$1.kind = 3;$n' +
'$1.offset = offsetof($2, $3);$n' + '$1.offset = offsetof($2, $3);$n' +
'$1.typ = $4;$n' + '$1.typ = $4;$n' +
'$1.name = $5;$n' + '$1.name = $5;$n' +
'$1.sons = &$6;$n' + '$1.sons = &$6[0];$n' +
'$1.len = $7;$n', '$1.len = $7;$n',
[expr, getTypeDesc(typ), field.loc.r, [expr, getTypeDesc(m, typ), field.loc.r,
genTypeInfo(m, field.typ), genTypeInfo(m, field.typ),
makeCString(field.name.s), tmp, makeCString(field.name.s), tmp,
toRope(lengthOrd(field.typ))]); toRope(lengthOrd(field.typ))]);
appRopeFormat(m.s[cfsTypeInit1], 'static TNimNode* $1[$2];$n', appf(m.s[cfsTypeInit1], 'static TNimNode* $1[$2];$n',
[tmp, toRope(lengthOrd(field.typ)+1)]); [tmp, toRope(lengthOrd(field.typ)+1)]);
for i := 1 to len-1 do begin for i := 1 to len-1 do begin
b := n.sons[i]; // branch b := n.sons[i]; // branch
tmp2 := getTempName(); tmp2 := getTempName();
appRopeFormat(m.s[cfsTypeInit1], 'static TNimNode $1;$n', [tmp2]); appf(m.s[cfsTypeInit1], 'static TNimNode $1;$n', [tmp2]);
genObjectFields(m, typ, lastSon(b), tmp2); genObjectFields(m, typ, lastSon(b), tmp2);
//writeln(output, renderTree(b.sons[j])); //writeln(output, renderTree(b.sons[j]));
case b.kind of case b.kind of
@ -648,18 +689,18 @@ begin
x := int(getOrdValue(b.sons[j].sons[0])); x := int(getOrdValue(b.sons[j].sons[0]));
y := int(getOrdValue(b.sons[j].sons[1])); y := int(getOrdValue(b.sons[j].sons[1]));
while x <= y do begin while x <= y do begin
appRopeFormat(m.s[cfsTypeInit3], '$1[$2] = &$3;$n', appf(m.s[cfsTypeInit3], '$1[$2] = &$3;$n',
[tmp, toRope(x), tmp2]); [tmp, toRope(x), tmp2]);
inc(x); inc(x);
end; end;
end end
else else
appRopeFormat(m.s[cfsTypeInit3], '$1[$2] = &$3;$n', appf(m.s[cfsTypeInit3], '$1[$2] = &$3;$n',
[tmp, toRope(getOrdValue(b.sons[j])), tmp2]) [tmp, toRope(getOrdValue(b.sons[j])), tmp2])
end end
end; end;
nkElse: begin nkElse: begin
appRopeFormat(m.s[cfsTypeInit3], '$1[$2] = &$3;$n', appf(m.s[cfsTypeInit3], '$1[$2] = &$3;$n',
[tmp, toRope(lengthOrd(field.typ)), tmp2]); [tmp, toRope(lengthOrd(field.typ)), tmp2]);
end end
else else
@ -669,11 +710,11 @@ begin
end; end;
nkSym: begin nkSym: begin
field := n.sym; field := n.sym;
appRopeFormat(m.s[cfsTypeInit3], '$1.kind = 1;$n' + appf(m.s[cfsTypeInit3], '$1.kind = 1;$n' +
'$1.offset = offsetof($2, $3);$n' + '$1.offset = offsetof($2, $3);$n' +
'$1.typ = $4;$n' + '$1.typ = $4;$n' +
'$1.name = $5;$n', '$1.name = $5;$n',
[expr, getTypeDesc(typ), field.loc.r, [expr, getTypeDesc(m, typ), field.loc.r,
genTypeInfo(m, field.typ), genTypeInfo(m, field.typ),
makeCString(field.name.s)]); makeCString(field.name.s)]);
end; end;
@ -685,11 +726,12 @@ procedure genObjectInfo(m: BModule; typ: PType; name: PRope);
var var
tmp: PRope; tmp: PRope;
begin begin
genTypeInfoAux(m, typ, name); if typ.kind = tyObject then genTypeInfoAux(m, typ, name)
else genTypeInfoAuxBase(m, typ, name, toRope('0'+''));
tmp := getTempName(); tmp := getTempName();
appRopeFormat(m.s[cfsTypeInit1], 'static TNimNode $1;$n', [tmp]); appf(m.s[cfsTypeInit1], 'static TNimNode $1;$n', [tmp]);
genObjectFields(m, typ, typ.n, tmp); genObjectFields(m, typ, typ.n, tmp);
appRopeFormat(m.s[cfsTypeInit3], '$1->node = &$2;$n', [name, tmp]); appf(m.s[cfsTypeInit3], '$1->node = &$2;$n', [name, tmp]);
end; end;
procedure genEnumInfo(m: BModule; typ: PType; name: PRope); procedure genEnumInfo(m: BModule; typ: PType; name: PRope);
@ -702,15 +744,15 @@ begin
tmp := getTempName(); tmp := getTempName();
tmp2 := getTempName(); tmp2 := getTempName();
len := sonsLen(typ.n); len := sonsLen(typ.n);
appRopeFormat(m.s[cfsTypeInit1], 'static TNimNode* $1[$2];$n' + appf(m.s[cfsTypeInit1], 'static TNimNode* $1[$2];$n' +
'static TNimNode $3;$n', 'static TNimNode $3;$n',
[tmp, toRope(len), tmp2]); [tmp, toRope(len), tmp2]);
for i := 0 to len-1 do begin for i := 0 to len-1 do begin
assert(typ.n.sons[i].kind = nkSym); assert(typ.n.sons[i].kind = nkSym);
field := typ.n.sons[i].sym; field := typ.n.sons[i].sym;
tmp3 := getTempName(); tmp3 := getTempName();
appRopeFormat(m.s[cfsTypeInit1], 'static TNimNode $1;$n', [tmp3]); appf(m.s[cfsTypeInit1], 'static TNimNode $1;$n', [tmp3]);
appRopeFormat(m.s[cfsTypeInit3], '$1[$2] = &$3;$n' + appf(m.s[cfsTypeInit3], '$1[$2] = &$3;$n' +
'$3.kind = 1;$n' + '$3.kind = 1;$n' +
'$3.offset = $4;$n' + '$3.offset = $4;$n' +
'$3.typ = $5;$n' + '$3.typ = $5;$n' +
@ -719,8 +761,8 @@ begin
toRope(field.position), toRope(field.position),
name, makeCString(field.name.s)]); name, makeCString(field.name.s)]);
end; end;
appRopeFormat(m.s[cfsTypeInit3], appf(m.s[cfsTypeInit3],
'$1.len = $2; $1.kind = 2; $1.sons = &$3;$n$4->node = &$1;$n', [ '$1.len = $2; $1.kind = 2; $1.sons = &$3[0];$n$4->node = &$1;$n', [
tmp2, toRope(len), tmp, name]); tmp2, toRope(len), tmp, name]);
end; end;
@ -731,8 +773,8 @@ begin
assert(typ.sons[0] <> nil); assert(typ.sons[0] <> nil);
genTypeInfoAux(m, typ, name); genTypeInfoAux(m, typ, name);
tmp := getTempName(); tmp := getTempName();
appRopeFormat(m.s[cfsTypeInit1], 'static TNimNode $1;$n', [tmp]); appf(m.s[cfsTypeInit1], 'static TNimNode $1;$n', [tmp]);
appRopeFormat(m.s[cfsTypeInit3], appf(m.s[cfsTypeInit3],
'$1.len = $2; $1.kind = 0;$n' + '$1.len = $2; $1.kind = 0;$n' +
'$3->node = &$1;$n', [tmp, toRope(firstOrd(typ)), name]); '$3->node = &$1;$n', [tmp, toRope(firstOrd(typ)), name]);
end; end;
@ -746,14 +788,13 @@ function genTypeInfo(m: BModule; typ: PType): PRope;
var var
t: PType; t: PType;
begin begin
t := typ; t := getUniqueType(typ);
if t.kind = tyGenericInst then t := lastSon(t); result := ropef('NTI$1', [toRope(t.id)]);
result := ropeFormat('NTI$1', [toRope(t.id)]);
if not IntSetContainsOrIncl(m.typeInfoMarker, t.id) then begin if not IntSetContainsOrIncl(m.typeInfoMarker, t.id) then begin
// declare type information structures: // declare type information structures:
useMagic('TNimType'); useMagic(m, 'TNimType');
useMagic('TNimNode'); useMagic(m, 'TNimNode');
appRopeFormat(m.s[cfsVars], 'extern TNimType* $1;$n', [result]); appf(m.s[cfsVars], 'extern TNimType* $1;$n', [result]);
end; end;
if IntSetContainsOrIncl(gTypeInfoGenerated, t.id) then exit; if IntSetContainsOrIncl(gTypeInfoGenerated, t.id) then exit;
case t.kind of case t.kind of
@ -763,7 +804,7 @@ begin
tyArrayConstr, tyArray: genArrayInfo(m, t, result); tyArrayConstr, tyArray: genArrayInfo(m, t, result);
tySet: genSetInfo(m, t, result); tySet: genSetInfo(m, t, result);
tyEnum: genEnumInfo(m, t, result); tyEnum: genEnumInfo(m, t, result);
tyObject, tyRecord, tyRecordConstr: genObjectInfo(m, t, result); tyObject, tyTuple: genObjectInfo(m, t, result);
tyVar: result := genTypeInfo(m, typ.sons[0]); tyVar: result := genTypeInfo(m, typ.sons[0]);
else InternalError('genTypeInfo(' + typekindToStr[t.kind] + ')'); else InternalError('genTypeInfo(' + typekindToStr[t.kind] + ')');
end end

View file

@ -17,15 +17,41 @@ interface
uses uses
charsets, nsystem, charsets, nsystem,
ast, astalgo, ropes, lists, hashes, strutils, types; ast, astalgo, ropes, lists, hashes, strutils, types, msgs;
function toCChar(c: Char): string; function toCChar(c: Char): string;
function makeCString(const s: string): PRope; function makeCString(const s: string): PRope;
function TableGetType(const tab: TIdTable; key: PType): PObject; function TableGetType(const tab: TIdTable; key: PType): PObject;
function GetUniqueType(key: PType): PType;
implementation implementation
var
gTypeTable: TIdTable;
function GetUniqueType(key: PType): PType;
var
t: PType;
h: THash;
begin
result := key;
if key = nil then exit;
assert(key.kind <> tyForward);
if key.kind = tyGenericInst then begin
result := GetUniqueType(lastSon(key));
exit
end;
if IdTableHasObjectAsKey(gTypeTable, key) then exit;
// we have to do a slow linear search because types may need
// to be compared by their structure:
for h := 0 to high(gTypeTable.data) do begin
t := PType(gTypeTable.data[h].key);
if (t <> nil) and sameType(t, key) then begin result := t; exit end
end;
IdTablePut(gTypeTable, key, key);
end;
function TableGetType(const tab: TIdTable; key: PType): PObject; function TableGetType(const tab: TIdTable; key: PType): PObject;
var var
t: PType; t: PType;
@ -69,7 +95,7 @@ begin
result := nil; result := nil;
res := '"'+''; res := '"'+'';
for i := strStart to length(s)+strStart-1 do begin for i := strStart to length(s)+strStart-1 do begin
if i mod MaxLineLength = 0 then begin if (i-strStart+1) mod MaxLineLength = 0 then begin
res := res +{&} '"' +{&} nl; res := res +{&} '"' +{&} nl;
app(result, toRope(res)); app(result, toRope(res));
res := '"'+''; // reset res := '"'+''; // reset
@ -80,4 +106,6 @@ begin
app(result, toRope(res)); app(result, toRope(res));
end; end;
initialization
InitIdTable(gTypeTable);
end. end.

View file

@ -43,13 +43,28 @@ type
cfsProcHeaders, // section for C procs prototypes cfsProcHeaders, // section for C procs prototypes
cfsProcs, // section for C procs that are not inline cfsProcs, // section for C procs that are not inline
cfsTypeInit1, // section 1 for declarations of type information cfsTypeInit1, // section 1 for declarations of type information
cfsTypeInit2, // section A for initialization of type information cfsTypeInit2, // section 2 for initialization of type information
cfsTypeInit3, // section B for init of type information cfsTypeInit3, // section 3 for init of type information
cfsDebugInit, // section for initialization of debug information cfsDebugInit, // section for initialization of debug information
cfsDynLibInit, // section for initialization of dynamic library binding cfsDynLibInit, // section for initialization of dynamic library binding
cfsDynLibDeinit // section for deinitialization of dynamic libraries cfsDynLibDeinit // section for deinitialization of dynamic libraries
); );
TCTypeKind = ( // describes the type kind of a C type
ctVoid,
ctChar,
ctBool,
ctUInt, ctUInt8, ctUInt16, ctUInt32, ctUInt64,
ctInt, ctInt8, ctInt16, ctInt32, ctInt64,
ctFloat, ctFloat32, ctFloat64, ctFloat128,
ctArray,
ctStruct,
ctPtr,
ctNimStr,
ctNimSeq,
ctProc,
ctCString
);
TCFileSections = array [TCFileSection] of PRope; TCFileSections = array [TCFileSection] of PRope;
// TCFileSections represents a generated C file // TCFileSections represents a generated C file
@ -66,15 +81,20 @@ type
BModule = ^TCGen; BModule = ^TCGen;
BProc = ^TCProc; BProc = ^TCProc;
TBlock = record
id: int; // the ID of the label; positive means that it
// has been used (i.e. the label should be emitted)
nestedTryStmts: int; // how many try statements is it nested into
end;
TCProc = record // represents C proc that is currently generated TCProc = record // represents C proc that is currently generated
s: TCProcSections; // the procs sections; short name for readability s: TCProcSections; // the procs sections; short name for readability
prc: PSym; // the Nimrod proc that this C proc belongs to prc: PSym; // the Nimrod proc that this C proc belongs to
BeforeRetNeeded: bool; // true iff 'BeforeRet' label for proc is needed BeforeRetNeeded: bool; // true iff 'BeforeRet' label for proc is needed
inTryStmt: Natural; // wether we are in a try statement nestedTryStmts: Natural; // in how many nested try statements we are
// (the vars must be volatile then) // (the vars must be volatile then)
unique: Natural; // for generating unique names in the C proc labels: Natural; // for generating unique labels in the C proc
blocks: array of int; // the ID of the label; positive means that it blocks: array of TBlock; // nested blocks
// has been used (i.e. the label should be emitted)
locals: array of TLoc; // locNone means slot is free again locals: array of TLoc; // locNone means slot is free again
options: TOptions; // options that should be used for code options: TOptions; // options that should be used for code
// generation; this is the same as prc.options // generation; this is the same as prc.options
@ -82,8 +102,9 @@ type
frameLen: int; // current length of frame descriptor frameLen: int; // current length of frame descriptor
sendClosure: PType; // closure record type that we pass sendClosure: PType; // closure record type that we pass
receiveClosure: PType; // closure record type that we get receiveClosure: PType; // closure record type that we get
module: BModule; // used to prevent excessive parameter passing
end; end;
TTypeSeq = array of PType;
TCGen = object(TBackend) // represents a C source file TCGen = object(TBackend) // represents a C source file
s: TCFileSections; // sections of the C file s: TCFileSections; // sections of the C file
cfilename: string; // filename of the module (including path, cfilename: string; // filename of the module (including path,
@ -93,55 +114,48 @@ type
declaredThings: TIntSet; // things we have declared in this .c file declaredThings: TIntSet; // things we have declared in this .c file
debugDeclared: TIntSet; // for debugging purposes debugDeclared: TIntSet; // for debugging purposes
headerFiles: TLinkedList; // needed headers to include headerFiles: TLinkedList; // needed headers to include
unique: Natural; // for generating unique names //unique: Natural; // for generating unique names
typeInfoMarker: TIntSet; // needed for generating type information typeInfoMarker: TIntSet; // needed for generating type information
initProc: BProc; // code for init procedure initProc: BProc; // code for init procedure
typeStack: TTypeSeq; // used for type generation
end; end;
var var
currMod: BModule; // currently compiled module gUnique: Natural;
// a global so that this needs not to be
// passed to every proc
mainModProcs, mainModInit: PRope; // parts of the main module mainModProcs, mainModInit: PRope; // parts of the main module
gMapping: PRope; // the generated mapping file (if requested) gMapping: PRope; // the generated mapping file (if requested)
constTok: PRope; // either 'const ' or nil depending on gCmd function initLoc(k: TLocKind; typ: PType; s: TStorageLoc): TLoc;
function initLoc(k: TLocKind; typ: PType): TLoc;
begin begin
result.k := k; result.k := k;
result.t := typ; result.s := s;
result.t := GetUniqueType(typ);
result.r := nil; result.r := nil;
result.a := -1; result.a := -1;
result.indirect := 0;
result.flags := {@set}[] result.flags := {@set}[]
end; end;
procedure fillLoc(var a: TLoc; k: TLocKind; typ: PType; r: PRope; procedure fillLoc(var a: TLoc; k: TLocKind; typ: PType; r: PRope;
flags: TLocFlags); s: TStorageLoc);
begin begin
// fills the loc if it is not already initialized // fills the loc if it is not already initialized
if a.k = locNone then begin if a.k = locNone then begin
a.k := k; a.k := k;
if typ.kind = tyGenericInst then a.t := lastSon(typ) else a.t := typ; a.t := getUniqueType(typ);
a.a := -1; a.a := -1;
a.s := s;
if a.r = nil then a.r := r; if a.r = nil then a.r := r;
a.flags := a.flags + flags
end end
end; end;
procedure inheritStorage(var dest: TLoc; const src: TLoc); function newProc(prc: PSym; module: BModule): BProc;
begin
dest.flags := src.flags * [lfOnStack, lfOnHeap, lfOnData, lfOnUnknown]
end;
function newProc(prc: PSym): BProc;
begin begin
new(result); new(result);
{@ignore} {@ignore}
fillChar(result^, sizeof(result^), 0); fillChar(result^, sizeof(result^), 0);
{@emit} {@emit}
result.prc := prc; result.prc := prc;
result.module := module;
if prc <> nil then if prc <> nil then
result.options := prc.options result.options := prc.options
else else
@ -157,20 +171,19 @@ end;
function isSimpleConst(typ: PType): bool; function isSimpleConst(typ: PType): bool;
begin begin
result := not (skipAbstract(typ).kind in [tyRecord, tyRecordConstr, result := not (skipVarGeneric(typ).kind in [tyTuple, tyObject, tyArray,
tyObject, tyArray,
tyArrayConstr, tySet, tySequence]) tyArrayConstr, tySet, tySequence])
end; end;
procedure useHeader(sym: PSym); procedure useHeader(m: BModule; sym: PSym);
begin begin
if lfHeader in sym.loc.Flags then begin if lfHeader in sym.loc.Flags then begin
assert(sym.annex <> nil); assert(sym.annex <> nil);
{@discard} lists.IncludeStr(currMod.headerFiles, PLib(sym.annex).path) {@discard} lists.IncludeStr(m.headerFiles, PLib(sym.annex).path)
end end
end; end;
procedure UseMagic(const name: string); forward; procedure UseMagic(m: BModule; const name: string); forward;
// ----------------------------- name mangling // ----------------------------- name mangling
// +++++++++++++++++++++++++++++ type generation // +++++++++++++++++++++++++++++ type generation
@ -182,14 +195,14 @@ procedure UseMagic(const name: string); forward;
function beEqualTypes(a, b: PType): bool; function beEqualTypes(a, b: PType): bool;
begin begin
// returns whether two type are equal for the backend // returns whether two type are equal for the backend
result := sameType(skipAbstract(a), skipAbstract(b)) result := sameType(skipGenericRange(a), skipGenericRange(b))
end; end;
function getTemp(p: BProc; t: PType): TLoc; function getTemp(p: BProc; t: PType): TLoc;
var var
i, index: int; i, index: int;
name: PRope; name: PRope;
begin begin (*
for i := 0 to high(p.locals) do begin for i := 0 to high(p.locals) do begin
assert(i = p.locals[i].a); assert(i = p.locals[i].a);
if (p.locals[i].k = locNone) and beEqualTypes(p.locals[i].t, t) then begin if (p.locals[i].k = locNone) and beEqualTypes(p.locals[i].t, t) then begin
@ -198,41 +211,41 @@ begin
result := p.locals[i]; result := p.locals[i];
exit exit
end end
end; end; *)
// not found: // not found:
index := length(p.locals); index := length(p.locals);
setLength(p.locals, index+1); setLength(p.locals, index+1);
// declare the new temporary: // declare the new temporary:
name := con('Loc', toRope(index)); name := con('Loc', toRope(index));
appRopeFormat(p.s[cpsLocals], '$1 $2; /* temporary */$n', appf(p.s[cpsLocals], '$1 $2; /* temporary */$n',
[getTypeDesc(t), name]); [getTypeDesc(p.module, t), name]);
p.locals[index].k := locTemp; p.locals[index].k := locTemp;
p.locals[index].a := index; p.locals[index].a := index;
p.locals[index].r := name; p.locals[index].r := name;
p.locals[index].t := t; p.locals[index].t := getUniqueType(t);
p.locals[index].flags := {@set}[lfOnStack]; p.locals[index].s := OnStack;
p.locals[index].flags := {@set}[];
result := p.locals[index] // BUGFIX! result := p.locals[index] // BUGFIX!
end; end;
procedure freeTemp(p: BProc; const temp: TLoc); procedure freeTemp(p: BProc; const temp: TLoc);
begin begin (*
if (temp.a >= 0) and (temp.a < length(p.locals)) and if (temp.a >= 0) and (temp.a < length(p.locals)) and
(p.locals[temp.a].k = locTemp) then (p.locals[temp.a].k = locTemp) then
p.locals[temp.a].k := locNone p.locals[temp.a].k := locNone *)
end; end;
// -------------------------- Variable manager ---------------------------- // -------------------------- Variable manager ----------------------------
procedure declareGlobalVar(s: PSym); procedure declareGlobalVar(m: BModule; s: PSym);
begin begin
if not IntSetContainsOrIncl(currMod.declaredThings, s.id) then begin if not IntSetContainsOrIncl(m.declaredThings, s.id) then begin
app(currMod.s[cfsVars], getTypeDesc(s.loc.t)); app(m.s[cfsVars], getTypeDesc(m, s.loc.t));
if sfRegister in s.flags then if sfRegister in s.flags then
app(currMod.s[cfsVars], ' register'); app(m.s[cfsVars], ' register');
if sfVolatile in s.flags then if sfVolatile in s.flags then
app(currMod.s[cfsVars], ' volatile'); app(m.s[cfsVars], ' volatile');
appRopeFormat(currMod.s[cfsVars], ' $1; /* $2 */$n', appf(m.s[cfsVars], ' $1;$n', [s.loc.r])
[s.loc.r, toRope(s.name.s)])
end end
end; end;
@ -241,39 +254,38 @@ begin
//assert(s.loc.k == locNone) // not yet assigned //assert(s.loc.k == locNone) // not yet assigned
// this need not be fullfilled for inline procs; they are regenerated // this need not be fullfilled for inline procs; they are regenerated
// for each module that uses them! // for each module that uses them!
fillLoc(s.loc, locLocalVar, s.typ, mangleName(s), {@set}[lfOnStack]); fillLoc(s.loc, locLocalVar, s.typ, mangleName(s), OnStack);
app(p.s[cpsLocals], getTypeDesc(s.loc.t)); app(p.s[cpsLocals], getTypeDesc(p.module, s.loc.t));
if sfRegister in s.flags then if sfRegister in s.flags then
app(p.s[cpsLocals], ' register'); app(p.s[cpsLocals], ' register');
if (sfVolatile in s.flags) or (p.inTryStmt > 0) then if (sfVolatile in s.flags) or (p.nestedTryStmts > 0) then
app(p.s[cpsLocals], ' volatile'); app(p.s[cpsLocals], ' volatile');
appRopeFormat(p.s[cpsLocals], ' $1; /* $2 */$n', appf(p.s[cpsLocals], ' $1;$n', [s.loc.r]);
[s.loc.r, toRope(s.name.s)]);
// if debugging we need a new slot for the local variable: // if debugging we need a new slot for the local variable:
if [optStackTrace, optEndb] * p.Options = [optStackTrace, optEndb] then begin if [optStackTrace, optEndb] * p.Options = [optStackTrace, optEndb] then begin
appRopeFormat(p.s[cpsInit], appf(p.s[cpsInit],
'F.s[$1].name = $2; F.s[$1].address = (void*)&$3; F.s[$1].typ = $4;$n', 'F.s[$1].name = $2; F.s[$1].address = (void*)&$3; F.s[$1].typ = $4;$n',
[toRope(p.frameLen), makeCString(normalize(s.name.s)), s.loc.r, [toRope(p.frameLen), makeCString(normalize(s.name.s)), s.loc.r,
genTypeInfo(currMod, s.loc.t)]); genTypeInfo(p.module, s.loc.t)]);
inc(p.frameLen); inc(p.frameLen);
end end
end; end;
procedure assignGlobalVar(s: PSym); procedure assignGlobalVar(m: BModule; s: PSym);
begin begin
fillLoc(s.loc, locGlobalVar, s.typ, mangleName(s), {@set}[lfOnData]); fillLoc(s.loc, locGlobalVar, s.typ, mangleName(s), OnHeap);
useHeader(s); useHeader(m, s);
if lfNoDecl in s.loc.flags then exit; if lfNoDecl in s.loc.flags then exit;
if sfImportc in s.flags then app(currMod.s[cfsVars], 'extern '); if sfImportc in s.flags then app(m.s[cfsVars], 'extern ');
declareGlobalVar(s); declareGlobalVar(m, s);
if [optStackTrace, optEndb] * currMod.module.options = if [optStackTrace, optEndb] * m.module.options =
[optStackTrace, optEndb] then begin [optStackTrace, optEndb] then begin
useMagic('dbgRegisterGlobal'); useMagic(m, 'dbgRegisterGlobal');
appRopeFormat(currMod.s[cfsDebugInit], appf(m.s[cfsDebugInit],
'dbgRegisterGlobal($1, &$2, $3);$n', 'dbgRegisterGlobal($1, &$2, $3);$n',
[makeCString(normalize(s.owner.name.s + '.' +{&} s.name.s)), s.loc.r, [makeCString(normalize(s.owner.name.s + '.' +{&} s.name.s)), s.loc.r,
genTypeInfo(currMod, s.typ)]) genTypeInfo(m, s.typ)])
end; end;
end; end;
@ -286,12 +298,12 @@ procedure assignParam(p: BProc; s: PSym);
begin begin
assert(s.loc.r <> nil); assert(s.loc.r <> nil);
if [optStackTrace, optEndb] * p.options = [optStackTrace, optEndb] then begin if [optStackTrace, optEndb] * p.options = [optStackTrace, optEndb] then begin
appRopeFormat(p.s[cpsInit], appf(p.s[cpsInit],
'F.s[$1].name = $2; F.s[$1].address = (void*)$3; ' + 'F.s[$1].name = $2; F.s[$1].address = (void*)$3; ' +
'F.s[$1].typ = $4;$n', 'F.s[$1].typ = $4;$n',
[toRope(p.frameLen), makeCString(normalize(s.name.s)), [toRope(p.frameLen), makeCString(normalize(s.name.s)),
iff(usePtrPassing(s), s.loc.r, con('&'+'', s.loc.r)), iff(ccgIntroducedPtr(s), s.loc.r, con('&'+'', s.loc.r)),
genTypeInfo(currMod, s.loc.t)]); genTypeInfo(p.module, s.loc.t)]);
inc(p.frameLen) inc(p.frameLen)
end end
end; end;
@ -301,19 +313,19 @@ end;
// note that a label is a location too // note that a label is a location too
function getLabel(p: BProc): TLabel; function getLabel(p: BProc): TLabel;
begin begin
inc(p.unique); inc(p.labels);
result := con('L'+'', toRope(p.unique)) result := con('L'+'', toRope(p.labels))
end; end;
procedure fixLabel(p: BProc; labl: TLabel); procedure fixLabel(p: BProc; labl: TLabel);
begin begin
appRopeFormat(p.s[cpsStmts], '$1: ;$n', [labl]) appf(p.s[cpsStmts], '$1: ;$n', [labl])
end; end;
procedure genProcPrototype(sym: PSym); forward; procedure genProcPrototype(m: BModule; sym: PSym); forward;
procedure genVarPrototype(sym: PSym); forward; procedure genVarPrototype(m: BModule; sym: PSym); forward;
procedure genConstPrototype(sym: PSym); forward; procedure genConstPrototype(m: BModule; sym: PSym); forward;
procedure genProc(prc: PSym); forward; procedure genProc(m: BModule; prc: PSym); forward;
procedure genStmts(p: BProc; t: PNode); forward; procedure genStmts(p: BProc; t: PNode); forward;
{$include 'ccgexprs.pas'} {$include 'ccgexprs.pas'}
@ -323,76 +335,76 @@ procedure genStmts(p: BProc; t: PNode); forward;
// We don't finalize dynamic libs as this does the OS for us. // We don't finalize dynamic libs as this does the OS for us.
procedure loadDynamicLib(lib: PLib); procedure loadDynamicLib(m: BModule; lib: PLib);
var var
tmp: PRope; tmp: PRope;
begin begin
assert(lib <> nil); assert(lib <> nil);
if lib.kind = libDynamic then begin if lib.kind = libDynamic then begin
lib.kind := libDynamicGenerated; lib.kind := libDynamicGenerated;
useMagic('nimLoadLibrary'); useMagic(m, 'nimLoadLibrary');
useMagic('nimUnloadLibrary'); useMagic(m, 'nimUnloadLibrary');
tmp := getTempName(); tmp := getTempName();
appRopeFormat(currMod.s[cfsVars], 'static void* $1;$n', [tmp]); appf(m.s[cfsVars], 'static void* $1;$n', [tmp]);
appRopeFormat(currMod.s[cfsDynLibInit], appf(m.s[cfsDynLibInit],
'$1 = nimLoadLibrary((string) &$2);$n', '$1 = nimLoadLibrary((string) &$2);$n',
[tmp, getStrLit(lib.path)]); [tmp, getStrLit(m, lib.path)]);
appRopeFormat(currMod.s[cfsDynLibDeinit], appf(m.s[cfsDynLibDeinit],
'if ($1 != NIM_NIL) nimUnloadLibrary($1);$n', [tmp]); 'if ($1 != NIM_NIL) nimUnloadLibrary($1);$n', [tmp]);
assert(lib.name = nil); assert(lib.name = nil);
lib.name := tmp lib.name := tmp
end end
end; end;
procedure SymInDynamicLib(sym: PSym); procedure SymInDynamicLib(m: BModule; sym: PSym);
var var
lib: PLib; lib: PLib;
extname, tmp: PRope; extname, tmp: PRope;
begin begin
lib := PLib(sym.annex); lib := PLib(sym.annex);
extname := sym.loc.r; extname := sym.loc.r;
loadDynamicLib(lib); loadDynamicLib(m, lib);
useMagic('nimGetProcAddr'); useMagic(m, 'nimGetProcAddr');
tmp := ropeFormat('Dl_$1', [toRope(sym.id)]); tmp := ropef('Dl_$1', [toRope(sym.id)]);
sym.loc.r := tmp; // from now on we only need the internal name sym.loc.r := tmp; // from now on we only need the internal name
sym.typ.sym := nil; // generate a new name sym.typ.sym := nil; // generate a new name
appRopeFormat(currMod.s[cfsDynLibInit], appf(m.s[cfsDynLibInit],
'$1 = ($2) nimGetProcAddr($3, $4);$n', '$1 = ($2) nimGetProcAddr($3, $4);$n',
[tmp, getTypeDesc(sym.typ), lib.name, [tmp, getTypeDesc(m, sym.typ), lib.name,
makeCString(ropeToStr(extname))]); makeCString(ropeToStr(extname))]);
declareGlobalVar(sym) declareGlobalVar(m, sym)
end; end;
// ----------------------------- sections --------------------------------- // ----------------------------- sections ---------------------------------
procedure UseMagic(const name: string); procedure UseMagic(m: BModule; const name: string);
var var
sym: PSym; sym: PSym;
begin begin
if (sfSystemModule in currMod.module.flags) then exit; if (sfSystemModule in m.module.flags) then exit;
// we don't know the magic symbols in the system module, but they will be // we don't know the magic symbols in the system module, but they will be
// there anyway, because that is the way the code generator works // there anyway, because that is the way the code generator works
sym := magicsys.getCompilerProc(name); sym := magicsys.getCompilerProc(name);
case sym.kind of case sym.kind of
skProc: genProcPrototype(sym); skProc, skConverter: genProcPrototype(m, sym);
skVar: genVarPrototype(sym); skVar: genVarPrototype(m, sym);
skType: {@discard} getTypeDesc(sym.typ); skType: {@discard} getTypeDesc(m, sym.typ);
else InternalError('useMagic: ' + name) else InternalError('useMagic: ' + name)
end end
end; end;
procedure generateHeaders(); procedure generateHeaders(m: BModule);
var var
it: PStrEntry; it: PStrEntry;
begin begin
app(currMod.s[cfsHeaders], '#include "nimbase.h"' +{&} tnl +{&} tnl); app(m.s[cfsHeaders], '#include "nimbase.h"' +{&} tnl +{&} tnl);
it := PStrEntry(currMod.headerFiles.head); it := PStrEntry(m.headerFiles.head);
while it <> nil do begin while it <> nil do begin
if not (it.data[strStart] in ['"', '<']) then if not (it.data[strStart] in ['"', '<']) then
appRopeFormat(currMod.s[cfsHeaders], appf(m.s[cfsHeaders],
'#include "$1"$n', [toRope(it.data)]) '#include "$1"$n', [toRope(it.data)])
else else
appRopeFormat(currMod.s[cfsHeaders], '#include $1$n', [toRope(it.data)]); appf(m.s[cfsHeaders], '#include $1$n', [toRope(it.data)]);
it := PStrEntry(it.Next) it := PStrEntry(it.Next)
end end
end; end;
@ -402,15 +414,15 @@ var
slots: PRope; slots: PRope;
begin begin
if p.frameLen > 0 then begin if p.frameLen > 0 then begin
useMagic('TVarSlot'); useMagic(p.module, 'TVarSlot');
slots := ropeFormat(' TVarSlot s[$1];$n', [toRope(p.frameLen)]) slots := ropef(' TVarSlot s[$1];$n', [toRope(p.frameLen)])
end end
else else
slots := nil; slots := nil;
appRopeFormat(p.s[cpsLocals], 'volatile struct {TFrame* prev;' + appf(p.s[cpsLocals], 'volatile struct {TFrame* prev;' +
'NCSTRING procname;NS line;NCSTRING filename;' + 'NCSTRING procname;NI line;NCSTRING filename;' +
'NS len;$n$1} F;$n', [slots]); 'NI len;$n$1} F;$n', [slots]);
prepend(p.s[cpsInit], ropeFormat('F.len = $1;$n', [toRope(p.frameLen)])) prepend(p.s[cpsInit], ropef('F.len = $1;$n', [toRope(p.frameLen)]))
end; end;
function retIsNotVoid(s: PSym): bool; function retIsNotVoid(s: PSym): bool;
@ -418,27 +430,27 @@ begin
result := (s.typ.sons[0] <> nil) and not isInvalidReturnType(s.typ.sons[0]) result := (s.typ.sons[0] <> nil) and not isInvalidReturnType(s.typ.sons[0])
end; end;
procedure genProc(prc: PSym); procedure genProc(m: BModule; prc: PSym);
var var
p: BProc; p: BProc;
generatedProc, header, returnStmt: PRope; generatedProc, header, returnStmt: PRope;
i: int; i: int;
res, param: PSym; res, param: PSym;
begin begin
useHeader(prc); useHeader(m, prc);
fillLoc(prc.loc, locProc, prc.typ, mangleName(prc), {@set}[lfOnData]); fillLoc(prc.loc, locProc, prc.typ, mangleName(prc), OnStack);
if (lfNoDecl in prc.loc.Flags) then exit; if (lfNoDecl in prc.loc.Flags) then exit;
if lfDynamicLib in prc.loc.flags then if lfDynamicLib in prc.loc.flags then
SymInDynamicLib(prc) SymInDynamicLib(m, prc)
else if not (sfImportc in prc.flags) then begin else if not (sfImportc in prc.flags) then begin
// we have a real proc here: // we have a real proc here:
p := newProc(prc); p := newProc(prc, m);
header := genProcHeader(prc); header := genProcHeader(m, prc);
if (sfCompilerProc in prc.flags) if (sfCompilerProc in prc.flags)
and (sfSystemModule in currMod.module.flags) and (sfSystemModule in m.module.flags)
and not IntSetContains(currMod.declaredThings, prc.id) then and not IntSetContains(m.declaredThings, prc.id) then
appRopeFormat(currMod.s[cfsProcHeaders], '$1;$n', [header]); appf(m.s[cfsProcHeaders], '$1;$n', [header]);
intSetIncl(currMod.declaredThings, prc.id); intSetIncl(m.declaredThings, prc.id);
returnStmt := nil; returnStmt := nil;
assert(prc.ast <> nil); assert(prc.ast <> nil);
@ -450,7 +462,7 @@ begin
assert(res.loc.r <> nil); assert(res.loc.r <> nil);
initVariable(p, res); initVariable(p, res);
genObjectInit(p, res); genObjectInit(p, res);
returnStmt := ropeFormat('return $1;$n', [rdLoc(res.loc)]); returnStmt := ropef('return $1;$n', [rdLoc(res.loc)]);
end end
else if (prc.typ.sons[0] <> nil) then begin else if (prc.typ.sons[0] <> nil) then begin
res := prc.ast.sons[resultPos].sym; // get result symbol res := prc.ast.sons[resultPos].sym; // get result symbol
@ -465,13 +477,13 @@ begin
genStmts(p, prc.ast.sons[codePos]); // modifies p.locals, p.init, etc. genStmts(p, prc.ast.sons[codePos]); // modifies p.locals, p.init, etc.
if sfPure in prc.flags then if sfPure in prc.flags then
generatedProc := ropeFormat('$1 {$n$2$3$4}$n', generatedProc := ropef('$1 {$n$2$3$4}$n',
[header, p.s[cpsLocals], p.s[cpsInit], p.s[cpsStmts]]) [header, p.s[cpsLocals], p.s[cpsInit], p.s[cpsStmts]])
else begin else begin
generatedProc := con(header, '{' + tnl); generatedProc := con(header, '{' + tnl);
if optStackTrace in prc.options then begin if optStackTrace in prc.options then begin
getFrameDecl(p); getFrameDecl(p);
prepend(p.s[cpsInit], ropeFormat( prepend(p.s[cpsInit], ropef(
'F.procname = $1;$n' + 'F.procname = $1;$n' +
'F.prev = framePtr;$n' + 'F.prev = framePtr;$n' +
'F.filename = $2;$n' + 'F.filename = $2;$n' +
@ -491,86 +503,93 @@ begin
//if prc.typ.callConv <> ccInline then //if prc.typ.callConv <> ccInline then
// prc.ast.sons[codePos] := nil; // prc.ast.sons[codePos] := nil;
end; end;
app(currMod.s[cfsProcs], generatedProc); app(m.s[cfsProcs], generatedProc);
end end
end; end;
procedure genVarPrototype(sym: PSym); procedure genVarPrototype(m: BModule; sym: PSym);
begin begin
assert(sfGlobal in sym.flags); assert(sfGlobal in sym.flags);
useHeader(sym); useHeader(m, sym);
fillLoc(sym.loc, locGlobalVar, sym.typ, mangleName(sym), {@set}[lfOnData]); fillLoc(sym.loc, locGlobalVar, sym.typ, mangleName(sym), OnHeap);
if (lfNoDecl in sym.loc.Flags) or if (lfNoDecl in sym.loc.Flags) or
intSetContainsOrIncl(currMod.declaredThings, sym.id) then intSetContainsOrIncl(m.declaredThings, sym.id) then
exit; exit;
if sym.owner.id <> currMod.module.id then begin if sym.owner.id <> m.module.id then begin
// else we already have the symbol generated! // else we already have the symbol generated!
assert(sym.loc.r <> nil); assert(sym.loc.r <> nil);
app(currMod.s[cfsVars], 'extern '); app(m.s[cfsVars], 'extern ');
app(currMod.s[cfsVars], getTypeDesc(sym.loc.t)); app(m.s[cfsVars], getTypeDesc(m, sym.loc.t));
if sfRegister in sym.flags then if sfRegister in sym.flags then
app(currMod.s[cfsVars], ' register'); app(m.s[cfsVars], ' register');
if sfVolatile in sym.flags then if sfVolatile in sym.flags then
app(currMod.s[cfsVars], ' volatile'); app(m.s[cfsVars], ' volatile');
appRopeFormat(currMod.s[cfsVars], ' $1; /* $2 */$n', appf(m.s[cfsVars], ' $1;$n', [sym.loc.r])
[sym.loc.r, toRope(sym.name.s)])
end end
end; end;
procedure genConstPrototype(sym: PSym); procedure genConstPrototype(m: BModule; sym: PSym);
begin begin
useHeader(sym); useHeader(m, sym);
fillLoc(sym.loc, locData, sym.typ, mangleName(sym), {@set}[lfOnData]); fillLoc(sym.loc, locData, sym.typ, mangleName(sym), OnUnknown);
if (lfNoDecl in sym.loc.Flags) or if (lfNoDecl in sym.loc.Flags) or
intSetContainsOrIncl(currMod.declaredThings, sym.id) then intSetContainsOrIncl(m.declaredThings, sym.id) then
exit; exit;
if sym.owner.id <> currMod.module.id then begin if sym.owner.id <> m.module.id then begin
// else we already have the symbol generated! // else we already have the symbol generated!
assert(sym.loc.r <> nil); assert(sym.loc.r <> nil);
app(currMod.s[cfsData], 'extern '); app(m.s[cfsData], 'extern ');
appRopeFormat(currMod.s[cfsData], '$1$2 $3; /* $4 */$n', appf(m.s[cfsData], 'NIM_CONST $1 $2;$n',
[constTok, getTypeDesc(sym.loc.t), sym.loc.r, toRope(sym.name.s)]) [getTypeDesc(m, sym.loc.t), sym.loc.r])
end end
end; end;
procedure genProcPrototype(sym: PSym); procedure genProcPrototype(m: BModule; sym: PSym);
begin begin
useHeader(sym); useHeader(m, sym);
fillLoc(sym.loc, locProc, sym.typ, mangleName(sym), {@set}[lfOnData]); fillLoc(sym.loc, locProc, sym.typ, mangleName(sym), OnStack);
if lfDynamicLib in sym.loc.Flags then begin if lfDynamicLib in sym.loc.Flags then begin
// it is a proc variable! // it is a proc variable!
if (sym.owner.id <> currMod.module.id) and if (sym.owner.id <> m.module.id) and
not intSetContainsOrIncl(currMod.declaredThings, sym.id) then begin not intSetContainsOrIncl(m.declaredThings, sym.id) then begin
app(currMod.s[cfsVars], 'extern '); app(m.s[cfsVars], 'extern ');
// BUGFIX: declareGlobalVar() inlined, because of intSetContainsOrIncl // BUGFIX: declareGlobalVar() inlined, because of intSetContainsOrIncl
// check // check
app(currMod.s[cfsVars], getTypeDesc(sym.loc.t)); app(m.s[cfsVars], getTypeDesc(m, sym.loc.t));
appRopeFormat(currMod.s[cfsVars], ' $1; /* $2 */$n', appf(m.s[cfsVars], ' $1;$n', [sym.loc.r])
[sym.loc.r, toRope(sym.name.s)])
end end
end end
else begin else begin
// it is a proc: // it is a proc:
if (lfNoDecl in sym.loc.Flags) then exit; if (lfNoDecl in sym.loc.Flags) then exit;
if intSetContainsOrIncl(currMod.declaredThings, sym.id) then exit; if intSetContainsOrIncl(m.declaredThings, sym.id) then exit;
appRopeFormat(currMod.s[cfsProcHeaders], '$1;$n', [genProcHeader(sym)]); appf(m.s[cfsProcHeaders], '$1;$n', [genProcHeader(m, sym)]);
if (sym.typ.callConv = ccInline) if (sym.typ.callConv = ccInline)
and (sym.owner.id <> currMod.module.id) then and (sym.owner.id <> m.module.id) then
genProc(sym) // generate the code again! genProc(m, sym) // generate the code again!
// else
// IntSetIncl(currMod.declaredThings, sym.id)
end end
end; end;
function getFileHeader: PRope; function getFileHeader(const cfilenoext: string): PRope;
begin begin
result := ropeFormat( result := ropef(
'/* Generated by the Nimrod Compiler v$1 */$n' + '/* Generated by the Nimrod Compiler v$1 */$n' +
'/* (c) 2008 Andreas Rumpf */$n' + '/* (c) 2008 Andreas Rumpf */$n' +
'/* Compiled for: $2, $3, $4 */$n', '/* Compiled for: $2, $3, $4 */$n' +
'/* Command for C compiler:$n $5 */$n',
[toRope(versionAsString), toRope(platform.OS[targetOS].name), [toRope(versionAsString), toRope(platform.OS[targetOS].name),
toRope(platform.CPU[targetCPU].name), toRope(platform.CPU[targetCPU].name),
toRope(extccomp.CC[extccomp.ccompiler].name)]) toRope(extccomp.CC[extccomp.ccompiler].name),
toRope(getCompileCFileCmd(cfilenoext))]);
case platform.CPU[targetCPU].intSize of
16: appf(result, '$ntypedef short int NI;$n' +
'typedef unsigned short int NU;$n', []);
32: appf(result, '$ntypedef long int NI;$n' +
'typedef unsigned long int NU;$n', []);
64: appf(result, '$ntypedef long long int NI;$n' +
'typedef unsigned long long int NU;$n', []);
else begin end
end
end; end;
procedure genMainProc(m: BModule); procedure genMainProc(m: BModule);
@ -581,13 +600,13 @@ const
'$1' + '$1' +
'$2'; '$2';
PosixMain = PosixMain =
'NS cmdCount;$n' + 'NI cmdCount;$n' +
'char** cmdLine;$n' + 'char** cmdLine;$n' +
'char** gEnv;$n' + 'char** gEnv;$n' +
'int main(int argc, char** args, char** env) {$n' + 'int main(int argc, char** args, char** env) {$n' +
' int dummy[8];$n' + ' int dummy[8];$n' +
' cmdLine = args;$n' + ' cmdLine = args;$n' +
' cmdCount = (NS)argc;$n' + ' cmdCount = (NI)argc;$n' +
' gEnv = env;$n' +{&} ' gEnv = env;$n' +{&}
CommonMainBody +{&} CommonMainBody +{&}
' return 0;$n' + ' return 0;$n' +
@ -610,7 +629,7 @@ const
var var
frmt: TFormatStr; frmt: TFormatStr;
begin begin
useMagic('setStackBottom'); useMagic(m, 'setStackBottom');
if (platform.targetOS = osWindows) and if (platform.targetOS = osWindows) and
(gGlobalOptions * [optGenGuiApp, optGenDynLib] <> []) then begin (gGlobalOptions * [optGenGuiApp, optGenDynLib] <> []) then begin
if optGenGuiApp in gGlobalOptions then if optGenGuiApp in gGlobalOptions then
@ -622,8 +641,8 @@ begin
else else
frmt := PosixMain; frmt := PosixMain;
if gBreakpoints <> nil then if gBreakpoints <> nil then
useMagic('dbgRegisterBreakpoint'); useMagic(m, 'dbgRegisterBreakpoint');
appRopeFormat(m.s[cfsProcs], frmt, [gBreakpoints, mainModInit]) appf(m.s[cfsProcs], frmt, [gBreakpoints, mainModInit])
end; end;
procedure genInitCode(m: BModule); procedure genInitCode(m: BModule);
@ -631,16 +650,16 @@ var
initname, prc: PRope; initname, prc: PRope;
begin begin
initname := con(m.module.name.s, toRope('Init')); initname := con(m.module.name.s, toRope('Init'));
appRopeFormat(mainModProcs, 'N_NIMCALL(void, $1)(void);$n', appf(mainModProcs, 'N_NIMCALL(void, $1)(void);$n',
[initname]); [initname]);
if not (sfSystemModule in m.module.flags) then if not (sfSystemModule in m.module.flags) then
appRopeFormat(mainModInit, '$1();$n', [initname]); appf(mainModInit, '$1();$n', [initname]);
prc := ropeFormat('N_NIMCALL(void, $1)(void) {$n', [initname]); prc := ropef('N_NIMCALL(void, $1)(void) {$n', [initname]);
if optStackTrace in m.initProc.options then begin if optStackTrace in m.initProc.options then begin
prepend(m.initProc.s[cpsLocals], toRope('volatile TFrame F;' + tnl)); prepend(m.initProc.s[cpsLocals], toRope('volatile TFrame F;' + tnl));
app(prc, m.initProc.s[cpsLocals]); app(prc, m.initProc.s[cpsLocals]);
app(prc, m.s[cfsTypeInit1]); app(prc, m.s[cfsTypeInit1]);
appRopeFormat(prc, appf(prc,
'F.len = 0;$n' + // IMPORTANT: else the debugger crashes! 'F.len = 0;$n' + // IMPORTANT: else the debugger crashes!
'F.procname = $1;$n' + 'F.procname = $1;$n' +
'F.prev = framePtr;$n' + 'F.prev = framePtr;$n' +
@ -666,12 +685,12 @@ begin
app(m.s[cfsProcs], prc) app(m.s[cfsProcs], prc)
end; end;
function genModule(m: BModule): PRope; function genModule(m: BModule; const cfilenoext: string): PRope;
var var
i: TCFileSection; i: TCFileSection;
begin begin
result := getFileHeader(); result := getFileHeader(cfilenoext);
generateHeaders(); generateHeaders(m);
for i := low(TCFileSection) to cfsProcs do app(result, m.s[i]) for i := low(TCFileSection) to cfsProcs do app(result, m.s[i])
end; end;
@ -688,11 +707,10 @@ begin
initIdTable(result.typeCache); initIdTable(result.typeCache);
initIdTable(result.forwTypeCache); initIdTable(result.forwTypeCache);
result.module := module; result.module := module;
if gCmd <> cmdCompileToCpp then
constTok := toRope('const ');
intSetInit(result.typeInfoMarker); intSetInit(result.typeInfoMarker);
result.initProc := newProc(nil); result.initProc := newProc(nil, result);
result.initProc.options := gOptions; result.initProc.options := gOptions;
{@emit result.typeStack := [];}
end; end;
function shouldRecompile(code: PRope; const cfile, cfilenoext: string): bool; function shouldRecompile(code: PRope; const cfile, cfilenoext: string): bool;
@ -717,28 +735,27 @@ var
code: PRope; code: PRope;
begin begin
m := BModule(b); m := BModule(b);
currMod := m; m.initProc.options := gOptions;
currMod.initProc.options := gOptions; genStmts(m.initProc, n);
genStmts(currMod.initProc, n);
// generate code for the init statements of the module: // generate code for the init statements of the module:
genInitCode(m); genInitCode(m);
finishTypeDescriptions(m);
if sfMainModule in m.module.flags then begin if sfMainModule in m.module.flags then begin
// generate mapping file (if requested): // generate mapping file (if requested):
if gMapping <> nil then if gMapping <> nil then
WriteRope(gMapping, ChangeFileExt(cfile + '_map', 'txt')); WriteRope(gMapping, ChangeFileExt(cfile + '_map', 'txt'));
// generate main file: // generate main file:
app(currMod.s[cfsProcHeaders], mainModProcs); app(m.s[cfsProcHeaders], mainModProcs);
genMainProc(currMod); genMainProc(m);
end; end;
cfile := completeCFilePath(m.cfilename); cfile := completeCFilePath(m.cfilename);
cfilenoext := changeFileExt(cfile, ''); cfilenoext := changeFileExt(cfile, '');
code := genModule(m); code := genModule(m, cfilenoext);
if shouldRecompile(code, changeFileExt(cfile, cExt), cfilenoext) then begin if shouldRecompile(code, changeFileExt(cfile, cExt), cfilenoext) then begin
addFileToCompile(cfilenoext); // is to compile addFileToCompile(cfilenoext); // is to compile
end; end;
addFileToLink(cfilenoext); addFileToLink(cfilenoext);
currMod := nil // free the memory
end; end;
function CBackend(b: PBackend; module: PSym; const filename: string): PBackend; function CBackend(b: PBackend; module: PSym; const filename: string): PBackend;
@ -749,7 +766,6 @@ begin
g.backendCreator := CBackend; g.backendCreator := CBackend;
g.eventMask := {@set}[eAfterModule]; g.eventMask := {@set}[eAfterModule];
g.afterModuleEvent := finishModule; g.afterModuleEvent := finishModule;
currMod := g;
result := g; result := g;
end; end;

View file

@ -7,10 +7,10 @@
// distribution, for details about the copyright. // distribution, for details about the copyright.
// //
// This module handles the parsing of command line arguments.
unit commands; unit commands;
// This module handles the parsing of command line arguments.
interface interface
{$include 'config.inc'} {$include 'config.inc'}
@ -41,16 +41,14 @@ uses
const const
{$ifdef fpc} {$ifdef fpc}
compileDate = {$I %date%}; compileDate = {$I %date%};
compileTime = {$I %time%};
{$else} {$else}
compileDate = '2008-0-0'; compileDate = '2008-0-0';
compileTime = '00:00:00';
{$endif} {$endif}
{@emit} {@emit}
const const
HelpMessage = 'Nimrod Compiler Version $1 (' +{&} HelpMessage = 'Nimrod Compiler Version $1 (' +{&}
compileDate +{&} ' ' +{&} compileTime +{&} ') [$2: $3]' +{&} nl +{&} compileDate +{&} ') [$2: $3]' +{&} nl +{&}
'Copyright (c) 2004-2008 by Andreas Rumpf' +{&} nl; 'Copyright (c) 2004-2008 by Andreas Rumpf' +{&} nl;
const const
@ -66,6 +64,7 @@ const
+{&} ' compile compile project with default code generator (C)' +{&} nl +{&} ' compile compile project with default code generator (C)' +{&} nl
+{&} ' compile_to_c compile project with C code generator' +{&} nl +{&} ' compile_to_c compile project with C code generator' +{&} nl
+{&} ' compile_to_cpp compile project with C++ code generator' +{&} nl +{&} ' compile_to_cpp compile project with C++ code generator' +{&} nl
+{&} ' compile_to_ecmascript compile project to ECMAScript code (experimental)' +{&} nl
+{&} ' doc generate the documentation for inputfile;' +{&} nl +{&} ' doc generate the documentation for inputfile;' +{&} nl
+{&} ' with --run switch opens it with $BROWSER' +{&} nl +{&} ' with --run switch opens it with $BROWSER' +{&} nl
+{&} 'Arguments:' +{&} nl +{&} 'Arguments:' +{&} nl
@ -80,6 +79,8 @@ const
+{&} ' --line_trace:on|off code generation for line trace ON|OFF' +{&} nl +{&} ' --line_trace:on|off code generation for line trace ON|OFF' +{&} nl
+{&} ' --debugger:on|off turn Embedded Nimrod Debugger ON|OFF' +{&} nl +{&} ' --debugger:on|off turn Embedded Nimrod Debugger ON|OFF' +{&} nl
+{&} ' -x, --checks:on|off code generation for all runtime checks ON|OFF' +{&} nl +{&} ' -x, --checks:on|off code generation for all runtime checks ON|OFF' +{&} nl
+{&} ' --obj_checks:on|off code generation for obj conversion checks ON|OFF' +{&} nl
+{&} ' --field_checks:on|off code generation for case record fields ON|OFF' +{&} nl
+{&} ' --range_checks:on|off code generation for range checks ON|OFF' +{&} nl +{&} ' --range_checks:on|off code generation for range checks ON|OFF' +{&} nl
+{&} ' --bound_checks:on|off code generation for bound checks ON|OFF' +{&} nl +{&} ' --bound_checks:on|off code generation for bound checks ON|OFF' +{&} nl
+{&} ' --overflow_checks:on|off code generation for over-/underflow checks ON|OFF' +{&} nl +{&} ' --overflow_checks:on|off code generation for over-/underflow checks ON|OFF' +{&} nl
@ -174,17 +175,8 @@ const
; ;
function getCommandLineDesc: string; function getCommandLineDesc: string;
var
v: string;
begin begin
// the Pascal version number gets a little star ('*'), the Nimrod version result := format(HelpMessage, [VersionAsString, platform.os[hostOS].name,
// does not! This helps distinguishing the different builds.
{@ignore}
v := VersionAsString +{&} '*';
{@emit
v := VersionAsString
}
result := format(HelpMessage, [v, platform.os[hostOS].name,
cpu[hostCPU].name]) +{&} Usage cpu[hostCPU].name]) +{&} Usage
end; end;
@ -210,6 +202,7 @@ begin
cpu[hostCPU].name]) +{&} AdvancedUsage); cpu[hostCPU].name]) +{&} AdvancedUsage);
advHelpWritten := true; advHelpWritten := true;
helpWritten := true; helpWritten := true;
halt(0);
end end
end; end;
@ -423,7 +416,7 @@ begin
ProcessOnOffSwitch({@set}[optHints], arg, pass, info); ProcessOnOffSwitch({@set}[optHints], arg, pass, info);
wCheckpoints: wCheckpoints:
ProcessOnOffSwitch({@set}[optCheckpoints], arg, pass, info); ProcessOnOffSwitch({@set}[optCheckpoints], arg, pass, info);
wStackTrace, wS: wStackTrace:
ProcessOnOffSwitch({@set}[optStackTrace], arg, pass, info); ProcessOnOffSwitch({@set}[optStackTrace], arg, pass, info);
wLineTrace: wLineTrace:
ProcessOnOffSwitch({@set}[optLineTrace], arg, pass, info); ProcessOnOffSwitch({@set}[optLineTrace], arg, pass, info);
@ -436,6 +429,10 @@ begin
end; end;
wChecks, wX: wChecks, wX:
ProcessOnOffSwitch(checksOptions, arg, pass, info); ProcessOnOffSwitch(checksOptions, arg, pass, info);
wObjChecks:
ProcessOnOffSwitch({@set}[optObjCheck], arg, pass, info);
wFieldChecks:
ProcessOnOffSwitch({@set}[optFieldCheck], arg, pass, info);
wRangeChecks: wRangeChecks:
ProcessOnOffSwitch({@set}[optRangeCheck], arg, pass, info); ProcessOnOffSwitch({@set}[optRangeCheck], arg, pass, info);
wBoundChecks: wBoundChecks:
@ -485,6 +482,10 @@ begin
liMessage(info, errGuiConsoleOrLibExpectedButXFound, arg) liMessage(info, errGuiConsoleOrLibExpectedButXFound, arg)
end end
end; end;
wListDef: begin
if pass in {@set}[passCmd2, passPP] then
condsyms.listSymbols();
end;
wPassC, wT: begin wPassC, wT: begin
expectArg(switch, arg, pass, info); expectArg(switch, arg, pass, info);
if pass in {@set}[passCmd2, passPP] then if pass in {@set}[passCmd2, passPP] then

View file

@ -19,7 +19,7 @@ type
TCrc32 = int32; TCrc32 = int32;
const const
InitCrc32 = TCrc32($ffffffff); InitCrc32 = TCrc32(-1);
function updateCrc32(val: Byte; crc: TCrc32): TCrc32; overload; function updateCrc32(val: Byte; crc: TCrc32): TCrc32; overload;
function updateCrc32(val: Char; crc: TCrc32): TCrc32; overload; function updateCrc32(val: Char; crc: TCrc32): TCrc32; overload;

View file

@ -40,6 +40,7 @@ type
modDesc: PRope; // module description modDesc: PRope; // module description
dependsOn: PRope; // dependencies dependsOn: PRope; // dependencies
id: int; // for generating IDs id: int; // for generating IDs
splitAfter: int; // split to long entries in the TOC
tocPart: array of TTocEntry; tocPart: array of TTocEntry;
hasToc: bool; hasToc: bool;
toc, section: TSections; toc, section: TSections;
@ -106,6 +107,8 @@ begin
end; end;
function newDocumentor(const filename: string): PDoc; function newDocumentor(const filename: string): PDoc;
var
s: string;
begin begin
new(result); new(result);
{@ignore} {@ignore}
@ -115,6 +118,10 @@ begin
} }
result.filename := filename; result.filename := filename;
result.id := 100; result.id := 100;
result.splitAfter := 25;
s := getConfigVar('split.item.toc');
if s <> '' then
result.splitAfter := parseInt(s);
end; end;
function getVarIdx(const varnames: array of string; const id: string): int; function getVarIdx(const varnames: array of string; const id: string): int;
@ -209,12 +216,16 @@ begin
end end
end; end;
function toXml(const s: string): string; function toXml(const s: string; splitAfter: int = -1): string;
var var
i: int; i: int;
begin begin
result := ''; result := '';
for i := strStart to length(s)+strStart-1 do addXmlChar(result, s[i]) for i := strStart to length(s)+strStart-1 do begin
if (splitAfter >= 0) and ((i-strStart+1) mod splitAfter = 0) then
addChar(result, ' ');
addXmlChar(result, s[i])
end
end; end;
function renderRstToHtml(d: PDoc; n: PRstNode): PRope; forward; function renderRstToHtml(d: PDoc; n: PRstNode): PRope; forward;
@ -226,8 +237,8 @@ var
begin begin
result := nil; result := nil;
for i := 0 to rsonsLen(n)-1 do for i := 0 to rsonsLen(n)-1 do
appRopeFormat(result, inner, [renderRstToHtml(d, n.sons[i])]); appf(result, inner, [renderRstToHtml(d, n.sons[i])]);
result := ropeFormat(outer, [result]); result := ropef(outer, [result]);
end; end;
procedure setIndexForSourceTerm(d: PDoc; name: PRstNode; id: int); procedure setIndexForSourceTerm(d: PDoc; name: PRstNode; id: int);
@ -249,7 +260,7 @@ var
a, h: PRstNode; a, h: PRstNode;
begin begin
inc(d.id); inc(d.id);
result := ropeFormat('<em id="$1">$2</em>', result := ropef('<em id="$1">$2</em>',
[toRope(d.id), renderAux(d, n)]); [toRope(d.id), renderAux(d, n)]);
h := newRstNode(rnHyperlink); h := newRstNode(rnHyperlink);
a := newRstNode(rnLeaf, d.indexValFilename +{&} '#' +{&} toString(d.id)); a := newRstNode(rnLeaf, d.indexValFilename +{&} '#' +{&} toString(d.id));
@ -277,11 +288,13 @@ var
begin begin
if n = nil then begin result := nil; exit end; if n = nil then begin result := nil; exit end;
result := genComment(d, n); result := genComment(d, n);
if result = nil then if result = nil then begin
if not (n.kind in [nkEmpty..nkNilLit]) then
for i := 0 to sonsLen(n)-1 do begin for i := 0 to sonsLen(n)-1 do begin
result := genRecComment(d, n.sons[i]); result := genRecComment(d, n.sons[i]);
if result <> nil then exit if result <> nil then exit
end end
end
else else
n.comment := snil n.comment := snil
end; end;
@ -303,14 +316,14 @@ begin
result := isVisible(n.sons[0]); result := isVisible(n.sons[0]);
end; end;
function getName(n: PNode): string; function getName(n: PNode; splitAfter: int = -1): string;
begin begin
case n.kind of case n.kind of
nkPostfix: result := getName(n.sons[1]); nkPostfix: result := getName(n.sons[1], splitAfter);
nkPragmaExpr: result := getName(n.sons[0]); nkPragmaExpr: result := getName(n.sons[0], splitAfter);
nkSym: result := toXML(n.sym.name.s); nkSym: result := toXML(n.sym.name.s, splitAfter);
nkIdent: result := toXML(n.ident.s); nkIdent: result := toXML(n.ident.s, splitAfter);
nkAccQuoted: result := '`' +{&} getName(n.sons[0]) +{&} '`'; nkAccQuoted: result := '`' +{&} getName(n.sons[0], splitAfter) +{&} '`';
else begin else begin
internalError(n.info, 'getName()'); internalError(n.info, 'getName()');
result := '' result := ''
@ -355,38 +368,38 @@ begin
case kind of case kind of
tkEof: break; tkEof: break;
tkComment: tkComment:
appRopeFormat(result, '<span class="Comment">$1</span>', appf(result, '<span class="Comment">$1</span>',
[toRope(toXml(literal))]); [toRope(toXml(literal))]);
tokKeywordLow..tokKeywordHigh: tokKeywordLow..tokKeywordHigh:
appRopeFormat(result, '<span class="Keyword">$1</span>', appf(result, '<span class="Keyword">$1</span>',
[toRope(literal)]); [toRope(literal)]);
tkOpr, tkHat: tkOpr, tkHat:
appRopeFormat(result, '<span class="Operator">$1</span>', appf(result, '<span class="Operator">$1</span>',
[toRope(toXml(literal))]); [toRope(toXml(literal))]);
tkStrLit..tkTripleStrLit: tkStrLit..tkTripleStrLit:
appRopeFormat(result, '<span class="StringLit">$1</span>', appf(result, '<span class="StringLit">$1</span>',
[toRope(toXml(literal))]); [toRope(toXml(literal))]);
tkCharLit, tkRCharLit: tkCharLit:
appRopeFormat(result, '<span class="CharLit">$1</span>', appf(result, '<span class="CharLit">$1</span>',
[toRope(toXml(literal))]); [toRope(toXml(literal))]);
tkIntLit..tkInt64Lit: tkIntLit..tkInt64Lit:
appRopeFormat(result, '<span class="DecNumber">$1</span>', appf(result, '<span class="DecNumber">$1</span>',
[toRope(literal)]); [toRope(literal)]);
tkFloatLit..tkFloat64Lit: tkFloatLit..tkFloat64Lit:
appRopeFormat(result, '<span class="FloatNumber">$1</span>', appf(result, '<span class="FloatNumber">$1</span>',
[toRope(literal)]); [toRope(literal)]);
tkSymbol: tkSymbol:
appRopeFormat(result, '<span class="Identifier">$1</span>', appf(result, '<span class="Identifier">$1</span>',
[toRope(literal)]); [toRope(literal)]);
tkInd, tkSad, tkDed, tkSpaces: tkInd, tkSad, tkDed, tkSpaces:
app(result, literal); app(result, literal);
//appRopeFormat(result, '<span class="Whitespace">$1</span>', //appf(result, '<span class="Whitespace">$1</span>',
// [toRope(literal)]); // [toRope(literal)]);
tkParLe, tkParRi, tkBracketLe, tkBracketRi, tkCurlyLe, tkCurlyRi, tkParLe, tkParRi, tkBracketLe, tkBracketRi, tkCurlyLe, tkCurlyRi,
tkBracketDotLe, tkBracketDotRi, tkCurlyDotLe, tkCurlyDotRi, tkBracketDotLe, tkBracketDotRi, tkCurlyDotLe, tkCurlyDotRi,
tkParDotLe, tkParDotRi, tkComma, tkSemiColon, tkColon, tkParDotLe, tkParDotRi, tkComma, tkSemiColon, tkColon,
tkEquals, tkDot, tkDotDot, tkAccent: tkEquals, tkDot, tkDotDot, tkAccent:
appRopeFormat(result, '<span class="Other">$1</span>', appf(result, '<span class="Other">$1</span>',
[toRope(literal)]); [toRope(literal)]);
else InternalError(n.info, 'docgen.genThing(' + toktypeToStr[kind] + ')'); else InternalError(n.info, 'docgen.genThing(' + toktypeToStr[kind] + ')');
end end
@ -397,7 +410,7 @@ begin
[name, result, comm, toRope(d.id)])); [name, result, comm, toRope(d.id)]));
app(d.toc[k], ropeFormatNamedVars(getConfigVar('doc.item.toc'), app(d.toc[k], ropeFormatNamedVars(getConfigVar('doc.item.toc'),
['name', 'header', 'desc', 'itemID'], ['name', 'header', 'desc', 'itemID'],
[name, result, comm, toRope(d.id)])); [toRope(getName(nameNode, d.splitAfter)), result, comm, toRope(d.id)]));
setIndexForSourceTerm(d, getRstName(nameNode), d.id); setIndexForSourceTerm(d, getRstName(nameNode), d.id);
end; end;
@ -416,12 +429,12 @@ begin
d.tocPart[len].refname := refname; d.tocPart[len].refname := refname;
d.tocPart[len].n := n; d.tocPart[len].n := n;
d.tocPart[len].header := result; d.tocPart[len].header := result;
result := ropeFormat('<h$1><a class="toc-backref" id="$2" href="#$2_toc">$3'+ result := ropef('<h$1><a class="toc-backref" id="$2" href="#$2_toc">$3'+
'</a></h$1>', '</a></h$1>',
[toRope(n.level), d.tocPart[len].refname, result]); [toRope(n.level), d.tocPart[len].refname, result]);
end end
else else
result := ropeFormat('<h$1 id="$2">$3</h$1>', result := ropef('<h$1 id="$2">$3</h$1>',
[toRope(n.level), refname, result]); [toRope(n.level), refname, result]);
end; end;
@ -437,7 +450,7 @@ begin
if d.meta[metaTitle] = nil then d.meta[metaTitle] := t if d.meta[metaTitle] = nil then d.meta[metaTitle] := t
else if d.meta[metaSubtitle] = nil then d.meta[metaSubtitle] := t else if d.meta[metaSubtitle] = nil then d.meta[metaSubtitle] := t
else else
result := ropeFormat('<h$1 id="$2"><center>$3</center></h$1>', result := ropef('<h$1 id="$2"><center>$3</center></h$1>',
[toRope(n.level), toRope(rstnodeToRefname(n)), t]); [toRope(n.level), toRope(rstnodeToRefname(n)), t]);
end; end;
@ -469,32 +482,32 @@ begin
rnHeadline: begin rnHeadline: begin
result := renderRstSons(d, n); result := renderRstSons(d, n);
L := ropeLen(result); L := ropeLen(result);
result := ropeFormat('$n$1$2$n$1$3', [ind, result, result := ropef('$n$1$2$n$1$3', [ind, result,
toRope(repeatChar(L, lvlToChar[n.level]))]); toRope(repeatChar(L, lvlToChar[n.level]))]);
end; end;
rnOverline: begin rnOverline: begin
result := renderRstSons(d, n); result := renderRstSons(d, n);
L := ropeLen(result); L := ropeLen(result);
result := ropeFormat('$n$1$3$n$1$2$n$1$3', [ind, result, result := ropef('$n$1$3$n$1$2$n$1$3', [ind, result,
toRope(repeatChar(L, lvlToChar[n.level]))]); toRope(repeatChar(L, lvlToChar[n.level]))]);
end; end;
rnTransition: rnTransition:
result := ropeFormat('$n$n$1$2$n$n', result := ropef('$n$n$1$2$n$n',
[ind, toRope(repeatChar(78-d.indent, '-'))]); [ind, toRope(repeatChar(78-d.indent, '-'))]);
rnParagraph: begin rnParagraph: begin
result := renderRstSons(d, n); result := renderRstSons(d, n);
result := ropeFormat('$n$n$1$2', [ind, result]); result := ropef('$n$n$1$2', [ind, result]);
end; end;
rnBulletItem: begin rnBulletItem: begin
inc(d.indent, 2); inc(d.indent, 2);
result := renderRstSons(d, n); result := renderRstSons(d, n);
if result <> nil then result := ropeFormat('$n$1* $2', [ind, result]); if result <> nil then result := ropef('$n$1* $2', [ind, result]);
dec(d.indent, 2); dec(d.indent, 2);
end; end;
rnEnumItem: begin rnEnumItem: begin
inc(d.indent, 4); inc(d.indent, 4);
result := renderRstSons(d, n); result := renderRstSons(d, n);
if result <> nil then result := ropeFormat('$n$1(#) $2', [ind, result]); if result <> nil then result := ropef('$n$1(#) $2', [ind, result]);
dec(d.indent, 4); dec(d.indent, 4);
end; end;
rnOptionList, rnFieldList, rnDefList, rnDefItem, rnLineBlock, rnFieldName, rnOptionList, rnFieldList, rnDefList, rnDefItem, rnLineBlock, rnFieldName,
@ -502,27 +515,27 @@ begin
result := renderRstSons(d, n); result := renderRstSons(d, n);
rnDefName: begin rnDefName: begin
result := renderRstSons(d, n); result := renderRstSons(d, n);
result := ropeFormat('$n$n$1$2', [ind, result]); result := ropef('$n$n$1$2', [ind, result]);
end; end;
rnDefBody: begin rnDefBody: begin
inc(d.indent, 2); inc(d.indent, 2);
result := renderRstSons(d, n); result := renderRstSons(d, n);
if n.sons[0].kind <> rnBulletList then if n.sons[0].kind <> rnBulletList then
result := ropeFormat('$n$1 $2', [ind, result]); result := ropef('$n$1 $2', [ind, result]);
dec(d.indent, 2); dec(d.indent, 2);
end; end;
rnField: begin rnField: begin
result := renderRstToRst(d, n.sons[0]); result := renderRstToRst(d, n.sons[0]);
L := max(ropeLen(result)+3, 30); L := max(ropeLen(result)+3, 30);
inc(d.indent, L); inc(d.indent, L);
result := ropeFormat('$n$1:$2:$3$4', [ result := ropef('$n$1:$2:$3$4', [
ind, result, toRope(repeatChar(L-ropeLen(result)-2)), ind, result, toRope(repeatChar(L-ropeLen(result)-2)),
renderRstToRst(d, n.sons[1])]); renderRstToRst(d, n.sons[1])]);
dec(d.indent, L); dec(d.indent, L);
end; end;
rnLineBlockItem: begin rnLineBlockItem: begin
result := renderRstSons(d, n); result := renderRstSons(d, n);
result := ropeFormat('$n$1| $2', [ind, result]); result := ropef('$n$1| $2', [ind, result]);
end; end;
rnBlockQuote: begin rnBlockQuote: begin
inc(d.indent, 2); inc(d.indent, 2);
@ -531,44 +544,44 @@ begin
end; end;
rnRef: begin rnRef: begin
result := renderRstSons(d, n); result := renderRstSons(d, n);
result := ropeFormat('`$1`_', [result]); result := ropef('`$1`_', [result]);
end; end;
rnHyperlink: begin rnHyperlink: begin
result := ropeFormat('`$1 <$2>`_', [renderRstToRst(d, n.sons[0]), result := ropef('`$1 <$2>`_', [renderRstToRst(d, n.sons[0]),
renderRstToRst(d, n.sons[1])]); renderRstToRst(d, n.sons[1])]);
end; end;
rnGeneralRole: begin rnGeneralRole: begin
result := renderRstToRst(d, n.sons[0]); result := renderRstToRst(d, n.sons[0]);
result := ropeFormat('`$1`:$2:', [result, renderRstToRst(d, n.sons[1])]); result := ropef('`$1`:$2:', [result, renderRstToRst(d, n.sons[1])]);
end; end;
rnSub: begin rnSub: begin
result := renderRstSons(d, n); result := renderRstSons(d, n);
result := ropeFormat('`$1`:sub:', [result]); result := ropef('`$1`:sub:', [result]);
end; end;
rnSup: begin rnSup: begin
result := renderRstSons(d, n); result := renderRstSons(d, n);
result := ropeFormat('`$1`:sup:', [result]); result := ropef('`$1`:sup:', [result]);
end; end;
rnIdx: begin rnIdx: begin
result := renderRstSons(d, n); result := renderRstSons(d, n);
result := ropeFormat('`$1`:idx:', [result]); result := ropef('`$1`:idx:', [result]);
end; end;
rnEmphasis: begin rnEmphasis: begin
result := renderRstSons(d, n); result := renderRstSons(d, n);
result := ropeFormat('*$1*', [result]); result := ropef('*$1*', [result]);
end; end;
rnStrongEmphasis: begin rnStrongEmphasis: begin
result := renderRstSons(d, n); result := renderRstSons(d, n);
result := ropeFormat('**$1**', [result]); result := ropef('**$1**', [result]);
end; end;
rnInterpretedText: begin rnInterpretedText: begin
result := renderRstSons(d, n); result := renderRstSons(d, n);
result := ropeFormat('`$1`', [result]); result := ropef('`$1`', [result]);
end; end;
rnInlineLiteral: begin rnInlineLiteral: begin
inc(d.verbatim); inc(d.verbatim);
result := renderRstSons(d, n); result := renderRstSons(d, n);
result := ropeFormat('``$1``', [result]); result := ropef('``$1``', [result]);
dec(d.verbatim); dec(d.verbatim);
end; end;
rnLeaf: begin rnLeaf: begin
@ -582,10 +595,10 @@ begin
if n.sons[2] <> nil then if n.sons[2] <> nil then
result := renderRstSons(d, n.sons[2]); result := renderRstSons(d, n.sons[2]);
dec(d.indent, 3); dec(d.indent, 3);
result := ropeFormat('$n$n$1.. index::$n$2', [ind, result]); result := ropef('$n$n$1.. index::$n$2', [ind, result]);
end; end;
rnContents: begin rnContents: begin
result := ropeFormat('$n$n$1.. contents::', [ind]); result := ropef('$n$n$1.. contents::', [ind]);
end; end;
else rawMessage(errCannotRenderX, rstnodeKindToStr[n.kind]); else rawMessage(errCannotRenderX, rstnodeKindToStr[n.kind]);
end; end;
@ -593,7 +606,7 @@ end;
function renderTocEntry(d: PDoc; const e: TTocEntry): PRope; function renderTocEntry(d: PDoc; const e: TTocEntry): PRope;
begin begin
result := ropeFormat('<li><a class="reference" id="$1_toc" href="#$1">$2' + result := ropef('<li><a class="reference" id="$1_toc" href="#$1">$2' +
'</a></li>$n', [e.refname, e.header]); '</a></li>$n', [e.refname, e.header]);
end; end;
@ -614,24 +627,24 @@ begin
break break
end; end;
if lvl > 1 then if lvl > 1 then
result := ropeFormat('<ul class="simple">$1</ul>', [result]); result := ropef('<ul class="simple">$1</ul>', [result]);
end; end;
function renderImage(d: PDoc; n: PRstNode): PRope; function renderImage(d: PDoc; n: PRstNode): PRope;
var var
s: string; s: string;
begin begin
result := ropeFormat('<img src="$1"', [toRope(getArgument(n))]); result := ropef('<img src="$1"', [toRope(getArgument(n))]);
s := getFieldValue(n, 'height'); s := getFieldValue(n, 'height');
if s <> '' then appRopeFormat(result, ' height="$1"', [toRope(s)]); if s <> '' then appf(result, ' height="$1"', [toRope(s)]);
s := getFieldValue(n, 'width'); s := getFieldValue(n, 'width');
if s <> '' then appRopeFormat(result, ' width="$1"', [toRope(s)]); if s <> '' then appf(result, ' width="$1"', [toRope(s)]);
s := getFieldValue(n, 'scale'); s := getFieldValue(n, 'scale');
if s <> '' then appRopeFormat(result, ' scale="$1"', [toRope(s)]); if s <> '' then appf(result, ' scale="$1"', [toRope(s)]);
s := getFieldValue(n, 'alt'); s := getFieldValue(n, 'alt');
if s <> '' then appRopeFormat(result, ' alt="$1"', [toRope(s)]); if s <> '' then appf(result, ' alt="$1"', [toRope(s)]);
s := getFieldValue(n, 'align'); s := getFieldValue(n, 'align');
if s <> '' then appRopeFormat(result, ' align="$1"', [toRope(s)]); if s <> '' then appf(result, ' align="$1"', [toRope(s)]);
app(result, ' />'); app(result, ' />');
if rsonsLen(n) >= 3 then app(result, renderRstToHtml(d, n.sons[2])) if rsonsLen(n) >= 3 then app(result, renderRstToHtml(d, n.sons[2]))
end; end;
@ -644,14 +657,14 @@ var
lang: TSourceLanguage; lang: TSourceLanguage;
begin begin
m := n.sons[2].sons[0]; m := n.sons[2].sons[0];
assert(m.kind = rnLeaf); if (m.kind <> rnLeaf) then InternalError('renderCodeBlock');
result := nil; result := nil;
langstr := strip(getArgument(n)); langstr := strip(getArgument(n));
if langstr = '' then lang := langNimrod // default language if langstr = '' then lang := langNimrod // default language
else lang := getSourceLanguage(langstr); else lang := getSourceLanguage(langstr);
if lang = langNone then begin if lang = langNone then begin
rawMessage(warnLanguageXNotSupported, langstr); rawMessage(warnLanguageXNotSupported, langstr);
result := ropeFormat('<pre>$1</pre>', [toRope(m.text)]) result := ropef('<pre>$1</pre>', [toRope(m.text)])
end end
else begin else begin
initGeneralTokenizer(g, m.text); initGeneralTokenizer(g, m.text);
@ -660,15 +673,17 @@ begin
case g.kind of case g.kind of
gtEof: break; gtEof: break;
gtNone, gtWhitespace: gtNone, gtWhitespace:
app(result, ncopy(m.text, g.start+strStart, g.len+g.start)); app(result, ncopy(m.text, g.start+strStart,
g.len+g.start-1+strStart));
else else
appRopeFormat(result, '<span class="$2">$1</span>', appf(result, '<span class="$2">$1</span>',
[toRope(ncopy(m.text, g.start+strStart, g.len+g.start)), [toRope(ncopy(m.text, g.start+strStart,
g.len+g.start-1+strStart)),
toRope(tokenClassToStr[g.kind])]); toRope(tokenClassToStr[g.kind])]);
end; end;
end; end;
deinitGeneralTokenizer(g); deinitGeneralTokenizer(g);
if result <> nil then result := ropeFormat('<pre>$1</pre>', [result]); if result <> nil then result := ropef('<pre>$1</pre>', [result]);
end end
end; end;
@ -719,10 +734,10 @@ begin
rnDescription: outer := '<td align="left">$1</td>$n'; rnDescription: outer := '<td align="left">$1</td>$n';
rnOption, rnOption,
rnOptionString, rnOptionString,
rnOptionArgument: assert(false); rnOptionArgument: InternalError('renderRstToHtml');
rnLiteralBlock: outer := '<pre>$1</pre>'+nl; rnLiteralBlock: outer := '<pre>$1</pre>'+nl;
rnQuotedLiteralBlock: assert(false); rnQuotedLiteralBlock: InternalError('renderRstToHtml');
rnLineBlock: outer := '<p>$1</p>'; rnLineBlock: outer := '<p>$1</p>';
rnLineBlockItem: outer := '$1<br />'; rnLineBlockItem: outer := '$1<br />';
@ -735,19 +750,19 @@ begin
rnTableDataCell: outer := '<td>$1</td>'; rnTableDataCell: outer := '<td>$1</td>';
rnTableHeaderCell: outer := '<th>$1</th>'; rnTableHeaderCell: outer := '<th>$1</th>';
rnLabel: assert(false); // used for footnotes and other things rnLabel: InternalError('renderRstToHtml'); // used for footnotes and other
rnFootnote: assert(false); // a footnote rnFootnote: InternalError('renderRstToHtml'); // a footnote
rnCitation: assert(false); // similar to footnote rnCitation: InternalError('renderRstToHtml'); // similar to footnote
rnRef: begin rnRef: begin
result := ropeFormat('<a class="reference external" href="#$2">$1</a>', result := ropef('<a class="reference external" href="#$2">$1</a>',
[renderAux(d, n), toRope(rstnodeToRefname(n))]); [renderAux(d, n), toRope(rstnodeToRefname(n))]);
exit exit
end; end;
rnStandaloneHyperlink: rnStandaloneHyperlink:
outer := '<a class="reference external" href="$1">$1</a>'; outer := '<a class="reference external" href="$1">$1</a>';
rnHyperlink: begin rnHyperlink: begin
result := ropeFormat('<a class="reference external" href="$2">$1</a>', result := ropef('<a class="reference external" href="$2">$1</a>',
[renderRstToHtml(d, n.sons[0]), [renderRstToHtml(d, n.sons[0]),
renderRstToHtml(d, n.sons[1])]); renderRstToHtml(d, n.sons[1])]);
exit exit
@ -766,7 +781,7 @@ begin
// Inline markup: // Inline markup:
rnGeneralRole: begin rnGeneralRole: begin
result := ropeFormat('<span class="$2">$1</span>', result := ropef('<span class="$2">$1</span>',
[renderRstToHtml(d, n.sons[0]), [renderRstToHtml(d, n.sons[0]),
renderRstToHtml(d, n.sons[1])]); renderRstToHtml(d, n.sons[1])]);
exit exit
@ -798,7 +813,7 @@ begin
d.meta[metaTitle] := renderRstToHtml(d, n.sons[0]); d.meta[metaTitle] := renderRstToHtml(d, n.sons[0]);
exit exit
end; end;
else assert(false); else InternalError('renderRstToHtml');
end; end;
result := renderAux(d, n, outer, inner); result := renderAux(d, n, outer, inner);
end; end;
@ -814,6 +829,7 @@ begin
nkIteratorDef: genItem(d, n, n.sons[namePos], skIterator); nkIteratorDef: genItem(d, n, n.sons[namePos], skIterator);
nkMacroDef: genItem(d, n, n.sons[namePos], skMacro); nkMacroDef: genItem(d, n, n.sons[namePos], skMacro);
nkTemplateDef: genItem(d, n, n.sons[namePos], skTemplate); nkTemplateDef: genItem(d, n, n.sons[namePos], skTemplate);
nkConverterDef: genItem(d, n, n.sons[namePos], skConverter);
nkVarSection: begin nkVarSection: begin
for i := 0 to sonsLen(n)-1 do for i := 0 to sonsLen(n)-1 do
genItem(d, n.sons[i], n.sons[i].sons[0], skVar); genItem(d, n.sons[i], n.sons[i].sons[0], skVar);
@ -860,13 +876,15 @@ var
begin begin
j := 0; j := 0;
toc := renderTocEntries(d, j, 1); toc := renderTocEntries(d, j, 1);
code := nil;
content := nil;
title := nil;
for i := low(TSymKind) to high(TSymKind) do begin for i := low(TSymKind) to high(TSymKind) do begin
genSection(d, i); genSection(d, i);
app(toc, d.toc[i]); app(toc, d.toc[i]);
end; end;
if toc <> nil then if toc <> nil then
toc := ropeFormatNamedVars(getConfigVar('doc.toc'), ['content'], [toc]); toc := ropeFormatNamedVars(getConfigVar('doc.toc'), ['content'], [toc]);
code := nil;
for i := low(TSymKind) to high(TSymKind) do for i := low(TSymKind) to high(TSymKind) do
app(code, d.section[i]); app(code, d.section[i]);
if d.meta[metaTitle] <> nil then if d.meta[metaTitle] <> nil then
@ -918,13 +936,16 @@ var
filen: string; filen: string;
d: PDoc; d: PDoc;
rst: PRstNode; rst: PRstNode;
code: PRope;
begin begin
filen := appendFileExt(filename, 'txt'); filen := appendFileExt(filename, 'txt');
d := newDocumentor(filen); d := newDocumentor(filen);
initIndexFile(d); initIndexFile(d);
rst := rstParse(readFile(filen), false, filen, 0, 1, d.hasToc); rst := rstParse(readFile(filen), false, filen, 0, 1, d.hasToc);
d.modDesc := renderRstToHtml(d, rst); d.modDesc := renderRstToHtml(d, rst);
writeRope(genHtmlFile(d), getOutFile(filename, HtmlExt)); code := genHtmlFile(d);
assert(ropeInvariant(code));
writeRope(code, getOutFile(filename, HtmlExt));
generateIndex(d); generateIndex(d);
end; end;

1869
nim/ecmasgen.pas Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -15,7 +15,9 @@ interface
{$include 'config.inc'} {$include 'config.inc'}
uses uses
nimconf, msgs; // some things are read in from the configuration file nsystem, nimconf, msgs;
// some things are read in from the configuration file
type type
TSystemCC = (ccNone, ccGcc, ccLLVM_Gcc, ccLcc, ccBcc, ccDmc, ccWcc, ccVcc, TSystemCC = (ccNone, ccGcc, ccLLVM_Gcc, ccLcc, ccBcc, ccDmc, ccWcc, ccVcc,
@ -27,15 +29,17 @@ type
hasCpp // CC is/contains a C++ compiler hasCpp // CC is/contains a C++ compiler
); );
TInfoCCProps = set of TInfoCCProp; TInfoCCProps = set of TInfoCCProp;
TInfoCC = record TInfoCC = record{@tuple}
name: string; // the short name of the compiler name: string; // the short name of the compiler
objExt: string; // the compiler's object file extenstion objExt: string; // the compiler's object file extenstion
optSpeed: string; // the options for optimization for speed optSpeed: string; // the options for optimization for speed
optSize: string; // the options for optimization for size optSize: string; // the options for optimization for size
compile: string; // the compile command template compilerExe: string; // the compiler's executable
compileTmpl: string; // the compile command template
buildGui: string; // command to build a GUI application buildGui: string; // command to build a GUI application
buildDll: string; // command to build a shared library buildDll: string; // command to build a shared library
link: string; // command to link files to produce an executable linkerExe: string; // the linker's executable
linkTmpl: string; // command to link files to produce an executable
includeCmd: string; // command to add an include directory path includeCmd: string; // command to add an include directory path
debug: string; // flags for debug build debug: string; // flags for debug build
pic: string; // command for position independent code pic: string; // command for position independent code
@ -50,10 +54,12 @@ const
objExt: 'o'+''; objExt: 'o'+'';
optSpeed: ' -O3 -ffast-math '; optSpeed: ' -O3 -ffast-math ';
optSize: ' -Os -ffast-math '; optSize: ' -Os -ffast-math ';
compile: 'gcc -c $options $include -o $objfile $file'; compilerExe: 'gcc';
compileTmpl: '-c $options $include -o $objfile $file';
buildGui: ' -mwindows'; buildGui: ' -mwindows';
buildDll: ' -mdll'; buildDll: ' -mdll';
link: 'gcc $options $buildgui $builddll -o $exefile $objfiles'; linkerExe: 'gcc';
linkTmpl: '$options $buildgui $builddll -o $exefile $objfiles';
includeCmd: ' -I'; includeCmd: ' -I';
debug: ''; debug: '';
pic: '-fPIC'; pic: '-fPIC';
@ -65,10 +71,12 @@ const
objExt: 'o'+''; objExt: 'o'+'';
optSpeed: ' -O3 -ffast-math '; optSpeed: ' -O3 -ffast-math ';
optSize: ' -Os -ffast-math '; optSize: ' -Os -ffast-math ';
compile: 'llvm-gcc -c $options $include -o $objfile $file'; compilerExe: 'llvm-gcc';
compileTmpl: '-c $options $include -o $objfile $file';
buildGui: ' -mwindows'; buildGui: ' -mwindows';
buildDll: ' -mdll'; buildDll: ' -mdll';
link: 'llvm-gcc $options $buildgui $builddll -o $exefile $objfiles'; linkerExe: 'llvm-gcc';
linkTmpl: '$options $buildgui $builddll -o $exefile $objfiles';
includeCmd: ' -I'; includeCmd: ' -I';
debug: ''; debug: '';
pic: '-fPIC'; pic: '-fPIC';
@ -80,10 +88,12 @@ const
objExt: 'obj'; objExt: 'obj';
optSpeed: ' -O -p6 '; optSpeed: ' -O -p6 ';
optSize: ' -O -p6 '; optSize: ' -O -p6 ';
compile: 'lcc -e1 $options $include -Fo$objfile $file'; compilerExe: 'lcc';
compileTmpl: '-e1 $options $include -Fo$objfile $file';
buildGui: ' -subsystem windows'; buildGui: ' -subsystem windows';
buildDll: ' -dll'; buildDll: ' -dll';
link: 'lcclnk $options $buildgui $builddll -O $exefile $objfiles'; linkerExe: 'lcclnk';
linkTmpl: '$options $buildgui $builddll -O $exefile $objfiles';
includeCmd: ' -I'; includeCmd: ' -I';
debug: ' -g5 '; debug: ' -g5 ';
pic: ''; pic: '';
@ -95,10 +105,12 @@ const
objExt: 'obj'; objExt: 'obj';
optSpeed: ' -O2 -6 '; optSpeed: ' -O2 -6 ';
optSize: ' -O1 -6 '; optSize: ' -O1 -6 ';
compile: 'bcc32 -c $options $include -o$objfile $file'; compilerExe: 'bcc32';
compileTmpl: '-c $options $include -o$objfile $file';
buildGui: ' -tW'; buildGui: ' -tW';
buildDll: ' -tWD'; buildDll: ' -tWD';
link: 'bcc32 $options $buildgui $builddll -e$exefile $objfiles'; linkerExe: 'bcc32';
linkTmpl: '$options $buildgui $builddll -e$exefile $objfiles';
includeCmd: ' -I'; includeCmd: ' -I';
debug: ''; debug: '';
pic: ''; pic: '';
@ -110,10 +122,12 @@ const
objExt: 'obj'; objExt: 'obj';
optSpeed: ' -ff -o -6 '; optSpeed: ' -ff -o -6 ';
optSize: ' -ff -o -6 '; optSize: ' -ff -o -6 ';
compile: 'dmc -c $options $include -o$objfile $file'; compilerExe: 'dmc';
compileTmpl: '-c $options $include -o$objfile $file';
buildGui: ' -L/exet:nt/su:windows'; buildGui: ' -L/exet:nt/su:windows';
buildDll: ' -WD'; buildDll: ' -WD';
link: 'dmc $options $buildgui $builddll -o$exefile $objfiles'; linkerExe: 'dmc';
linkTmpl: '$options $buildgui $builddll -o$exefile $objfiles';
includeCmd: ' -I'; includeCmd: ' -I';
debug: ' -g '; debug: ' -g ';
pic: ''; pic: '';
@ -125,10 +139,12 @@ const
objExt: 'obj'; objExt: 'obj';
optSpeed: ' -ox -on -6 -d0 -fp6 -zW '; optSpeed: ' -ox -on -6 -d0 -fp6 -zW ';
optSize: ''; optSize: '';
compile: 'wcl386 -c $options $include -fo=$objfile $file'; compilerExe: 'wcl386';
compileTmpl: '-c $options $include -fo=$objfile $file';
buildGui: ' -bw'; buildGui: ' -bw';
buildDll: ' -bd'; buildDll: ' -bd';
link: 'wcl386 $options $buildgui $builddll -fe=$exefile $objfiles '; linkerExe: 'wcl386';
linkTmpl: '$options $buildgui $builddll -fe=$exefile $objfiles ';
includeCmd: ' -i='; includeCmd: ' -i=';
debug: ' -d2 '; debug: ' -d2 ';
pic: ''; pic: '';
@ -140,10 +156,12 @@ const
objExt: 'obj'; objExt: 'obj';
optSpeed: ' /Ogityb2 /G7 /arch:SSE2 '; optSpeed: ' /Ogityb2 /G7 /arch:SSE2 ';
optSize: ' /O1 /G7 '; optSize: ' /O1 /G7 ';
compile: 'cl /c $options $include /Fo$objfile $file'; compilerExe: 'cl';
compileTmpl: '/c $options $include /Fo$objfile $file';
buildGui: ' /link /SUBSYSTEM:WINDOWS '; buildGui: ' /link /SUBSYSTEM:WINDOWS ';
buildDll: ' /LD'; buildDll: ' /LD';
link: 'cl $options $builddll /Fe$exefile $objfiles $buildgui'; linkerExe: 'cl';
linkTmpl: '$options $builddll /Fe$exefile $objfiles $buildgui';
includeCmd: ' /I'; includeCmd: ' /I';
debug: ' /GZ /Zi '; debug: ' /GZ /Zi ';
pic: ''; pic: '';
@ -155,10 +173,12 @@ const
objExt: 'o'+''; objExt: 'o'+'';
optSpeed: ''; optSpeed: '';
optSize: ''; optSize: '';
compile: 'tcc -c $options $include -o $objfile $file'; compilerExe: 'tcc';
compileTmpl: '-c $options $include -o $objfile $file';
buildGui: 'UNAVAILABLE!'; buildGui: 'UNAVAILABLE!';
buildDll: ' -shared'; buildDll: ' -shared';
link: 'tcc -o $exefile $options $buildgui $builddll $objfiles'; linkerExe: 'tcc';
linkTmpl: '-o $exefile $options $buildgui $builddll $objfiles';
includeCmd: ' -I'; includeCmd: ' -I';
debug: ' -g '; debug: ' -g ';
pic: ''; pic: '';
@ -170,10 +190,12 @@ const
objExt: 'obj'; objExt: 'obj';
optSpeed: ' -Ox '; optSpeed: ' -Ox ';
optSize: ' -Os '; optSize: ' -Os ';
compile: 'cc -c $options $include -Fo$objfile $file'; compilerExe: 'cc';
compileTmpl: '-c $options $include -Fo$objfile $file';
buildGui: ' -SUBSYSTEM:WINDOWS'; buildGui: ' -SUBSYSTEM:WINDOWS';
buildDll: ' -DLL'; buildDll: ' -DLL';
link: 'cc $options $buildgui $builddll -OUT:$exefile $objfiles'; linkerExe: 'cc';
linkTmpl: '$options $buildgui $builddll -OUT:$exefile $objfiles';
includeCmd: ' -I'; includeCmd: ' -I';
debug: ' -Zi '; debug: ' -Zi ';
pic: ''; pic: '';
@ -185,10 +207,12 @@ const
objExt: 'o'+''; objExt: 'o'+'';
optSpeed: ' -O3 '; optSpeed: ' -O3 ';
optSize: ' -O1 '; optSize: ' -O1 ';
compile: 'cc -c $options $include -o $objfile $file'; compilerExe: 'cc';
compileTmpl: '-c $options $include -o $objfile $file';
buildGui: ''; buildGui: '';
buildDll: ' -shared '; buildDll: ' -shared ';
link: 'cc -o $exefile $options $buildgui $builddll $objfiles'; linkerExe: 'cc';
linkTmpl: '-o $exefile $options $buildgui $builddll $objfiles';
includeCmd: ' -I'; includeCmd: ' -I';
debug: ''; debug: '';
pic: ''; pic: '';
@ -199,10 +223,12 @@ const
objExt: 'o'+''; objExt: 'o'+'';
optSpeed: ' -O3 '; optSpeed: ' -O3 ';
optSize: ' -Os '; optSize: ' -Os ';
compile: 'icc -c $options $include -o $objfile $file'; compilerExe: 'icc';
compileTmpl: '-c $options $include -o $objfile $file';
buildGui: ' -mwindows'; buildGui: ' -mwindows';
buildDll: ' -mdll'; buildDll: ' -mdll';
link: 'icc $options $buildgui $builddll -o $exefile $objfiles'; linkerExe: 'icc';
linkTmpl: '$options $buildgui $builddll -o $exefile $objfiles';
includeCmd: ' -I'; includeCmd: ' -I';
debug: ''; debug: '';
pic: '-fPIC'; pic: '-fPIC';
@ -213,10 +239,12 @@ const
objExt: 'o'+''; objExt: 'o'+'';
optSpeed: ' -O3 -ffast-math '; optSpeed: ' -O3 -ffast-math ';
optSize: ' -Os -ffast-math '; optSize: ' -Os -ffast-math ';
compile: 'g++ -c $options $include -o $objfile $file'; compilerExe: 'g++';
compileTmpl: '-c $options $include -o $objfile $file';
buildGui: ' -mwindows'; buildGui: ' -mwindows';
buildDll: ' -mdll'; buildDll: ' -mdll';
link: 'g++ $options $buildgui $builddll -o $exefile $objfiles'; linkerExe: 'g++';
linkTmpl: '$options $buildgui $builddll -o $exefile $objfiles';
includeCmd: ' -I'; includeCmd: ' -I';
debug: ' -g '; debug: ' -g ';
pic: '-fPIC'; pic: '-fPIC';
@ -238,6 +266,9 @@ var
function completeCFilePath(const cfile: string; function completeCFilePath(const cfile: string;
createSubDir: Boolean = true): string; createSubDir: Boolean = true): string;
function getCompileCFileCmd(const cfilename: string;
isExternal: bool = false): string;
procedure addFileToCompile(const filename: string); procedure addFileToCompile(const filename: string);
procedure addExternalFileToCompile(const filename: string); procedure addExternalFileToCompile(const filename: string);
procedure addFileToLink(const filename: string); procedure addFileToLink(const filename: string);
@ -260,7 +291,7 @@ procedure setCC(const ccname: string);
implementation implementation
uses uses
nsystem, charsets, charsets,
lists, options, ropes, nos, strutils, platform, condsyms; lists, options, ropes, nos, strutils, platform, condsyms;
var var
@ -389,16 +420,13 @@ begin
result := cc[c].optSize // use default settings from this file result := cc[c].optSize // use default settings from this file
end; end;
procedure CompileCFile(const list: TLinkedList; function getCompileCFileCmd(const cfilename: string;
var script: PRope; isExternal: Boolean); isExternal: bool = false): string;
var var
it: PStrEntry; cfile, objfile, options, includeCmd, compilePattern: string;
compileCmd, cfile, objfile, options, includeCmd, compilePattern: string;
c: TSystemCC; // an alias to ccompiler c: TSystemCC; // an alias to ccompiler
begin begin
c := ccompiler; c := ccompiler;
it := PStrEntry(list.head);
options := compileOptions; options := compileOptions;
if optCDebug in gGlobalOptions then addStr(options, ' ' + getDebug(c)); if optCDebug in gGlobalOptions then addStr(options, ' ' + getDebug(c));
if optOptimizeSpeed in gOptions then addStr(options, ' ' + getOptSpeed(c)) if optOptimizeSpeed in gOptions then addStr(options, ' ' + getOptSpeed(c))
@ -413,31 +441,43 @@ begin
includeCmd := cc[c].includeCmd; // this is more complex than needed, but includeCmd := cc[c].includeCmd; // this is more complex than needed, but
// a workaround of a FPC bug... // a workaround of a FPC bug...
addStr(includeCmd, libpath); addStr(includeCmd, libpath);
compilePattern := JoinPath(ccompilerpath, cc[c].compile); compilePattern := quoteIfSpaceExists(
JoinPath(ccompilerpath, cc[c].compilerExe));
end end
else begin else begin
includeCmd := ''; includeCmd := '';
compilePattern := cc[c].compile compilePattern := cc[c].compilerExe
end; end;
while it <> nil do begin
// call the C compiler for the .c file:
if targetOS = hostOS then if targetOS = hostOS then
cfile := it.data cfile := cfilename
else else
cfile := extractFileName(it.data); cfile := extractFileName(cfilename);
if not isExternal or (targetOS <> hostOS) then if not isExternal or (targetOS <> hostOS) then
objfile := toObjFile(cfile) objfile := toObjFile(cfile)
else else
objfile := completeCFilePath(toObjFile(cfile)); objfile := completeCFilePath(toObjFile(cfile));
compileCmd := format(compilePattern, result := compilePattern +{&} ' ' +{&} format(cc[c].compileTmpl,
['file', AppendFileExt(cfile, cExt), ['file', AppendFileExt(cfile, cExt),
'objfile', objfile, 'objfile', objfile,
'options', options, 'options', options,
'include', includeCmd 'include', includeCmd,
'nimrod', getPrefixDir(),
'lib', libpath
]); ]);
end;
procedure CompileCFile(const list: TLinkedList;
var script: PRope; isExternal: Boolean);
var
it: PStrEntry;
compileCmd: string;
begin
it := PStrEntry(list.head);
while it <> nil do begin
// call the C compiler for the .c file:
compileCmd := getCompileCFileCmd(it.data, isExternal);
if not (optCompileOnly in gGlobalOptions) then if not (optCompileOnly in gGlobalOptions) then
execExternalProgram(compileCmd); execExternalProgram(compileCmd);
if (optGenScript in gGlobalOptions) then begin if (optGenScript in gGlobalOptions) then begin
@ -469,9 +509,9 @@ begin
if not (optNoLinking in gGlobalOptions) then begin if not (optNoLinking in gGlobalOptions) then begin
// call the linker: // call the linker:
if (hostOS <> targetOS) then if (hostOS <> targetOS) then
linkCmd := cc[c].link linkCmd := cc[c].linkerExe
else else
linkCmd := JoinPath(ccompilerpath, cc[c].link); linkCmd := quoteIfSpaceExists(JoinPath(ccompilerpath, cc[c].linkerExe));
if optGenDynLib in gGlobalOptions then if optGenDynLib in gGlobalOptions then
buildDll := cc[c].buildDll buildDll := cc[c].buildDll
@ -506,12 +546,14 @@ begin
it := PStrEntry(it.next); it := PStrEntry(it.next);
end; end;
linkCmd := format(linkCmd, [ linkCmd := linkCmd +{&} ' ' +{&} format(cc[c].linkTmpl, [
'builddll', builddll, 'builddll', builddll,
'buildgui', buildgui, 'buildgui', buildgui,
'options', linkOptions, 'options', linkOptions,
'objfiles', objfiles, 'objfiles', objfiles,
'exefile', exefile 'exefile', exefile,
'nimrod', getPrefixDir(),
'lib', libpath
]); ]);
if not (optCompileOnly in gGlobalOptions) then if not (optCompileOnly in gGlobalOptions) then
execExternalProgram(linkCmd); execExternalProgram(linkCmd);

View file

@ -1,175 +0,0 @@
//
//
// The Nimrod Compiler
// (c) Copyright 2008 Andreas Rumpf
//
// See the file "copying.txt", included in this
// distribution, for details about the copyright.
//
unit genhelp;
// This module contains some helper routines used by the different
// code generators.
interface
{$include 'config.inc'}
uses
nsystem,
ast, astalgo, trees, msgs, options, platform;
function hasSideEffect(t: PNode): Boolean;
function ReturnsNewThing(op: PNode): Boolean;
function containsGarbageCollectedRef(typ: PType): Boolean;
// returns true if typ contains a reference, sequence or string (all the things
// that are garbage-collected)
function containsHiddenPointer(typ: PType): Boolean;
// returns true if typ contains a string, table or sequence (all the things
// that need to be copied deeply)
function containsObject(typ: PType): Boolean;
// Returns true if typ contains an object type directly; then it has to
// be initialized in a complex way that sets up the typeid field.
function isGarbageCollected(typ: PType): Boolean;
function pointerOf(typ: PType): PType;
implementation
function pointerOf(typ: PType): PType;
begin
result := newType(unknownLineInfo, tyPtr);
result.baseType := typ;
result.align := platform.PtrSize;
result.size := platform.PtrSize;
end;
function isGarbageCollected(typ: PType): Boolean;
begin
result := typ.Kind in [tyTable, tyRef, tySequence, tyString]
end;
function ReturnsNewThing(op: PNode): Boolean;
var
s: PSym;
begin
result := false;
if op.kind = nkCall then begin
if op.sons[0].kind = nkSym then begin
s := op.sons[0].sym;
result := (sfReturnsNew in s.flags)
end
end
else if op.typ.Kind = tyArrayConstr then
result := true // array constructor returns a newly allocated thing
end;
function containsHiddenPointer(typ: PType): Boolean;
var
t: PType;
i: int;
begin
t := typ;
result := false;
if t = nil then exit;
case t.Kind of
tySequence, tyString, tyTable: result := true;
tyArray, tyArrayConstr, tyOpenArray:
result := containsHiddenPointer(t.baseType);
tySubtype: result := containsHiddenPointer(typ.baseType);
tyRecord, tyObject: begin
if (t.baseType <> nil) and containsHiddenPointer(t.baseType) then
result := true
else
// walk through all fields:
for i := 0 to seqTableLen(t.symList)-1 do
if containsHiddenPointer(seqTableAt(t.symList, i).typ) then begin
result := true; break
end;
end
else result := false
end
end;
function containsGarbageCollectedRef(typ: PType): Boolean;
var
t: PType;
i: int;
begin
t := typ;
result := false;
if t = nil then exit;
case t.Kind of
tySequence, tyRef, tyString, tyTable: result := true;
tyArray: result := containsGarbageCollectedRef(t.baseType);
tyRecord, tyObject: begin
if (t.baseType <> nil) and containsGarbageCollectedRef(t.baseType) then
result := true
else
// walk through all fields:
for i := 0 to seqTableLen(t.symList)-1 do
if containsGarbageCollectedRef(SeqTableAt(t.symList, i).typ) then
begin
result := true; break
end;
end
else result := false
end
end;
function containsObject(typ: PType): Boolean;
var
t: PType;
i: int;
begin
t := typ;
result := false;
if t = nil then exit;
case t.Kind of
tyArray, tyArrayConstr:
result := containsObject(t.baseType);
tyObject: result := true;
tySubtype: result := containsObject(typ.baseType);
tyRecord: begin
// walk through all fields:
for i := 0 to seqTableLen(t.symList)-1 do
if containsObject(SeqTableAt(t.symList, i).typ) then begin
result := true; break
end;
end
else result := false
end
end;
function hasSideEffect(t: PNode): Boolean;
{var
it: PNode; }
begin
result := t.kind in [nkCall, nkArrayConstr, nkRecordConstr, nkSetConstr]
// assume side effect for operations
{
if t.Kind = nkOperation then begin
// this is for function pointers:
if hasSideEffect(t.left) then begin
result := true; exit
end;
it := t.right;
while it <> nil do begin
if hasSideEffect(it) then begin
result := true; exit
end;
it := it.next
end;
result := true
end;
result := false }
end;
end.

View file

@ -60,7 +60,9 @@ type
function nextPowerOfTwo(x: int): int; function nextPowerOfTwo(x: int): int;
begin begin
result := x -{%} 1; result := x -{%} 1;
result := result or (result shr 32); // complicated, to make it a nop if sizeof(int) == 4,
// because shifting more than 31 bits is undefined in C
result := result or (result shr ((sizeof(int)-4)* 32));
result := result or (result shr 16); result := result or (result shr 16);
result := result or (result shr 8); result := result or (result shr 8);
result := result or (result shr 4); result := result or (result shr 4);

View file

@ -137,6 +137,11 @@ procedure initGeneralTokenizer(var g: TGeneralTokenizer;
begin begin
{@ignore} fillChar(g, sizeof(g), 0); {@emit} {@ignore} fillChar(g, sizeof(g), 0); {@emit}
g.buf := PChar(buf); g.buf := PChar(buf);
g.kind := low(TTokenClass);
g.start := 0;
g.len := 0;
g.pos := 0;
g.state := low(TTokenClass);
end; end;
procedure deinitGeneralTokenizer(var g: TGeneralTokenizer); procedure deinitGeneralTokenizer(var g: TGeneralTokenizer);

View file

@ -42,8 +42,9 @@ var
j: int; j: int;
etyp: PType; // enumeration type etyp: PType; // enumeration type
begin begin
copy := copySym(s, s.owner); //copy := copySym(s, true);
copy.ast := s.ast; // BUGFIX //copy.ast := s.ast;
copy := s; // do not copy symbols when importing!
// check if we have already a symbol of the same name: // check if we have already a symbol of the same name:
check := StrTableGet(c.tab.stack[importTablePos], s.name); check := StrTableGet(c.tab.stack[importTablePos], s.name);
if check <> nil then begin if check <> nil then begin
@ -55,17 +56,17 @@ begin
end; end;
StrTableAdd(c.tab.stack[importTablePos], copy); StrTableAdd(c.tab.stack[importTablePos], copy);
if s.kind = skType then begin if s.kind = skType then begin
// types are special: we need to copy types but need to
// consider private fields
etyp := s.typ; etyp := s.typ;
if etyp.kind = tyEnum then begin if etyp.kind = tyEnum then begin
for j := 0 to sonsLen(etyp.n)-1 do begin for j := 0 to sonsLen(etyp.n)-1 do begin
e := etyp.n.sons[j].sym; e := etyp.n.sons[j].sym;
assert(e.Kind = skEnumField); if (e.Kind = skEnumField) then rawImportSymbol(c, e)
rawImportSymbol(c, e) else InternalError(s.info, 'rawImportSymbol');
end end
end end
end; end
else if s.kind = skConverter then
addConverter(c, s);
end; end;
procedure importSymbol(c: PContext; ident: PNode; fromMod: PSym); procedure importSymbol(c: PContext; ident: PNode; fromMod: PSym);
@ -73,18 +74,20 @@ var
s, e: PSym; s, e: PSym;
it: TIdentIter; it: TIdentIter;
begin begin
assert(ident.kind = nkIdent); if (ident.kind <> nkIdent) then InternalError(ident.info, 'importSymbol');
s := StrTableGet(fromMod.tab, ident.ident); s := StrTableGet(fromMod.tab, ident.ident);
if s = nil then if s = nil then
liMessage(ident.info, errUndeclaredIdentifier, ident.ident.s); liMessage(ident.info, errUndeclaredIdentifier, ident.ident.s);
assert(s.Kind in ExportableSymKinds); if not (s.Kind in ExportableSymKinds) then
InternalError(ident.info, 'importSymbol: 2');
// for an enumeration we have to add all identifiers // for an enumeration we have to add all identifiers
case s.Kind of case s.Kind of
skProc, skIterator, skMacro, skTemplate: begin skProc, skIterator, skMacro, skTemplate, skConverter: begin
// for a overloadable syms add all overloaded routines // for a overloadable syms add all overloaded routines
e := InitIdentIter(it, fromMod.tab, s.name); e := InitIdentIter(it, fromMod.tab, s.name);
while e <> nil do begin while e <> nil do begin
assert(e.name.id = s.Name.id); if (e.name.id <> s.Name.id) then
InternalError(ident.info, 'importSymbol: 3');
rawImportSymbol(c, e); rawImportSymbol(c, e);
e := NextIdentIter(it, fromMod.tab); e := NextIdentIter(it, fromMod.tab);
end end
@ -101,8 +104,11 @@ begin
s := InitTabIter(i, fromMod.tab); s := InitTabIter(i, fromMod.tab);
while s <> nil do begin while s <> nil do begin
if s.kind <> skModule then begin if s.kind <> skModule then begin
assert(s.Kind in ExportableSymKinds); if s.kind <> skEnumField then begin
if not (s.Kind in ExportableSymKinds) then
InternalError(s.info, 'importAllSymbols');
rawImportSymbol(c, s); // this is correct! rawImportSymbol(c, s); // this is correct!
end
end; end;
s := NextIter(i, fromMod.tab) s := NextIter(i, fromMod.tab)
end end
@ -129,6 +135,7 @@ var
i: int; i: int;
begin begin
result := n; result := n;
checkMinSonsLen(n, 2);
m := c.ImportModule(getModuleFile(n.sons[0]), c.b); m := c.ImportModule(getModuleFile(n.sons[0]), c.b);
n.sons[0] := newSymNode(m); n.sons[0] := newSymNode(m);
addDecl(c, m); // add symbol to symbol table of module addDecl(c, m); // add symbol to symbol table of module
@ -140,7 +147,7 @@ var
i: int; i: int;
x: PNode; x: PNode;
begin begin
result := newNode(nkStmtList); result := newNodeI(nkStmtList, n.info);
for i := 0 to sonsLen(n)-1 do begin for i := 0 to sonsLen(n)-1 do begin
x := c.includeFile(getModuleFile(n.sons[i])); x := c.includeFile(getModuleFile(n.sons[i]));
x := semStmt(c, x); x := semStmt(c, x);

View file

@ -21,11 +21,12 @@ type
newOwner: PSym; newOwner: PSym;
instantiator: TLineInfo; instantiator: TLineInfo;
end; end;
PInstClosure = ^TInstantiateClosure; PInstantiateClosure = ^TInstantiateClosure;
PInstClosure = PInstantiateClosure;
function instantiateTree(var c: TInstantiateClosure; t: PNode): PNode; forward; function instantiateTree(c: PInstantiateClosure; t: PNode): PNode; forward;
function instantiateSym(c: PInstantiateClosure; sym: PSym): PSym; forward;
function instantiateSym(var c: TInstantiateClosure; sym: PSym): PSym; forward; function instantiateType(c: PInstantiateClosure; typ: PType): PType; forward;
function containsGenericTypeIter(t: PType; closure: PObject): bool; function containsGenericTypeIter(t: PType; closure: PObject): bool;
begin begin
@ -37,35 +38,58 @@ begin
result := iterOverType(t, containsGenericTypeIter, nil); result := iterOverType(t, containsGenericTypeIter, nil);
end; end;
function instTypeNode(c: PInstantiateClosure; n: PNode): PNode;
function instantiateTypeMutator(typ: PType; c: PObject): PType; var
i: int;
begin begin
result := PType(idTableGet(PInstClosure(c).mapping, typ)); 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]));
end
end
end
end;
function instantiateType(c: PInstantiateClosure; typ: PType): PType;
var
i: int;
begin
result := PType(idTableGet(c.mapping, typ));
if result <> nil then exit; if result <> nil then exit;
if containsGenericType(typ) then begin if containsGenericType(typ) then begin
result := copyType(typ, PInstClosure(c).newOwner); result := copyType(typ, c.newOwner);
idTablePut(PInstClosure(c).mapping, typ, result) idTablePut(c.mapping, 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);
end end
else else
result := typ; result := typ;
if result.Kind in GenericTypes then begin if result.Kind in GenericTypes then begin
liMessage(PInstClosure(c).instantiator, errCannotInstantiateX, liMessage(c.instantiator, errCannotInstantiateX,
TypeToString(typ, preferName)); TypeToString(typ, preferName));
end
else if result.kind = tyVar then begin
if result.sons[0].kind = tyVar then
liMessage(c.instantiator, errVarVarTypeNotAllowed);
end; end;
end; end;
function instantiateType(var c: TInstantiateClosure; typ: PType): PType; function instantiateSym(c: PInstantiateClosure; sym: PSym): PSym;
begin
result := mutateType(typ, instantiateTypeMutator, {@cast}PObject(addr(c)));
end;
function instantiateSym(var c: TInstantiateClosure; sym: PSym): PSym;
begin begin
if sym = nil then begin result := nil; exit end; // BUGFIX if sym = nil then begin result := nil; exit end; // BUGFIX
result := PSym(idTableGet(c.mapping, sym)); result := PSym(idTableGet(c.mapping, sym));
if (result = nil) then begin if (result = nil) then begin
if (sym.owner.id = c.fn.id) or (sym.id = c.fn.id) then begin if (sym.owner.id = c.fn.id) or (sym.id = c.fn.id) then begin
result := copySym(sym, nil); result := copySym(sym);
if sym.id = c.fn.id then c.newOwner := result; if sym.id = c.fn.id then c.newOwner := result;
include(result.flags, sfIsCopy); include(result.flags, sfIsCopy);
idTablePut(c.mapping, sym, result); // BUGFIX idTablePut(c.mapping, sym, result); // BUGFIX
@ -83,7 +107,7 @@ begin
end end
end; end;
function instantiateTree(var c: TInstantiateClosure; t: PNode): PNode; function instantiateTree(c: PInstantiateClosure; t: PNode): PNode;
var var
len, i: int; len, i: int;
begin begin
@ -124,7 +148,8 @@ begin
q := n.sons[i].sym; q := n.sons[i].sym;
s := newSym(skType, q.name, getCurrOwner(c)); s := newSym(skType, q.name, getCurrOwner(c));
t := PType(IdTableGet(pt, q.typ)); t := PType(IdTableGet(pt, q.typ));
if t = nil then liMessage(n.sons[i].info, errCannotInstantiateX, s.name.s); if t = nil then
liMessage(n.sons[i].info, errCannotInstantiateX, s.name.s);
assert(t.kind <> tyGenericParam); assert(t.kind <> tyGenericParam);
s.typ := t; s.typ := t;
addDecl(c, s); addDecl(c, s);
@ -138,7 +163,8 @@ var
begin begin
result := nil; result := nil;
for i := 0 to sonsLen(c.generics)-1 do begin for i := 0 to sonsLen(c.generics)-1 do begin
assert(c.generics.sons[i].kind = nkExprEqExpr); if c.generics.sons[i].kind <> nkExprEqExpr then
InternalError(genericSym.info, 'GenericCacheGet');
a := c.generics.sons[i].sons[0].sym; a := c.generics.sons[i].sons[0].sym;
if genericSym.id = a.id then begin if genericSym.id = a.id then begin
b := c.generics.sons[i].sons[1].sym; b := c.generics.sons[i].sons[1].sym;
@ -173,8 +199,8 @@ var
n: PNode; n: PNode;
begin begin
oldP := c.p; // restore later oldP := c.p; // restore later
result := copySym(fn, getCurrOwner(c)); result := copySym(fn);
result.id := getId(); result.owner := getCurrOwner(c);
n := copyTree(fn.ast); n := copyTree(fn.ast);
result.ast := n; result.ast := n;
pushOwner(c, result); pushOwner(c, result);
@ -202,7 +228,7 @@ begin
addDecl(c, result); addDecl(c, result);
if n.sons[codePos] <> nil then begin if n.sons[codePos] <> nil then begin
c.p := newProcCon(result); c.p := newProcCon(result);
if result.kind = skProc then begin if result.kind in [skProc, skConverter] then begin
addResult(c, result.typ.sons[0], n.info); addResult(c, result.typ.sons[0], n.info);
addResultNode(c, n); addResultNode(c, n);
end; end;
@ -221,8 +247,12 @@ end;
function generateTypeInstance(p: PContext; const pt: TIdTable; function generateTypeInstance(p: PContext; const pt: TIdTable;
const instantiator: TLineInfo; t: PType): PType; const instantiator: TLineInfo; t: PType): PType;
var var
c: TInstantiateClosure; c: PInstantiateClosure;
begin begin
new(c);
{@ignore}
fillChar(c^, sizeof(c^), 0);
{@emit}
c.mapping := pt; // making a copy is not necessary c.mapping := pt; // making a copy is not necessary
c.fn := nil; c.fn := nil;
c.instantiator := instantiator; c.instantiator := instantiator;

View file

@ -227,7 +227,7 @@ begin
L.linenumber := 1; // lines start at 1 L.linenumber := 1; // lines start at 1
L.fileOpened := false; L.fileOpened := false;
if L.bufLen > 0 then begin if L.bufLen > 0 then begin
copyMem(L.buf, addr(buffer[strStart]), L.bufLen); copyMem(L.buf, {@cast}pointer(buffer), L.bufLen);
L.buf[L.bufLen-1] := EndOfFile; L.buf[L.bufLen-1] := EndOfFile;
end end
else else

View file

@ -12,8 +12,7 @@
function getSymRepr(s: PSym): string; function getSymRepr(s: PSym): string;
begin begin
case s.kind of case s.kind of
skProc, skConverter, skIterator: skProc, skConverter, skIterator: result := getProcHeader(s);
result := getProcHeader(s);
else result := s.name.s else result := s.name.s
end end
end; end;
@ -24,7 +23,7 @@ var
s: PSym; s: PSym;
begin begin
// check if all symbols have been used and defined: // check if all symbols have been used and defined:
assert(tab.tos <= length(tab.stack)); if (tab.tos > length(tab.stack)) then InternalError('CloseScope');
s := InitTabIter(it, tab.stack[tab.tos-1]); s := InitTabIter(it, tab.stack[tab.tos-1]);
while s <> nil do begin while s <> nil do begin
if sfForward in s.flags then if sfForward in s.flags then
@ -59,7 +58,8 @@ procedure addOverloadableSymAt(c: PContext; fn: PSym; at: Natural);
var var
check: PSym; check: PSym;
begin begin
assert(fn.kind in OverloadableSyms); if not (fn.kind in OverloadableSyms) then
InternalError(fn.info, 'addOverloadableSymAt');
check := StrTableGet(c.tab.stack[at], fn.name); check := StrTableGet(c.tab.stack[at], fn.name);
if (check <> nil) and (check.Kind <> fn.kind) then if (check <> nil) and (check.Kind <> fn.kind) then
liMessage(fn.info, errAttemptToRedefine, fn.Name.s); liMessage(fn.info, errAttemptToRedefine, fn.Name.s);
@ -70,7 +70,7 @@ procedure AddInterfaceDeclAux(c: PContext; sym: PSym);
begin begin
if (sfInInterface in sym.flags) then begin if (sfInInterface in sym.flags) then begin
// add to interface: // add to interface:
assert(c.module <> nil); if c.module = nil then InternalError(sym.info, 'AddInterfaceDeclAux');
StrTableAdd(c.module.tab, sym); StrTableAdd(c.module.tab, sym);
end; end;
if getCurrOwner(c).kind = skModule then if getCurrOwner(c).kind = skModule then
@ -92,12 +92,21 @@ end;
function lookUp(c: PContext; n: PNode): PSym; function lookUp(c: PContext; n: PNode): PSym;
// Looks up a symbol. Generates an error in case of nil. // Looks up a symbol. Generates an error in case of nil.
begin begin
if n.kind = nkAccQuoted then result := lookup(c, n.sons[0]) case n.kind of
else begin nkAccQuoted: result := lookup(c, n.sons[0]);
assert(n.kind = nkIdent); nkSym: begin
result := SymtabGet(c.Tab, n.ident); result := SymtabGet(c.Tab, n.sym.name);
if result = nil then liMessage(n.info, errUndeclaredIdentifier, n.ident.s); if result = nil then
liMessage(n.info, errUndeclaredIdentifier, n.sym.name.s);
include(result.flags, sfUsed); include(result.flags, sfUsed);
end;
nkIdent: begin
result := SymtabGet(c.Tab, n.ident);
if result = nil then
liMessage(n.info, errUndeclaredIdentifier, n.ident.s);
include(result.flags, sfUsed);
end
else InternalError(n.info, 'lookUp');
end end
end; end;
@ -115,6 +124,14 @@ begin
and StrTableContains(c.AmbigiousSymbols, result) then and StrTableContains(c.AmbigiousSymbols, result) then
liMessage(n.info, errUseQualifier, n.ident.s) liMessage(n.info, errUseQualifier, n.ident.s)
end; end;
nkSym: begin
result := SymtabGet(c.Tab, n.sym.name);
if result = nil then
liMessage(n.info, errUndeclaredIdentifier, n.sym.name.s)
else if ambigiousCheck
and StrTableContains(c.AmbigiousSymbols, result) then
liMessage(n.info, errUseQualifier, n.sym.name.s)
end;
nkDotExpr, nkQualified: begin nkDotExpr, nkQualified: begin
result := nil; result := nil;
m := qualifiedLookUp(c, n.sons[0], false); m := qualifiedLookUp(c, n.sons[0], false);
@ -165,6 +182,15 @@ begin
result := InitIdentIter(o.it, c.tab.stack[o.stackPtr], n.ident); result := InitIdentIter(o.it, c.tab.stack[o.stackPtr], n.ident);
end; end;
end; end;
nkSym: begin
o.stackPtr := c.tab.tos;
o.mode := oimNoQualifier;
while (result = nil) do begin
dec(o.stackPtr);
if o.stackPtr < 0 then break;
result := InitIdentIter(o.it, c.tab.stack[o.stackPtr], n.sym.name);
end;
end;
nkDotExpr, nkQualified: begin nkDotExpr, nkQualified: begin
o.mode := oimOtherModule; o.mode := oimOtherModule;
o.m := qualifiedLookUp(c, n.sons[0], false); o.m := qualifiedLookUp(c, n.sons[0], false);
@ -199,7 +225,8 @@ begin
while (result = nil) do begin while (result = nil) do begin
dec(o.stackPtr); dec(o.stackPtr);
if o.stackPtr < 0 then break; if o.stackPtr < 0 then break;
result := InitIdentIter(o.it, c.tab.stack[o.stackPtr], n.ident); result := InitIdentIter(o.it, c.tab.stack[o.stackPtr], o.it.name);
// BUGFIX: o.it.name <-> n.ident
end end
end end
else result := nil; else result := nil;

View file

@ -17,7 +17,8 @@ interface
uses uses
nsystem, strutils, ast, astalgo, scanner, pnimsyn, rnimsyn, options, msgs, nsystem, strutils, ast, astalgo, scanner, pnimsyn, rnimsyn, options, msgs,
nos, lists, condsyms, paslex, pasparse, rodgen, ropes, trees, nos, lists, condsyms, paslex, pasparse, rodgen, ropes, trees,
wordrecg, sem, idents, magicsys, backends, docgen, extccomp, cgen; wordrecg, sem, idents, magicsys, backends, docgen, extccomp, cgen,
platform, ecmasgen;
procedure MainCommand(const cmd, filename: string); procedure MainCommand(const cmd, filename: string);
@ -109,7 +110,9 @@ begin
// compile the module // compile the module
// XXX: here caching could be implemented // XXX: here caching could be implemented
result := compileModule(filename, backend, false, false); result := compileModule(filename, backend, false, false);
end; end
else if sfSystemModule in result.flags then
liMessage(result.info, errAttemptToRedefine, result.Name.s);
end; end;
function CompileModule(const filename: string; backend: PBackend; function CompileModule(const filename: string; backend: PBackend;
@ -131,8 +134,8 @@ begin
openScope(c.tab); // scope for imported symbols openScope(c.tab); // scope for imported symbols
SymTabAdd(c.tab, result); SymTabAdd(c.tab, result);
if not isSystemFile then begin if not isSystemFile then begin
importAllSymbols(c, magicsys.SystemModule);
SymTabAdd(c.tab, magicsys.SystemModule); // import the "System" identifier SymTabAdd(c.tab, magicsys.SystemModule); // import the "System" identifier
importAllSymbols(c, magicsys.SystemModule);
SymTabAdd(c.tab, newIsMainModuleSym(result, isMainFile)); SymTabAdd(c.tab, newIsMainModuleSym(result, isMainFile));
end end
else begin else begin
@ -142,7 +145,6 @@ begin
end; end;
{@discard} semModule(c, ast); {@discard} semModule(c, ast);
rawCloseScope(c.tab); // imported symbols; don't check for unused ones! rawCloseScope(c.tab); // imported symbols; don't check for unused ones!
// XXX: compile the generated generic procs!
msgCompiled(result.name.s); msgCompiled(result.name.s);
end; end;
@ -161,7 +163,7 @@ var
procedure addDependencyAux(importing, imported: PSym); procedure addDependencyAux(importing, imported: PSym);
begin begin
appRopeFormat(gDotGraph, '$1 -> $2;$n', [toRope(importing.name.s), appf(gDotGraph, '$1 -> $2;$n', [toRope(importing.name.s),
toRope(imported.name.s)]); toRope(imported.name.s)]);
// s1 -> s2_4 [label="[0-9]"]; // s1 -> s2_4 [label="[0-9]"];
end; end;
@ -193,7 +195,7 @@ end;
procedure generateDot(const project: string); procedure generateDot(const project: string);
begin begin
writeRope( writeRope(
ropeFormat('digraph $1 {$n$2}$n', [ ropef('digraph $1 {$n$2}$n', [
toRope(changeFileExt(extractFileName(project), '')), gDotGraph]), toRope(changeFileExt(extractFileName(project), '')), gDotGraph]),
changeFileExt(project, 'dot') ); changeFileExt(project, 'dot') );
end; end;
@ -257,6 +259,14 @@ begin
extccomp.CallCCompiler(changeFileExt(filename, '')); extccomp.CallCCompiler(changeFileExt(filename, ''));
end; end;
procedure CommandCompileToEcmaScript(const filename: string);
begin
include(gGlobalOptions, optSafeCode);
setTarget(osEcmaScript, cpuEcmaScript);
initDefines();
compileProject(filename, EcmasBackend(nil, nil, filename));
end;
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
procedure exSymbols(n: PNode); procedure exSymbols(n: PNode);
@ -279,7 +289,7 @@ begin
for i := 0 to sonsLen(n)-1 do begin for i := 0 to sonsLen(n)-1 do begin
exSymbol(n.sons[i].sons[0]); exSymbol(n.sons[i].sons[0]);
if (n.sons[i].sons[2] <> nil) and if (n.sons[i].sons[2] <> nil) and
(n.sons[i].sons[2].kind in [nkRecordTy, nkObjectTy]) then (n.sons[i].sons[2].kind = nkObjectTy) then
fixRecordDef(n.sons[i].sons[2]) fixRecordDef(n.sons[i].sons[2])
end end
end; end;
@ -406,6 +416,11 @@ begin
wantFile(filename); wantFile(filename);
CommandCompileToC(filename); CommandCompileToC(filename);
end; end;
wCompileToEcmaScript: begin
gCmd := cmdCompileToEcmaScript;
wantFile(filename);
CommandCompileToEcmaScript(filename);
end;
wPretty: begin wPretty: begin
// compile means compileToC currently // compile means compileToC currently
gCmd := cmdPretty; gCmd := cmdPretty;

View file

@ -74,10 +74,6 @@ type
errTokenExpected, errTokenExpected,
errStringAfterIncludeExpected, errStringAfterIncludeExpected,
errRecursiveInclude, errRecursiveInclude,
errAtIfExpected,
errAtIfExpectedBeforeElse,
errAtIfExpectedBeforeElif,
errAtEndExpected,
errOnOrOffExpected, errOnOrOffExpected,
errNoneSpeedOrSizeExpected, errNoneSpeedOrSizeExpected,
errInvalidPragma, errInvalidPragma,
@ -186,7 +182,7 @@ type
errSizeTooBig, errSizeTooBig,
errSetTooBig, errSetTooBig,
errBaseTypeMustBeOrdinal, errBaseTypeMustBeOrdinal,
errInheritanceOnlyWithObjects, errInheritanceOnlyWithNonFinalObjects,
errInheritanceOnlyWithEnums, errInheritanceOnlyWithEnums,
errIllegalRecursionInTypeX, errIllegalRecursionInTypeX,
errCannotInstantiateX, errCannotInstantiateX,
@ -267,6 +263,20 @@ type
errWhitespaceExpected, errWhitespaceExpected,
errXisNoValidIndexFile, errXisNoValidIndexFile,
errCannotRenderX, errCannotRenderX,
errVarVarTypeNotAllowed,
errIsExpectsTwoArguments,
errIsExpectsObjectTypes,
errXcanNeverBeOfThisSubtype,
errTooManyIterations,
errCannotInterpretNodeX,
errFieldXNotFound,
errInvalidConversionFromTypeX,
errAssertionFailed,
errCannotGenerateCodeForX,
errXNeedsReturnType,
errXRequiresOneArgument,
errUnhandledExceptionX,
errCyclicTree,
errUser, errUser,
warnCannotOpenFile, warnCannotOpenFile,
warnOctalEscape, warnOctalEscape,
@ -291,6 +301,8 @@ type
hintMo2FileInvalid, hintMo2FileInvalid,
hintModuleHasChanged, hintModuleHasChanged,
hintCannotOpenMo2File, hintCannotOpenMo2File,
hintQuitCalled,
hintProcessing,
hintUser); hintUser);
const const
@ -310,7 +322,7 @@ const
'invalid token: $1', 'invalid token: $1',
'line too long', 'line too long',
'$1 is not a valid number', '$1 is not a valid number',
'$1 is too large or too small', 'number $1 out of valid range',
'\n not allowed in character literal', '\n not allowed in character literal',
'closing '']'' expected, but end of file reached', 'closing '']'' expected, but end of file reached',
'missing final ''', 'missing final ''',
@ -319,10 +331,6 @@ const
'''$1'' expected', '''$1'' expected',
'string after ''include'' expected', 'string after ''include'' expected',
'recursive include file: ''$1''', 'recursive include file: ''$1''',
'''@if'' expected',
'''@if'' expected before ''@else''',
'''@if'' expected before ''@elif''',
'''@end'' expected',
'''on'' or ''off'' expected', '''on'' or ''off'' expected',
'''none'', ''speed'' or ''size'' expected', '''none'', ''speed'' or ''size'' expected',
'invalid pragma', 'invalid pragma',
@ -431,12 +439,12 @@ const
'computing the type''s size produced an overflow', 'computing the type''s size produced an overflow',
'set is too large', 'set is too large',
'base type of a set must be an ordinal', 'base type of a set must be an ordinal',
'inheritance only works with an object', 'inheritance only works non-final objects',
'inheritance only works with an enum', 'inheritance only works with an enum',
'illegal recursion in type ''$1''', 'illegal recursion in type ''$1''',
'cannot instantiate: ''$1''', 'cannot instantiate: ''$1''',
'expression has no address', 'expression has no address',
'to an out parameter a variable needs to be passed', 'for a ''var'' type a variable needs to be passed',
'type mismatch', 'type mismatch',
'type mismatch: got (', 'type mismatch: got (',
'but expected one of: ', 'but expected one of: ',
@ -512,6 +520,20 @@ const
'whitespace expected, got ''$1''', 'whitespace expected, got ''$1''',
'''$1'' is no valid index file', '''$1'' is no valid index file',
'cannot render reStructuredText element ''$1''', 'cannot render reStructuredText element ''$1''',
'type ''var var'' is not allowed',
'''is'' expects two arguments',
'''is'' expects object types',
'''$1'' can never be of this subtype',
'interpretation requires too many iterations',
'cannot interpret node kind ''$1''',
'field ''$1'' cannot be found',
'invalid conversion from type ''$1''',
'assertion failed',
'cannot generate code for ''$1''',
'converter needs return type',
'converter requires one parameter',
'unhandled exception: $1',
'macro returned a cyclic abstract syntax tree',
'$1', '$1',
'cannot open ''$1'' [CannotOpenFile]', 'cannot open ''$1'' [CannotOpenFile]',
'octal escape sequences do not exist; leading zero is ignored [OctalEscape]', 'octal escape sequences do not exist; leading zero is ignored [OctalEscape]',
@ -536,6 +558,8 @@ const
'mo2 file ''$1'' is invalid [Mo2FileInvalid]', 'mo2 file ''$1'' is invalid [Mo2FileInvalid]',
'module ''$1'' has been changed [ModuleHasChanged]', 'module ''$1'' has been changed [ModuleHasChanged]',
'mo2 file ''$1'' does not exist [CannotOpenMo2File]', 'mo2 file ''$1'' does not exist [CannotOpenMo2File]',
'quit() called [QuitCalled]',
'processing [Processing]',
'$1 [User]' '$1 [User]'
); );
const const
@ -556,7 +580,7 @@ const
'User' 'User'
); );
const const
HintsToStr: array [0..9] of string = ( HintsToStr: array [0..11] of string = (
'Success', 'Success',
'LineTooLong', 'LineTooLong',
'XDeclaredButNotUsed', 'XDeclaredButNotUsed',
@ -566,6 +590,8 @@ const
'Mo2FileInvalid', 'Mo2FileInvalid',
'ModuleHasChanged', 'ModuleHasChanged',
'CannotOpenMo2File', 'CannotOpenMo2File',
'QuitCalled',
'Processing',
'User' 'User'
); );
//[[[end]]] //[[[end]]]
@ -593,12 +619,7 @@ type
fileIndex: int32; fileIndex: int32;
end; end;
const function UnknownLineInfo(): TLineInfo;
UnknownLineInfo: TLineInfo = (
line: -1;
col: -1;
fileIndex: -1;
);
var var
gNotes: TNoteKinds = [low(TNoteKind)..high(TNoteKind)]; gNotes: TNoteKinds = [low(TNoteKind)..high(TNoteKind)];
@ -649,6 +670,13 @@ procedure popInfoContext;
implementation implementation
function UnknownLineInfo(): TLineInfo;
begin
result.line := -1;
result.col := -1;
result.fileIndex := -1;
end;
{@ignore} {@ignore}
var var
filenames: array of string; filenames: array of string;
@ -782,12 +810,13 @@ end;
procedure handleError(const msg: TMsgKind); procedure handleError(const msg: TMsgKind);
begin begin
if (msg >= fatalMin) and (msg <= fatalMax) then begin if (msg >= fatalMin) and (msg <= fatalMax) then begin
assert(false); halt(1) if optVerbose in gGlobalOptions then assert(false);
halt(1)
end; end;
if (msg >= errMin) and (msg <= errMax) then begin if (msg >= errMin) and (msg <= errMax) then begin
inc(gErrorCounter); inc(gErrorCounter);
if gErrorCounter >= gErrorMax then begin if gErrorCounter >= gErrorMax then begin
assert(false); // stack trace for debugging if optVerbose in gGlobalOptions then assert(false);
halt(1) // one error stops the compiler halt(1) // one error stops the compiler
end end
end end
@ -797,7 +826,7 @@ procedure writeContext;
var var
i: int; i: int;
begin begin
for i := length(msgContext)-1 downto 0 do begin for i := 0 to length(msgContext)-1 do begin
MessageOut(Format(posErrorFormat, [toFilename(msgContext[i]), MessageOut(Format(posErrorFormat, [toFilename(msgContext[i]),
coordToStr(msgContext[i].line), coordToStr(msgContext[i].line),
coordToStr(msgContext[i].col), coordToStr(msgContext[i].col),

View file

@ -101,7 +101,7 @@ var
procedure doEnd(var L: TLexer; tok: PToken); procedure doEnd(var L: TLexer; tok: PToken);
begin begin
if high(condStack) < 0 then lexMessage(L, errAtIfExpected); if high(condStack) < 0 then lexMessage(L, errTokenExpected, '@if');
ppGetTok(L, tok); // skip 'end' ppGetTok(L, tok); // skip 'end'
setLength(condStack, high(condStack)) setLength(condStack, high(condStack))
end; end;
@ -114,7 +114,7 @@ procedure jumpToDirective(var L: TLexer; tok: PToken; dest: TJumpDest); forward;
procedure doElse(var L: TLexer; tok: PToken); procedure doElse(var L: TLexer; tok: PToken);
begin begin
if high(condStack) < 0 then if high(condStack) < 0 then
lexMessage(L, errAtIfExpectedBeforeElse); lexMessage(L, errTokenExpected, '@if');
ppGetTok(L, tok); ppGetTok(L, tok);
if tok.tokType = tkColon then ppGetTok(L, tok); if tok.tokType = tkColon then ppGetTok(L, tok);
if condStack[high(condStack)] then if condStack[high(condStack)] then
@ -126,7 +126,7 @@ var
res: bool; res: bool;
begin begin
if high(condStack) < 0 then if high(condStack) < 0 then
lexMessage(L, errAtIfExpectedBeforeElif); lexMessage(L, errTokenExpected, '@if');
res := EvalppIf(L, tok); res := EvalppIf(L, tok);
if condStack[high(condStack)] or not res then if condStack[high(condStack)] or not res then
jumpToDirective(L, tok, jdElseEndif) jumpToDirective(L, tok, jdElseEndif)
@ -168,7 +168,7 @@ begin
ppGetTok(L, tok) ppGetTok(L, tok)
end end
else if tok.tokType = tkEof then else if tok.tokType = tkEof then
lexMessage(L, errAtEndExpected) lexMessage(L, errTokenExpected, '@end')
else else
ppGetTok(L, tok) ppGetTok(L, tok)
end end
@ -303,7 +303,7 @@ begin
while tok.tokType <> tkEof do while tok.tokType <> tkEof do
parseAssignment(L, tok); parseAssignment(L, tok);
if length(condStack) > 0 then if length(condStack) > 0 then
lexMessage(L, errAtEndExpected); lexMessage(L, errTokenExpected, '@end');
closeLexer(L) closeLexer(L)
end end
end; end;

View file

@ -6,7 +6,7 @@
// See the file "copying.txt", included in this // See the file "copying.txt", included in this
// distribution, for details about the copyright. // distribution, for details about the copyright.
// //
program nim; program nimrod;
{$include 'config.inc'} {$include 'config.inc'}
{@ignore} {@ignore}
@ -18,39 +18,37 @@ program nim;
uses uses
nsystem, nsystem,
charsets, sysutils, commands, scanner, condsyms, options, msgs, nversion, charsets, sysutils, commands, scanner, condsyms, options, msgs, nversion,
nimconf, ropes, extccomp, strutils, nos, platform, main; nimconf, ropes, extccomp, strutils, nos, platform, main, parseopt;
var var
arguments: string = ''; // the arguments to be passed to the program that arguments: string = ''; // the arguments to be passed to the program that
// should be run // should be run
cmdLineInfo: TLineInfo;
function ProcessCmdLine(pass: TCmdLinePass): string; procedure ProcessCmdLine(pass: TCmdLinePass; var command, filename: string);
var var
i, paramCounter: int; p: TOptParser;
param: string;
begin begin
i := 1; p := parseopt.init();
result := ''; while true do begin
paramCounter := paramCount(); parseopt.next(p);
while i <= paramCounter do begin case p.kind of
param := ParamStr(i); cmdEnd: break;
if param[strStart] = '-' then begin cmdLongOption, cmdShortOption:
commands.ProcessCommand(param, pass); ProcessSwitch(p.key, p.val, pass, cmdLineInfo);
cmdArgument: begin
if command = '' then command := p.key
else if filename = '' then begin
filename := unixToNativePath(p.key);
// BUGFIX for portable build scripts
break
end
end
end end
else if i > 1 then begin
result := unixToNativePath(param); // BUGFIX for portable build scripts
options.compilerArgs := i;
break // do not process the arguments
end; end;
Inc(i)
end;
inc(i); // skip program file
// collect the arguments: // collect the arguments:
if pass = passCmd2 then begin if pass = passCmd2 then begin
while i <= paramCounter do begin arguments := getRestOfCommandLine(p);
arguments := arguments + ' ' +{&} paramStr(i);
inc(i)
end;
if not (optRun in gGlobalOptions) and (arguments <> '') then if not (optRun in gGlobalOptions) and (arguments <> '') then
rawMessage(errArgsNeedRunOption); rawMessage(errArgsNeedRunOption);
end end
@ -58,42 +56,36 @@ end;
procedure HandleCmdLine; procedure HandleCmdLine;
var var
inp: string; command, filename: string;
begin begin
if paramCount() = 0 then if paramCount() = 0 then
writeCommandLineUsage() writeCommandLineUsage()
else begin else begin
// Process command line arguments: // Process command line arguments:
inp := ProcessCmdLine(passCmd1); command := '';
if inp <> '' then begin filename := '';
ProcessCmdLine(passCmd1, command, filename);
if filename <> '' then begin
if gCmd = cmdInterpret then DefineSymbol('interpreting'); if gCmd = cmdInterpret then DefineSymbol('interpreting');
nimconf.LoadConfig(inp); // load the right config file nimconf.LoadConfig(filename); // load the right config file
// now process command line arguments again, because some options in the // now process command line arguments again, because some options in the
// command line can overwite the config file's settings // command line can overwite the config file's settings
extccomp.initVars(); extccomp.initVars();
inp := ProcessCmdLine(passCmd2); command := '';
filename := '';
ProcessCmdLine(passCmd2, command, filename);
end; end;
MainCommand(paramStr(1), inp); MainCommand(command, filename);
if (gCmd <> cmdInterpret) and (msgs.gErrorCounter = 0) then if (gCmd <> cmdInterpret) and (msgs.gErrorCounter = 0) then
rawMessage(hintSuccess); rawMessage(hintSuccess);
if optRun in gGlobalOptions then if optRun in gGlobalOptions then
execExternalProgram(changeFileExt(inp, '') +{&} arguments) execExternalProgram(changeFileExt(filename, '') +{&} ' ' +{&} arguments)
end end
end; end;
{@ignore}
var
Saved8087CW: Word;
{@emit}
begin begin
{@ignore} cmdLineInfo := newLineInfo('command line', -1, -1);
Saved8087CW := Default8087CW;
Set8087CW($133f); // Disable all fpu exceptions
{@emit}
condsyms.InitDefines(); condsyms.InitDefines();
HandleCmdLine(); HandleCmdLine();
{@ignore}
Set8087CW(Saved8087CW);
{@emit}
halt(options.gExitcode); halt(options.gExitcode);
end. end.

View file

@ -49,7 +49,7 @@ function inSet(s: PNode; const elem: PNode): Boolean;
var var
i: int; i: int;
begin begin
assert(s.kind in [nkSetConstr, nkConstSetConstr]); if s.kind <> nkCurly then InternalError(s.info, 'inSet');
for i := 0 to sonsLen(s)-1 do for i := 0 to sonsLen(s)-1 do
if s.sons[i].kind = nkRange then begin if s.sons[i].kind = nkRange then begin
if leValue(s.sons[i].sons[0], elem) if leValue(s.sons[i].sons[0], elem)
@ -95,7 +95,7 @@ function SomeInSet(s: PNode; const a, b: PNode): Boolean;
var var
i: int; i: int;
begin begin
assert(s.kind in [nkSetConstr, nkConstSetConstr]); if s.kind <> nkCurly then InternalError(s.info, 'SomeInSet');
for i := 0 to sonsLen(s)-1 do for i := 0 to sonsLen(s)-1 do
if s.sons[i].kind = nkRange then begin if s.sons[i].kind = nkRange then begin
if leValue(s.sons[i].sons[0], b) if leValue(s.sons[i].sons[0], b)
@ -142,7 +142,7 @@ var
begin begin
elemType := settype.sons[0]; elemType := settype.sons[0];
first := firstOrd(elemType); first := firstOrd(elemType);
result := newNode(nkConstSetConstr); result := newNode(nkCurly);
result.typ := settype; result.typ := settype;
result.info := info; result.info := info;
@ -244,7 +244,7 @@ function SetHasRange(s: PNode): Boolean;
var var
i: int; i: int;
begin begin
assert(s.kind in [nkSetConstr, nkConstSetConstr]); if s.kind <> nkCurly then InternalError(s.info, 'SetHasRange');
for i := 0 to sonsLen(s)-1 do for i := 0 to sonsLen(s)-1 do
if s.sons[i].kind = nkRange then begin if s.sons[i].kind = nkRange then begin
result := true; exit result := true; exit

View file

@ -22,8 +22,8 @@ uses
{$ifdef mswindows} {$ifdef mswindows}
windows, windows,
{$else} {$else}
unix,
dos, dos,
unix,
{$endif} {$endif}
strutils, strutils,
nsystem; nsystem;
@ -83,6 +83,14 @@ function sameFile(const path1, path2: string): boolean;
implementation implementation
function UnixToNativePath(const path: string): string;
begin
if dirSep <> '/' then
result := replaceStr(path, '/', dirSep)
else
result := path;
end;
function expandFilename(filename: string): string; function expandFilename(filename: string): string;
begin begin
result := sysutils.expandFilename(filename) result := sysutils.expandFilename(filename)
@ -90,16 +98,8 @@ end;
function sameFile(const path1, path2: string): boolean; function sameFile(const path1, path2: string): boolean;
begin begin
result := cmpIgnoreCase(expandFilename(path1), result := cmpIgnoreCase(expandFilename(UnixToNativePath(path1)),
expandFilename(path2)) = 0; expandFilename(UnixToNativePath(path2))) = 0;
end;
function UnixToNativePath(const path: string): string;
begin
if dirSep <> '/' then
result := replaceStr(path, '/', dirSep)
else
result := path;
end; end;
procedure createDir(dir: string); procedure createDir(dir: string);
@ -417,8 +417,9 @@ begin
SI.hStdError := GetStdHandle(STD_ERROR_HANDLE); SI.hStdError := GetStdHandle(STD_ERROR_HANDLE);
SI.hStdInput := GetStdHandle(STD_INPUT_HANDLE); SI.hStdInput := GetStdHandle(STD_INPUT_HANDLE);
SI.hStdOutput := GetStdHandle(STD_OUTPUT_HANDLE); SI.hStdOutput := GetStdHandle(STD_OUTPUT_HANDLE);
if not Windows.CreateProcess(nil, PChar(cmd), nil, nil, true, if not Windows.CreateProcess(nil, PChar(cmd), nil, nil, false,
NORMAL_PRIORITY_CLASS, Windows.GetEnvironmentStrings(), nil, SI, ProcInfo) NORMAL_PRIORITY_CLASS, nil {Windows.GetEnvironmentStrings()},
nil, SI, ProcInfo)
then then
result := getLastError() result := getLastError()
else begin else begin
@ -434,6 +435,13 @@ begin
end; end;
end; end;
{$else}
{$ifdef windows}
function executeProcess(const cmd: string): int;
begin
result := dos.Exec(cmd, '')
end;
//C:\Eigenes\compiler\MinGW\bin;
{$else} {$else}
// fpc has a portable function for this // fpc has a portable function for this
function executeProcess(const cmd: string): int; function executeProcess(const cmd: string): int;
@ -441,6 +449,7 @@ begin
result := shell(cmd); result := shell(cmd);
end; end;
{$endif} {$endif}
{$endif}
{$ifdef windows} {$ifdef windows}
type type

View file

@ -90,10 +90,11 @@ type
TAddress = longint; TAddress = longint;
{$endif} {$endif}
var
NaN: float;
inf: float;
NegInf: float;
{$ifdef fpc} {$ifdef fpc}
const
inf = math.Infinity;
NegInf = -inf;
{$else} {$else}
{$ifopt Q+} {$ifopt Q+}
{$define Q_on} {$define Q_on}
@ -150,6 +151,10 @@ function shlU(a, b: biggestInt): biggestInt;
function shrU(a, b: biggestInt): biggestInt; function shrU(a, b: biggestInt): biggestInt;
function ltU(a, b: biggestInt): bool; function ltU(a, b: biggestInt): bool;
function leU(a, b: biggestInt): bool; function leU(a, b: biggestInt): bool;
function toU8(a: biggestInt): byte;
function toU32(a: biggestInt): int32;
function ze64(a: byte): biggestInt;
{@emit} {@emit}
function alloc(size: int): Pointer; function alloc(size: int): Pointer;
@ -257,6 +262,23 @@ function leU(a, b: biggestInt): bool;
begin begin
result := biggestUInt(a) < biggestUInt(b); result := biggestUInt(a) < biggestUInt(b);
end; end;
function toU8(a: biggestInt): byte;
begin
assert(a >= 0);
assert(a <= 255);
result := a;
end;
function toU32(a: biggestInt): int32;
begin
result := int32(a and $ffffffff);
end;
function ze64(a: byte): biggestInt;
begin
result := a
end;
{@emit} {@emit}
procedure addChar(var s: string; c: Char); procedure addChar(var s: string; c: Char);
@ -486,4 +508,21 @@ end;
{$ifdef I_on} {$undef I_on} {$I+} {$endif} {$ifdef I_on} {$undef I_on} {$I+} {$endif}
{$ifopt R+} {$R-,Q-} {$define R_on} {$endif}
var
zero: float;
Saved8087CW: Word;
initialization
Saved8087CW := Default8087CW;
Set8087CW($133f); // Disable all fpu exceptions
zero := 0.0;
NaN := 0.0 / zero;
inf := 1.0 / zero;
NegInf := -inf;
finalization
Set8087CW(Saved8087CW);
{$ifdef R_on}
{$R+,Q+}
{$endif}
end. end.

View file

@ -18,22 +18,32 @@ interface
uses uses
strutils; strutils;
// the Pascal version number gets a little star ('*'), the Nimrod version
// does not! This helps distinguishing the different builds.
{@ignore}
const
VersionStar = '*'+'';
{@emit
const
VersionStar = '';
}
const const
MaxSetElements = 1 shl 16; // (2^16) to support unicode character sets? MaxSetElements = 1 shl 16; // (2^16) to support unicode character sets?
defaultAsmMarkerSymbol = '!'; defaultAsmMarkerSymbol = '!';
//[[[cog //[[[cog
//from koch import NIMROD_VERSION //from koch import NIMROD_VERSION
//cog.outl("VersionAsString = '%s';" % NIMROD_VERSION) //cog.outl("VersionAsString = '%s'+VersionStar;" % NIMROD_VERSION)
//ver = NIMROD_VERSION.split('.') //ver = NIMROD_VERSION.split('.')
//cog.outl('VersionMajor = %s;' % ver[0]) //cog.outl('VersionMajor = %s;' % ver[0])
//cog.outl('VersionMinor = %s;' % ver[1]) //cog.outl('VersionMinor = %s;' % ver[1])
//cog.outl('VersionPatch = %s;' % ver[2]) //cog.outl('VersionPatch = %s;' % ver[2])
//]]] //]]]
VersionAsString = '0.5.1'; VersionAsString = '0.6.0'+VersionStar;
VersionMajor = 0; VersionMajor = 0;
VersionMinor = 5; VersionMinor = 6;
VersionPatch = 1; VersionPatch = 0;
//[[[[end]]]] //[[[[end]]]]
implementation implementation

34
nim/optast.pas Normal file
View file

@ -0,0 +1,34 @@
//
//
// The Nimrod Compiler
// (c) Copyright 2008 Andreas Rumpf
//
// See the file "copying.txt", included in this
// distribution, for details about the copyright.
//
unit optast;
// Optimizations that can be done by AST transformations. The code generators
// should work without the optimizer. The optimizer does the following:
// - cross-module constant merging
// - cross-module generic merging
// - lowers set operations to bit operations
// - inlining of procs
// - ``s == ""`` --> ``len(s) == 0``
// - optimization of ``&`` string operator
interface
{$include 'config.inc'}
uses
nsystem, ast, astalgo, strutils, hashes, trees, treetab, platform, magicsys,
options, msgs, crc, idents, lists, types, ropes, nmath, wordrecg, rnimsyn;
implementation
end.

View file

@ -13,12 +13,14 @@ interface
{$include 'config.inc'} {$include 'config.inc'}
uses uses
nsystem, nos, lists, strutils; nsystem, nos, lists, strutils, strtabs;
type type
// please make sure we have under 32 options // please make sure we have under 32 options
// (improves code efficiency a lot!) // (improves code efficiency a lot!)
TOption = (optNone, optRangeCheck, TOption = (optNone,
optObjCheck,
optFieldCheck, optRangeCheck,
optBoundsCheck, optOverflowCheck, optNilCheck, optAssert, optLineDir, optBoundsCheck, optOverflowCheck, optNilCheck, optAssert, optLineDir,
optWarns, optHints, optWarns, optHints,
optOptimizeSpeed, optOptimizeSpeed,
@ -56,6 +58,7 @@ type
cmdNone, cmdNone,
cmdCompileToC, cmdCompileToC,
cmdCompileToCpp, cmdCompileToCpp,
cmdCompileToEcmaScript,
cmdInterpret, cmdInterpret,
cmdPretty, cmdPretty,
cmdDoc, cmdDoc,
@ -69,32 +72,27 @@ type
cmdDebugTrans, // debug a transformation pass cmdDebugTrans, // debug a transformation pass
cmdRst2html // convert a reStructuredText file to HTML cmdRst2html // convert a reStructuredText file to HTML
); );
TStringSeq = array of string;
TNumericalBase = (base10, // base10 is listed as the first element,
// so that it is the correct default value
base2,
base8,
base16);
const const
ChecksOptions = {@set}[optRangeCheck, optNilCheck, optOverflowCheck, ChecksOptions = {@set}[optObjCheck, optFieldCheck, optRangeCheck,
optBoundsCheck, optAssert]; optNilCheck, optOverflowCheck, optBoundsCheck,
optAssert];
optionToStr: array [TOption] of string = ( optionToStr: array [TOption] of string = (
'optNone', 'optRangeCheck', 'optNone', 'optObjCheck', 'optFieldCheck', 'optRangeCheck',
'optBoundsCheck', 'optOverflowCheck', 'optNilCheck', 'optAssert', 'optBoundsCheck', 'optOverflowCheck', 'optNilCheck', 'optAssert',
'optLineDir', 'optWarns', 'optHints', 'optOptimizeSpeed', 'optLineDir', 'optWarns', 'optHints', 'optOptimizeSpeed',
'optOptimizeSize', 'optStackTrace', 'optLineTrace', 'optEmdb', 'optOptimizeSize', 'optStackTrace', 'optLineTrace', 'optEmdb',
'optByRef', 'optCheckpoints' 'optByRef', 'optCheckpoints'
); );
var var
gOptions: TOptions = {@set}[optRangeCheck, optBoundsCheck, optOverflowCheck, gOptions: TOptions = {@set}[optObjCheck, optFieldCheck, optRangeCheck,
optBoundsCheck, optOverflowCheck,
optAssert, optWarns, optHints, optLineDir, optAssert, optWarns, optHints, optLineDir,
optStackTrace, optLineTrace]; optStackTrace, optLineTrace];
gGlobalOptions: TGlobalOptions = {@set}[optRefcGC]; gGlobalOptions: TGlobalOptions = {@set}[optRefcGC];
compilerArgs: int;
gExitcode: Byte; gExitcode: Byte;
searchPaths: TLinkedList; searchPaths: TLinkedList;
outFile: string = ''; outFile: string = '';
@ -124,22 +122,15 @@ function getPrefixDir: string;
// gets the application directory // gets the application directory
// additional configuration variables: // additional configuration variables:
type
TPair = record
key, val: string;
end;
TPairs = array of TPair;
TStringSeq = array of string;
var var
gConfigVars: TPairs = {@ignore} nil {@emit []}; gConfigVars: PStringTable;
libpath: string = ''; libpath: string = '';
gKeepComments: boolean = true; // whether the parser needs to keep comments gKeepComments: boolean = true; // whether the parser needs to keep comments
gImplicitMods: TStringSeq = {@ignore} nil {@emit []}; gImplicitMods: TStringSeq = {@ignore} nil {@emit []};
// modules that are to be implicitly imported // modules that are to be implicitly imported
procedure setConfigVar(const key, val: string);
function getConfigVar(const key: string): string; function getConfigVar(const key: string): string;
procedure setConfigVar(const key, val: string);
procedure addImplicitMod(const filename: string); procedure addImplicitMod(const filename: string);
@ -149,6 +140,16 @@ function binaryStrSearch(const x: array of string; const y: string): int;
implementation implementation
function getConfigVar(const key: string): string;
begin
result := strtabs.get(gConfigVars, key);
end;
procedure setConfigVar(const key, val: string);
begin
strtabs.put(gConfigVars, key, val);
end;
function getOutFile(const filename, ext: string): string; function getOutFile(const filename, ext: string): string;
begin begin
if options.outFile <> '' then result := options.outFile if options.outFile <> '' then result := options.outFile
@ -172,38 +173,6 @@ begin
SplitPath(appdir, result, bin); SplitPath(appdir, result, bin);
end; end;
function getConfigIdx(const key: string): int;
var
i: int;
begin
for i := 0 to high(gConfigVars) do
if cmpIgnoreStyle(gConfigVars[i].key, key) = 0 then begin
result := i; exit end;
result := -1
end;
function getConfigVar(const key: string): string;
var
i: int;
begin
i := getConfigIdx(key);
if i >= 0 then result := gConfigVars[i].val
else result := ''
end;
procedure setConfigVar(const key, val: string);
var
i: int;
begin
i := getConfigIdx(key);
if i < 0 then begin
i := length(gConfigVars);
setLength(gConfigVars, i+1);
gConfigVars[i].key := key
end;
gConfigVars[i].val := val
end;
function toGeneratedFile(const path, ext: string): string; function toGeneratedFile(const path, ext: string): string;
var var
head, tail: string; head, tail: string;
@ -261,4 +230,6 @@ begin
result := -1 result := -1
end; end;
initialization
gConfigVars := newStringTable([], modeStyleInsensitive);
end. end.

414
nim/parsecfg.pas Normal file
View file

@ -0,0 +1,414 @@
//
//
// Nimrod's Runtime Library
// (c) Copyright 2008 Andreas Rumpf
//
// See the file "copying.txt", included in this
// distribution, for details about the copyright.
//
unit parsecfg;
// A HIGH-PERFORMANCE configuration file parser;
// the Nimrod version of this file will become part
// of the standard library.
interface
{$include 'config.inc'}
uses
charsets, nsystem, sysutils, hashes, strutils, lexbase;
type
TCfgEventKind = (
cfgEof, // end of file reached
cfgSectionStart, // a ``[section]`` has been parsed
cfgKeyValuePair, // a ``key=value`` pair has been detected
cfgOption, // a ``--key=value`` command line option
cfgError // an error ocurred during parsing; msg contains the
// error message
);
TCfgEvent = {@ignore} record
kind: TCfgEventKind;
section: string;
key, value: string;
msg: string;
end;
{@emit object(NObject)
case kind: TCfgEventKind of
cfgSection: (section: string);
cfgKeyValuePair, cfgOption: (key, value: string);
cfgError: (msg: string);
end;}
TTokKind = (tkInvalid, tkEof, // order is important here!
tkSymbol, tkEquals, tkColon,
tkBracketLe, tkBracketRi, tkDashDash
);
TToken = record // a token
kind: TTokKind; // the type of the token
literal: string; // the parsed (string) literal
end;
TParserState = (startState, commaState);
TCfgParser = object(TBaseLexer)
tok: TToken;
state: TParserState;
filename: string;
end;
function Open(var c: TCfgParser; const filename: string): bool;
procedure OpenFromBuffer(var c: TCfgParser; const buf: string);
procedure Close(var c: TCfgParser);
function next(var c: TCfgParser): TCfgEvent;
function getColumn(const c: TCfgParser): int;
function getLine(const c: TCfgParser): int;
function getFilename(const c: TCfgParser): string;
implementation
const
SymChars: TCharSet = ['a'..'z', 'A'..'Z', '0'..'9', '_', #128..#255];
// ----------------------------------------------------------------------------
procedure rawGetTok(var c: TCfgParser; var tok: TToken); forward;
function open(var c: TCfgParser; const filename: string): bool;
begin
{@ignore}
FillChar(c, sizeof(c), 0); // work around Delphi/fpc bug
{@emit}
result := initBaseLexer(c, filename);
c.filename := filename;
c.state := startState;
c.tok.kind := tkInvalid;
c.tok.literal := '';
if result then rawGetTok(c, c.tok);
end;
procedure openFromBuffer(var c: TCfgParser; const buf: string);
begin
{@ignore}
FillChar(c, sizeof(c), 0); // work around Delphi/fpc bug
{@emit}
initBaseLexerFromBuffer(c, buf);
c.filename := 'buffer';
c.state := startState;
c.tok.kind := tkInvalid;
c.tok.literal := '';
rawGetTok(c, c.tok);
end;
procedure close(var c: TCfgParser);
begin
deinitBaseLexer(c);
end;
function getColumn(const c: TCfgParser): int;
begin
result := getColNumber(c, c.bufPos)
end;
function getLine(const c: TCfgParser): int;
begin
result := c.linenumber
end;
function getFilename(const c: TCfgParser): string;
begin
result := c.filename
end;
// ----------------------------------------------------------------------------
procedure handleHexChar(var c: TCfgParser; var xi: int);
begin
case c.buf[c.bufpos] of
'0'..'9': begin
xi := (xi shl 4) or (ord(c.buf[c.bufpos]) - ord('0'));
inc(c.bufpos);
end;
'a'..'f': begin
xi := (xi shl 4) or (ord(c.buf[c.bufpos]) - ord('a') + 10);
inc(c.bufpos);
end;
'A'..'F': begin
xi := (xi shl 4) or (ord(c.buf[c.bufpos]) - ord('A') + 10);
inc(c.bufpos);
end;
else begin end // do nothing
end
end;
procedure handleDecChars(var c: TCfgParser; var xi: int);
begin
while c.buf[c.bufpos] in ['0'..'9'] do begin
xi := (xi * 10) + (ord(c.buf[c.bufpos]) - ord('0'));
inc(c.bufpos);
end;
end;
procedure getEscapedChar(var c: TCfgParser; var tok: TToken);
var
xi: int;
begin
inc(c.bufpos); // skip '\'
case c.buf[c.bufpos] of
'n', 'N': begin
tok.literal := tok.literal +{&} nl;
Inc(c.bufpos);
end;
'r', 'R', 'c', 'C': begin addChar(tok.literal, CR); Inc(c.bufpos); end;
'l', 'L': begin addChar(tok.literal, LF); Inc(c.bufpos); end;
'f', 'F': begin addChar(tok.literal, FF); inc(c.bufpos); end;
'e', 'E': begin addChar(tok.literal, ESC); Inc(c.bufpos); end;
'a', 'A': begin addChar(tok.literal, BEL); Inc(c.bufpos); end;
'b', 'B': begin addChar(tok.literal, BACKSPACE); Inc(c.bufpos); end;
'v', 'V': begin addChar(tok.literal, VT); Inc(c.bufpos); end;
't', 'T': begin addChar(tok.literal, Tabulator); Inc(c.bufpos); end;
'''', '"': begin addChar(tok.literal, c.buf[c.bufpos]); Inc(c.bufpos); end;
'\': begin addChar(tok.literal, '\'); Inc(c.bufpos) end;
'x', 'X': begin
inc(c.bufpos);
xi := 0;
handleHexChar(c, xi);
handleHexChar(c, xi);
addChar(tok.literal, Chr(xi));
end;
'0'..'9': begin
xi := 0;
handleDecChars(c, xi);
if (xi <= 255) then
addChar(tok.literal, Chr(xi))
else
tok.kind := tkInvalid
end
else tok.kind := tkInvalid
end
end;
function HandleCRLF(var c: TCfgParser; pos: int): int;
begin
case c.buf[pos] of
CR: result := lexbase.HandleCR(c, pos);
LF: result := lexbase.HandleLF(c, pos);
else result := pos
end
end;
procedure getString(var c: TCfgParser; var tok: TToken; rawMode: Boolean);
var
pos: int;
ch: Char;
buf: PChar;
begin
pos := c.bufPos + 1; // skip "
buf := c.buf; // put `buf` in a register
tok.kind := tkSymbol;
if (buf[pos] = '"') and (buf[pos+1] = '"') then begin
// long string literal:
inc(pos, 2); // skip ""
// skip leading newline:
pos := HandleCRLF(c, pos);
repeat
case buf[pos] of
'"': begin
if (buf[pos+1] = '"') and (buf[pos+2] = '"') then
break;
addChar(tok.literal, '"');
Inc(pos)
end;
CR, LF: begin
pos := HandleCRLF(c, pos);
tok.literal := tok.literal +{&} nl;
end;
lexbase.EndOfFile: begin
tok.kind := tkInvalid;
break
end
else begin
addChar(tok.literal, buf[pos]);
Inc(pos)
end
end
until false;
c.bufpos := pos + 3 // skip the three """
end
else begin // ordinary string literal
repeat
ch := buf[pos];
if ch = '"' then begin
inc(pos); // skip '"'
break
end;
if ch in [CR, LF, lexbase.EndOfFile] then begin
tok.kind := tkInvalid;
break
end;
if (ch = '\') and not rawMode then begin
c.bufPos := pos;
getEscapedChar(c, tok);
pos := c.bufPos;
end
else begin
addChar(tok.literal, ch);
Inc(pos)
end
until false;
c.bufpos := pos;
end
end;
procedure getSymbol(var c: TCfgParser; var tok: TToken);
var
pos: int;
buf: pchar;
begin
pos := c.bufpos;
buf := c.buf;
while true do begin
addChar(tok.literal, buf[pos]);
Inc(pos);
if not (buf[pos] in SymChars) then break;
end;
c.bufpos := pos;
tok.kind := tkSymbol
end;
procedure skip(var c: TCfgParser);
var
buf: PChar;
pos: int;
begin
pos := c.bufpos;
buf := c.buf;
repeat
case buf[pos] of
' ': Inc(pos);
Tabulator: inc(pos);
'#', ';': while not (buf[pos] in [CR, LF, lexbase.EndOfFile]) do inc(pos);
CR, LF: pos := HandleCRLF(c, pos);
else break // EndOfFile also leaves the loop
end
until false;
c.bufpos := pos;
end;
procedure rawGetTok(var c: TCfgParser; var tok: TToken);
begin
tok.kind := tkInvalid;
setLength(tok.literal, 0);
skip(c);
case c.buf[c.bufpos] of
'=': begin
tok.kind := tkEquals;
inc(c.bufpos);
tok.literal := '='+'';
end;
'-': begin
inc(c.bufPos);
if c.buf[c.bufPos] = '-' then inc(c.bufPos);
tok.kind := tkDashDash;
tok.literal := '--';
end;
':': begin
tok.kind := tkColon;
inc(c.bufpos);
tok.literal := ':'+'';
end;
'r', 'R': begin
if c.buf[c.bufPos+1] = '"' then begin
Inc(c.bufPos);
getString(c, tok, true);
end
else
getSymbol(c, tok);
end;
'[': begin
tok.kind := tkBracketLe;
inc(c.bufpos);
tok.literal := '['+'';
end;
']': begin
tok.kind := tkBracketRi;
Inc(c.bufpos);
tok.literal := ']'+'';
end;
'"': getString(c, tok, false);
lexbase.EndOfFile: tok.kind := tkEof;
else getSymbol(c, tok);
end
end;
function errorStr(const c: TCfgParser; const msg: string): string;
begin
result := format('$1($2, $3) Error: $4', [
c.filename, toString(getLine(c)), toString(getColumn(c)),
msg
]);
end;
function getKeyValPair(var c: TCfgParser; kind: TCfgEventKind): TCfgEvent;
begin
if c.tok.kind = tkSymbol then begin
result.kind := kind;
result.key := c.tok.literal;
result.value := '';
rawGetTok(c, c.tok);
if c.tok.kind in [tkEquals, tkColon] then begin
rawGetTok(c, c.tok);
if c.tok.kind = tkSymbol then begin
result.value := c.tok.literal;
end
else begin
result.kind := cfgError;
result.msg := errorStr(c, 'symbol expected, but found: '
+ c.tok.literal);
end;
rawGetTok(c, c.tok);
end
end
else begin
result.kind := cfgError;
result.msg := errorStr(c, 'symbol expected, but found: ' + c.tok.literal);
rawGetTok(c, c.tok);
end;
end;
function next(var c: TCfgParser): TCfgEvent;
begin
case c.tok.kind of
tkEof: result.kind := cfgEof;
tkDashDash: begin
rawGetTok(c, c.tok);
result := getKeyValPair(c, cfgOption);
end;
tkSymbol: begin
result := getKeyValPair(c, cfgKeyValuePair);
end;
tkBracketLe: begin
rawGetTok(c, c.tok);
if c.tok.kind = tkSymbol then begin
result.kind := cfgSectionStart;
result.section := c.tok.literal;
end
else begin
result.kind := cfgError;
result.msg := errorStr(c, 'symbol expected, but found: ' + c.tok.literal);
end;
rawGetTok(c, c.tok);
if c.tok.kind = tkBracketRi then rawGetTok(c, c.tok)
else begin
result.kind := cfgError;
result.msg := errorStr(c, ''']'' expected, but found: ' + c.tok.literal);
end
end;
tkInvalid, tkEquals, tkColon: begin
result.kind := cfgError;
result.msg := errorStr(c, 'invalid token: ' + c.tok.literal);
rawGetTok(c, c.tok);
end
end
end;
end.

153
nim/parseopt.pas Normal file
View file

@ -0,0 +1,153 @@
//
//
// Nimrod's Runtime Library
// (c) Copyright 2008 Andreas Rumpf
//
// See the file "copying.txt", included in this
// distribution, for details about the copyright.
//
unit parseopt;
// A command line parser; the Nimrod version of this file
// will become part of the standard library.
interface
{$include 'config.inc'}
uses
nsystem, charsets, nos, strutils;
type
TCmdLineKind = (
cmdEnd, // end of command line reached
cmdArgument, // argument detected
cmdLongoption, // a long option ``--option`` detected
cmdShortOption // a short option ``-c`` detected
);
TOptParser = object(NObject)
cmd: string;
pos: int;
inShortState: bool;
kind: TCmdLineKind;
key, val: string;
end;
function init(const cmdline: string = ''): TOptParser;
procedure next(var p: TOptParser);
function getRestOfCommandLine(const p: TOptParser): string;
implementation
function init(const cmdline: string = ''): TOptParser;
var
i: int;
begin
result.pos := strStart;
result.inShortState := false;
if cmdline <> '' then
result.cmd := cmdline
else begin
result.cmd := '';
for i := 1 to ParamCount() do
result.cmd := result.cmd +{&} quoteIfSpaceExists(paramStr(i)) +{&} ' ';
{@ignore}
result.cmd := result.cmd + #0;
{@emit}
end;
result.kind := cmdEnd;
result.key := '';
result.val := '';
end;
function parseWord(const s: string; const i: int; var w: string;
const delim: TCharSet = {@set}[#9, ' ', #0]): int;
begin
result := i;
if s[result] = '"' then begin
inc(result);
while not (s[result] in [#0, '"']) do begin
addChar(w, s[result]);
inc(result);
end;
if s[result] = '"' then inc(result)
end
else begin
while not (s[result] in delim) do begin
addChar(w, s[result]);
inc(result);
end
end
end;
procedure handleShortOption(var p: TOptParser);
var
i: int;
begin
i := p.pos;
p.kind := cmdShortOption;
addChar(p.key, p.cmd[i]);
inc(i);
p.inShortState := true;
while p.cmd[i] in [#9, ' '] do begin
inc(i);
p.inShortState := false;
end;
if p.cmd[i] in [':', '='] then begin
inc(i); p.inShortState := false;
while p.cmd[i] in [#9, ' '] do inc(i);
i := parseWord(p.cmd, i, p.val);
end;
if p.cmd[i] = #0 then p.inShortState := false;
p.pos := i;
end;
procedure next(var p: TOptParser);
var
i: int;
begin
i := p.pos;
while p.cmd[i] in [#9, ' '] do inc(i);
p.pos := i;
setLength(p.key, 0);
setLength(p.val, 0);
if p.inShortState then begin
handleShortOption(p); exit
end;
case p.cmd[i] of
#0: p.kind := cmdEnd;
'-': begin
inc(i);
if p.cmd[i] = '-' then begin
p.kind := cmdLongOption;
inc(i);
i := parseWord(p.cmd, i, p.key, {@set}[#0, ' ', #9, ':', '=']);
while p.cmd[i] in [#9, ' '] do inc(i);
if p.cmd[i] in [':', '='] then begin
inc(i);
while p.cmd[i] in [#9, ' '] do inc(i);
p.pos := parseWord(p.cmd, i, p.val);
end
else
p.pos := i;
end
else begin
p.pos := i;
handleShortOption(p)
end
end;
else begin
p.kind := cmdArgument;
p.pos := parseWord(p.cmd, i, p.key);
end
end
end;
function getRestOfCommandLine(const p: TOptParser): string;
begin
result := strip(ncopy(p.cmd, p.pos+strStart, length(p.cmd)-1))
// always -1, because Pascal version uses a trailing zero here
end;
end.

View file

@ -70,6 +70,7 @@ type
pxSymbol, // a symbol pxSymbol, // a symbol
pxIntLit, pxIntLit,
pxInt64Lit, // long constant like 0x00000070fffffff or out of int range
pxFloatLit, pxFloatLit,
pxParLe, pxParRi, pxBracketLe, pxBracketRi, pxParLe, pxParRi, pxBracketLe, pxBracketRi,
@ -110,7 +111,8 @@ const
'with', 'xor', 'with', 'xor',
//[[[end]]] //[[[end]]]
'pxComment', 'pxCommand', 'pxComment', 'pxCommand',
'{&}', '{%}', 'pxStrLit', '[IDENTIFIER]', 'pxIntLit', 'pxFloatLit', '{&}', '{%}', 'pxStrLit', '[IDENTIFIER]', 'pxIntLit', 'pxInt64Lit',
'pxFloatLit',
'('+'', ')'+'', '['+'', ']'+'', '('+'', ')'+'', '['+'', ']'+'',
','+'', ';'+'', ':'+'', ','+'', ';'+'', ':'+'',
':=', '='+'', '.'+'', '..', '^'+'', '+'+'', '-'+'', '*'+'', '/'+'', ':=', '='+'', '.'+'', '..', '^'+'', '+'+'', '-'+'', '*'+'', '/'+'',
@ -135,7 +137,7 @@ implementation
function pastokToStr(const tok: TPasTok): string; function pastokToStr(const tok: TPasTok): string;
begin begin
case tok.xkind of case tok.xkind of
pxIntLit: pxIntLit, pxInt64Lit:
result := toString(tok.iNumber); result := toString(tok.iNumber);
pxFloatLit: pxFloatLit:
result := toStringF(tok.fNumber); result := toStringF(tok.fNumber);
@ -271,7 +273,7 @@ end;
procedure getNumber2(var L: TPasLex; var tok: TPasTok); procedure getNumber2(var L: TPasLex; var tok: TPasTok);
var var
pos: int; pos, bits: int;
xi: biggestInt; xi: biggestInt;
begin begin
pos := L.bufpos+1; // skip % pos := L.bufpos+1; // skip %
@ -284,6 +286,7 @@ begin
tok.base := base2; tok.base := base2;
xi := 0; xi := 0;
bits := 0;
while true do begin while true do begin
case L.buf[pos] of case L.buf[pos] of
'A'..'Z', 'a'..'z', '2'..'9', '.': begin 'A'..'Z', 'a'..'z', '2'..'9', '.': begin
@ -294,23 +297,28 @@ begin
'0', '1': begin '0', '1': begin
xi := (xi shl 1) or (ord(L.buf[pos]) - ord('0')); xi := (xi shl 1) or (ord(L.buf[pos]) - ord('0'));
inc(pos); inc(pos);
inc(bits);
end; end;
else break; else break;
end end
end; end;
tok.iNumber := xi; tok.iNumber := xi;
if (bits > 32) then //or (xi < low(int32)) or (xi > high(int32)) then
tok.xkind := pxInt64Lit
else
tok.xkind := pxIntLit; tok.xkind := pxIntLit;
L.bufpos := pos; L.bufpos := pos;
end; end;
procedure getNumber16(var L: TPasLex; var tok: TPasTok); procedure getNumber16(var L: TPasLex; var tok: TPasTok);
var var
pos: int; pos, bits: int;
xi: biggestInt; xi: biggestInt;
begin begin
pos := L.bufpos+1; // skip $ pos := L.bufpos+1; // skip $
tok.base := base16; tok.base := base16;
xi := 0; xi := 0;
bits := 0;
while true do begin while true do begin
case L.buf[pos] of case L.buf[pos] of
'G'..'Z', 'g'..'z', '.': begin 'G'..'Z', 'g'..'z', '.': begin
@ -321,19 +329,25 @@ begin
'0'..'9': begin '0'..'9': begin
xi := (xi shl 4) or (ord(L.buf[pos]) - ord('0')); xi := (xi shl 4) or (ord(L.buf[pos]) - ord('0'));
inc(pos); inc(pos);
inc(bits, 4);
end; end;
'a'..'f': begin 'a'..'f': begin
xi := (xi shl 4) or (ord(L.buf[pos]) - ord('a') + 10); xi := (xi shl 4) or (ord(L.buf[pos]) - ord('a') + 10);
inc(pos); inc(pos);
inc(bits, 4);
end; end;
'A'..'F': begin 'A'..'F': begin
xi := (xi shl 4) or (ord(L.buf[pos]) - ord('A') + 10); xi := (xi shl 4) or (ord(L.buf[pos]) - ord('A') + 10);
inc(pos); inc(pos);
inc(bits, 4);
end; end;
else break; else break;
end end
end; end;
tok.iNumber := xi; tok.iNumber := xi;
if (bits > 32) then // (xi < low(int32)) or (xi > high(int32)) then
tok.xkind := pxInt64Lit
else
tok.xkind := pxIntLit; tok.xkind := pxIntLit;
L.bufpos := pos; L.bufpos := pos;
end; end;
@ -354,6 +368,9 @@ begin
end end
else begin else begin
tok.iNumber := ParseInt(tok.literal); tok.iNumber := ParseInt(tok.literal);
if (tok.iNumber < low(int32)) or (tok.iNumber > high(int32)) then
tok.xkind := pxInt64Lit
else
tok.xkind := pxIntLit; tok.xkind := pxIntLit;
end; end;
except except

View file

@ -322,6 +322,10 @@ begin
result := newNodeP(nkPtrTy, p); result := newNodeP(nkPtrTy, p);
getTok(p); eat(p, pxCurlyDirRi); getTok(p); eat(p, pxCurlyDirRi);
end end
else if p.tok.ident.id = getIdent('tuple').id then begin
result := newNodeP(nkTupleTy, p);
getTok(p); eat(p, pxCurlyDirRi);
end
else begin else begin
parMessage(p, errUnknownDirective, pasTokToStr(p.tok)); parMessage(p, errUnknownDirective, pasTokToStr(p.tok));
while true do begin while true do begin
@ -481,6 +485,16 @@ begin
exprListAux(p, elemKind, endTok, sepTok, result); exprListAux(p, elemKind, endTok, sepTok, result);
end; end;
procedure setBaseFlags(n: PNode; base: TNumericalBase);
begin
case base of
base10: begin end;
base2: include(n.flags, nfBase2);
base8: include(n.flags, nfBase8);
base16: include(n.flags, nfBase16);
end
end;
function identOrLiteral(var p: TPasParser): PNode; function identOrLiteral(var p: TPasParser): PNode;
var var
a: PNode; a: PNode;
@ -493,12 +507,17 @@ begin
// literals // literals
pxIntLit: begin pxIntLit: begin
result := newIntNodeP(nkIntLit, p.tok.iNumber, p); result := newIntNodeP(nkIntLit, p.tok.iNumber, p);
result.base := p.tok.base; setBaseFlags(result, p.tok.base);
getTok(p);
end;
pxInt64Lit: begin
result := newIntNodeP(nkInt64Lit, p.tok.iNumber, p);
setBaseFlags(result, p.tok.base);
getTok(p); getTok(p);
end; end;
pxFloatLit: begin pxFloatLit: begin
result := newFloatNodeP(nkFloatLit, p.tok.fNumber, p); result := newFloatNodeP(nkFloatLit, p.tok.fNumber, p);
result.base := p.tok.base; setBaseFlags(result, p.tok.base);
getTok(p); getTok(p);
end; end;
pxStrLit: begin pxStrLit: begin
@ -683,6 +702,7 @@ begin
end end
else begin end else begin end
end; end;
if not (n.kind in [nkEmpty..nkNilLit]) then
for i := 0 to sonsLen(n)-1 do for i := 0 to sonsLen(n)-1 do
result.sons[i] := fixExpr(n.sons[i]) result.sons[i] := fixExpr(n.sons[i])
end; end;
@ -948,6 +968,7 @@ begin
if p.tok.xkind <> pxIf then begin if p.tok.xkind <> pxIf then begin
// ordinary else part: // ordinary else part:
branch := newNodeP(nkElse, p); branch := newNodeP(nkElse, p);
skipCom(p, result); // BUGFIX
addSon(branch, parseStmt(p)); addSon(branch, parseStmt(p));
addSon(result, branch); addSon(result, branch);
break break
@ -1235,6 +1256,14 @@ begin
noBody := true; noBody := true;
getTok(p); opt(p, pxSemicolon); getTok(p); opt(p, pxSemicolon);
end; end;
wNoConv: begin
// This is a fake for platform module. There is no ``noconv``
// directive in Pascal.
if result = nil then result := newNodeP(nkPragma, p);
addSon(result, newIdentNodeP(getIdent('noconv'), p));
noBody := true;
getTok(p); opt(p, pxSemicolon);
end;
wVarargs: begin wVarargs: begin
if result = nil then result := newNodeP(nkPragma, p); if result = nil then result := newNodeP(nkPragma, p);
addSon(result, newIdentNodeP(getIdent('varargs'), p)); addSon(result, newIdentNodeP(getIdent('varargs'), p));
@ -1464,7 +1493,7 @@ begin
nkIdent, nkAccQuoted: begin nkIdent, nkAccQuoted: begin
a := newNode(nkPostFix); a := newNode(nkPostFix);
a.info := n.info; a.info := n.info;
addSon(a, newIdentNode(getIdent('*'+''))); addSon(a, newIdentNode(getIdent('*'+''), n.info));
addSon(a, n); addSon(a, n);
n := a n := a
end; end;
@ -1486,7 +1515,7 @@ begin
end end
end; end;
nkRecList, nkRecWhen, nkElse, nkOfBranch, nkElifBranch, nkRecList, nkRecWhen, nkElse, nkOfBranch, nkElifBranch,
nkRecordTy, nkObjectTy: begin nkObjectTy: begin
for i := 0 to sonsLen(n)-1 do fixRecordDef(n.sons[i]) for i := 0 to sonsLen(n)-1 do fixRecordDef(n.sons[i])
end; end;
nkIdentDefs: begin nkIdentDefs: begin
@ -1497,6 +1526,19 @@ begin
end end
end; end;
procedure parseRecordBody(var p: TPasParser; result: PNode);
var
a: PNode;
begin
skipCom(p, result);
a := parseRecordPart(p);
if result.kind <> nkTupleTy then fixRecordDef(a);
addSon(result, a);
eat(p, pxEnd);
opt(p, pxSemicolon);
skipCom(p, result);
end;
function parseRecordOrObject(var p: TPasParser; kind: TNodeKind): PNode; function parseRecordOrObject(var p: TPasParser; kind: TNodeKind): PNode;
var var
a: PNode; a: PNode;
@ -1512,19 +1554,14 @@ begin
eat(p, pxParRi); eat(p, pxParRi);
end end
else addSon(result, nil); else addSon(result, nil);
skipCom(p, result); parseRecordBody(p, result);
a := parseRecordPart(p);
fixRecordDef(a);
addSon(result, a);
eat(p, pxEnd);
opt(p, pxSemicolon);
skipCom(p, result);
end; end;
function parseTypeDesc(var p: TPasParser): PNode; function parseTypeDesc(var p: TPasParser): PNode;
var var
oldcontext: TPasContext; oldcontext: TPasContext;
a, r: PNode; a, r: PNode;
i: int;
begin begin
oldcontext := p.context; oldcontext := p.context;
p.context := conTypeDesc; p.context := conTypeDesc;
@ -1532,7 +1569,28 @@ begin
case p.tok.xkind of case p.tok.xkind of
pxCommand: result := parseCommand(p); pxCommand: result := parseCommand(p);
pxProcedure, pxFunction: result := parseRoutineType(p); pxProcedure, pxFunction: result := parseRoutineType(p);
pxRecord: result := parseRecordOrObject(p, nkRecordTy); pxRecord: begin
getTok(p);
if p.tok.xkind = pxCommand then begin
result := parseCommand(p);
if result.kind <> nkTupleTy then
InternalError(result.info, 'parseTypeDesc');
parseRecordBody(p, result);
a := lastSon(result);
// embed nkRecList directly into nkTupleTy
for i := 0 to sonsLen(a)-1 do
if i = 0 then result.sons[sonsLen(result)-1] := a.sons[0]
else addSon(result, a.sons[i]);
end
else begin
result := newNodeP(nkReturnToken, p);
// we use nkReturnToken to signal that this object should be marked as
// final
addSon(result, nil);
addSon(result, nil);
parseRecordBody(p, result);
end;
end;
pxObject: result := parseRecordOrObject(p, nkObjectTy); pxObject: result := parseRecordOrObject(p, nkObjectTy);
pxParLe: result := parseEnum(p); pxParLe: result := parseEnum(p);
pxArray: begin pxArray: begin
@ -1591,13 +1649,29 @@ begin
end; end;
function parseTypeDef(var p: TPasParser): PNode; function parseTypeDef(var p: TPasParser): PNode;
var
a, e, pragmasNode: PNode;
begin begin
result := newNodeP(nkTypeDef, p); result := newNodeP(nkTypeDef, p);
addSon(result, identVis(p)); addSon(result, identVis(p));
addSon(result, nil); // generic params addSon(result, nil); // generic params
if p.tok.xkind = pxEquals then begin if p.tok.xkind = pxEquals then begin
getTok(p); skipCom(p, result); getTok(p); skipCom(p, result);
addSon(result, parseTypeDesc(p)); a := parseTypeDesc(p);
addSon(result, a);
if a.kind = nkReturnToken then begin // a `final` object?
a.kind := nkObjectTy;
if result.sons[0].kind <> nkPragmaExpr then begin
e := newNodeP(nkPragmaExpr, p);
pragmasNode := newNodeP(nkPragma, p);
addSon(e, result.sons[0]);
addSon(e, pragmasNode);
result.sons[0] := e;
end
else
pragmasNode := result.sons[1];
addSon(pragmasNode, newIdentNodeP(getIdent('final'), p));
end
end end
else else
addSon(result, nil); addSon(result, nil);

View file

@ -13,7 +13,7 @@ unit platform;
// Note: Unfortunately if an OS or CPU is listed here this does not mean that // Note: Unfortunately if an OS or CPU is listed here this does not mean that
// Nimrod has been tested on this platform or that the RTL has been ported. // Nimrod has been tested on this platform or that the RTL has been ported.
// Feel free to test for your exentric platform! (Windows on I386 and Linux // Feel free to test for your exentric platform! (Windows on I386 and Linux
// on AMD64 have been tested, though.) // on I386 have been tested, though.)
interface interface
@ -45,7 +45,8 @@ type
osAtari, osAtari,
osNetware, osNetware,
osMacos, osMacos,
osMacosx osMacosx,
osEcmaScript
); );
type type
TInfoOSProp = ( TInfoOSProp = (
@ -55,7 +56,7 @@ type
); );
TInfoOSProps = set of TInfoOSProp; TInfoOSProps = set of TInfoOSProp;
TInfoOS = record TInfoOS = record{@tuple}
name: string; name: string;
parDir: string; parDir: string;
dllExt: string; dllExt: string;
@ -360,6 +361,22 @@ const
exeExt: ''; exeExt: '';
extSep: '.'+''; extSep: '.'+'';
props: {@set}[ospNeedsPIC, ospPosix]; props: {@set}[ospNeedsPIC, ospPosix];
),
(
name: 'EcmaScript';
parDir: '..';
dllExt: '.so';
altDirSep: '/'+'';
dllPrefix: 'lib';
objExt: '.o';
newLine: #10+'';
pathSep: ':'+'';
dirSep: '/'+'';
scriptExt: '.sh';
curDir: '.'+'';
exeExt: '';
extSep: '.'+'';
props: {@set}[];
) )
); );
type type
@ -377,11 +394,12 @@ type
cpuIa64, cpuIa64,
cpuAmd64, cpuAmd64,
cpuMips, cpuMips,
cpuArm cpuArm,
cpuEcmaScript
); );
type type
TEndian = (littleEndian, bigEndian); TEndian = (littleEndian, bigEndian);
TInfoCPU = record TInfoCPU = record{@tuple}
name: string; name: string;
intSize: int; intSize: int;
endian: TEndian; endian: TEndian;
@ -460,6 +478,13 @@ const
endian: littleEndian; endian: littleEndian;
floatSize: 64; floatSize: 64;
bit: 32; bit: 32;
),
(
name: 'ecmascript';
intSize: 32;
endian: bigEndian;
floatSize: 64;
bit: 32;
) )
); );
@ -517,9 +542,9 @@ end;
// this is Ok for the Pascal version, but the Nimrod version needs a different // this is Ok for the Pascal version, but the Nimrod version needs a different
// mechanism // mechanism
{@emit {@emit
procedure nimCPU(): cstring; importc;} procedure nimCPU(): cstring; importc; noconv;}
{@emit {@emit
procedure nimOS(): cstring; importc;} procedure nimOS(): cstring; importc; noconv;}
{@ignore} {@ignore}
initialization initialization

View file

@ -240,6 +240,9 @@ begin
end; end;
function parseSymbol(var p: TParser): PNode; function parseSymbol(var p: TParser): PNode;
var
s: string;
id: PIdent;
begin begin
case p.tok.tokType of case p.tok.tokType of
tkSymbol: begin tkSymbol: begin
@ -251,9 +254,31 @@ begin
getTok(p); getTok(p);
case p.tok.tokType of case p.tok.tokType of
tkBracketLe: begin tkBracketLe: begin
addSon(result, newIdentNodeP(getIdent('[]'), p)); s := '['+'';
getTok(p); getTok(p);
if (p.tok.tokType = tkOpr) and (p.tok.ident.s = '$'+'') then begin
s := s + '$..';
getTok(p);
eat(p, tkDotDot);
if (p.tok.tokType = tkOpr) and (p.tok.ident.s = '$'+'') then begin
s := s + '$'+'';
getTok(p);
end;
end
else if p.tok.tokType = tkDotDot then begin
s := s + '..';
getTok(p);
if (p.tok.tokType = tkOpr) and (p.tok.ident.s = '$'+'') then begin
s := s + '$'+'';
getTok(p);
end;
end;
eat(p, tkBracketRi); eat(p, tkBracketRi);
s := s + ']'+'';
if p.tok.tokType = tkEquals then begin
s := s + '='; getTok(p);
end;
addSon(result, newIdentNodeP(getIdent(s), p));
end; end;
tkParLe: begin tkParLe: begin
addSon(result, newIdentNodeP(getIdent('()'), p)); addSon(result, newIdentNodeP(getIdent('()'), p));
@ -261,8 +286,14 @@ begin
eat(p, tkParRi); eat(p, tkParRi);
end; end;
tokKeywordLow..tokKeywordHigh, tkSymbol, tkOpr: begin tokKeywordLow..tokKeywordHigh, tkSymbol, tkOpr: begin
addSon(result, newIdentNodeP(p.tok.ident, p)); id := p.tok.ident;
getTok(p); getTok(p);
if p.tok.tokType = tkEquals then begin
addSon(result, newIdentNodeP(getIdent(id.s + '='), p));
getTok(p);
end
else
addSon(result, newIdentNodeP(id, p));
end; end;
else begin else begin
parMessage(p, errIdentifierExpected, tokToStr(p.tok)); parMessage(p, errIdentifierExpected, tokToStr(p.tok));
@ -350,7 +381,7 @@ var
begin begin
case p.tok.tokType of case p.tok.tokType of
tkDotDot: result := dotdotExpr(p); tkDotDot: result := dotdotExpr(p);
tkVar, tkRef, tkPtr, tkProc, tkType: result := parseTypeDescK(p); tkVar, tkRef, tkPtr, tkProc, tkTuple, tkType: result := parseTypeDescK(p);
else begin else begin
a := parseExpr(p); a := parseExpr(p);
case p.tok.tokType of case p.tok.tokType of
@ -519,6 +550,16 @@ begin
eat(p, tkParRi); eat(p, tkParRi);
end; end;
procedure setBaseFlags(n: PNode; base: TNumericalBase);
begin
case base of
base10: begin end;
base2: include(n.flags, nfBase2);
base8: include(n.flags, nfBase8);
base16: include(n.flags, nfBase16);
end
end;
function identOrLiteral(var p: TParser): PNode; function identOrLiteral(var p: TParser): PNode;
begin begin
case p.tok.tokType of case p.tok.tokType of
@ -530,42 +571,42 @@ begin
// literals // literals
tkIntLit: begin tkIntLit: begin
result := newIntNodeP(nkIntLit, p.tok.iNumber, p); result := newIntNodeP(nkIntLit, p.tok.iNumber, p);
result.base := p.tok.base; setBaseFlags(result, p.tok.base);
getTok(p); getTok(p);
end; end;
tkInt8Lit: begin tkInt8Lit: begin
result := newIntNodeP(nkInt8Lit, p.tok.iNumber, p); result := newIntNodeP(nkInt8Lit, p.tok.iNumber, p);
result.base := p.tok.base; setBaseFlags(result, p.tok.base);
getTok(p); getTok(p);
end; end;
tkInt16Lit: begin tkInt16Lit: begin
result := newIntNodeP(nkInt16Lit, p.tok.iNumber, p); result := newIntNodeP(nkInt16Lit, p.tok.iNumber, p);
result.base := p.tok.base; setBaseFlags(result, p.tok.base);
getTok(p); getTok(p);
end; end;
tkInt32Lit: begin tkInt32Lit: begin
result := newIntNodeP(nkInt32Lit, p.tok.iNumber, p); result := newIntNodeP(nkInt32Lit, p.tok.iNumber, p);
result.base := p.tok.base; setBaseFlags(result, p.tok.base);
getTok(p); getTok(p);
end; end;
tkInt64Lit: begin tkInt64Lit: begin
result := newIntNodeP(nkInt64Lit, p.tok.iNumber, p); result := newIntNodeP(nkInt64Lit, p.tok.iNumber, p);
result.base := p.tok.base; setBaseFlags(result, p.tok.base);
getTok(p); getTok(p);
end; end;
tkFloatLit: begin tkFloatLit: begin
result := newFloatNodeP(nkFloatLit, p.tok.fNumber, p); result := newFloatNodeP(nkFloatLit, p.tok.fNumber, p);
result.base := p.tok.base; setBaseFlags(result, p.tok.base);
getTok(p); getTok(p);
end; end;
tkFloat32Lit: begin tkFloat32Lit: begin
result := newFloatNodeP(nkFloat32Lit, p.tok.fNumber, p); result := newFloatNodeP(nkFloat32Lit, p.tok.fNumber, p);
result.base := p.tok.base; setBaseFlags(result, p.tok.base);
getTok(p); getTok(p);
end; end;
tkFloat64Lit: begin tkFloat64Lit: begin
result := newFloatNodeP(nkFloat64Lit, p.tok.fNumber, p); result := newFloatNodeP(nkFloat64Lit, p.tok.fNumber, p);
result.base := p.tok.base; setBaseFlags(result, p.tok.base);
getTok(p); getTok(p);
end; end;
tkStrLit: begin tkStrLit: begin
@ -584,10 +625,6 @@ begin
result := newIntNodeP(nkCharLit, ord(p.tok.literal[strStart]), p); result := newIntNodeP(nkCharLit, ord(p.tok.literal[strStart]), p);
getTok(p); getTok(p);
end; end;
tkRCharLit: begin
result := newIntNodeP(nkRCharLit, ord(p.tok.literal[strStart]), p);
getTok(p);
end;
tkNil: begin tkNil: begin
result := newNodeP(nkNilLit, p); result := newNodeP(nkNilLit, p);
getTok(p); getTok(p);
@ -598,8 +635,7 @@ begin
tkColon); tkColon);
end; end;
tkCurlyLe: begin // {} constructor tkCurlyLe: begin // {} constructor
result := exprColonEqExprList(p, nkCurly, nkRange, tkCurlyRi, result := exprColonEqExprList(p, nkCurly, nkRange, tkCurlyRi, tkDotDot);
tkDotDot);
end; end;
tkBracketLe: begin // [] constructor tkBracketLe: begin // [] constructor
result := exprColonEqExprList(p, nkBracket, nkExprColonExpr, tkBracketRi, result := exprColonEqExprList(p, nkBracket, nkExprColonExpr, tkBracketRi,
@ -1278,6 +1314,8 @@ begin
end; end;
function parseTypeDescK(var p: TParser): PNode; function parseTypeDescK(var p: TParser): PNode;
var
a: PNode;
begin begin
case p.tok.tokType of case p.tok.tokType of
tkVar: result := parseTypeDescKAux(p, nkVarTy); tkVar: result := parseTypeDescKAux(p, nkVarTy);
@ -1298,7 +1336,25 @@ begin
addSon(result, parsePragma(p)) addSon(result, parsePragma(p))
else else
addSon(result, nil); addSon(result, nil);
end end;
tkTuple: begin
result := newNodeP(nkTupleTy, p);
getTok(p);
eat(p, tkBracketLe);
optInd(p, result);
while true do begin
case p.tok.tokType of
tkSymbol, tkAccent: a := parseIdentColonEquals(p, false);
tkBracketRi: begin getTok(p); break end;
else begin parMessage(p, errTokenExpected, ']'+''); break; end;
end;
optInd(p, a);
if p.tok.tokType = tkComma then begin
getTok(p); optInd(p, a)
end;
addSon(result, a);
end;
end;
else begin else begin
InternalError(parLineInfo(p), 'pnimsyn.parseTypeDescK'); InternalError(parLineInfo(p), 'pnimsyn.parseTypeDescK');
result := nil result := nil
@ -1309,7 +1365,7 @@ end;
function parseTypeDesc(var p: TParser): PNode; function parseTypeDesc(var p: TParser): PNode;
begin begin
case p.tok.tokType of case p.tok.tokType of
tkVar, tkRef, tkPtr, tkProc, tkType: tkVar, tkRef, tkPtr, tkProc, tkType, tkTuple:
result := parseTypeDescK(p); result := parseTypeDescK(p);
else result := primary(p) else result := primary(p)
end end
@ -1599,7 +1655,7 @@ begin
if kind = nkObjectTy then if kind = nkObjectTy then
addSon(result, a) addSon(result, a)
else else
parMessage(p, errInheritanceOnlyWithObjects); parMessage(p, errInheritanceOnlyWithNonFinalObjects);
end end
else addSon(result, nil); else addSon(result, nil);
skipComment(p, result); skipComment(p, result);
@ -1617,7 +1673,6 @@ begin
if p.tok.tokType = tkEquals then begin if p.tok.tokType = tkEquals then begin
getTok(p); optInd(p, result); getTok(p); optInd(p, result);
case p.tok.tokType of case p.tok.tokType of
tkRecord: a := parseRecordOrObject(p, nkRecordTy);
tkObject: a := parseRecordOrObject(p, nkObjectTy); tkObject: a := parseRecordOrObject(p, nkObjectTy);
tkEnum: a := parseEnum(p); tkEnum: a := parseEnum(p);
else a := parseTypeDesc(p); else a := parseTypeDesc(p);
@ -1671,6 +1726,7 @@ begin
tkIterator: result := parseRoutine(p, nkIteratorDef); tkIterator: result := parseRoutine(p, nkIteratorDef);
tkMacro: result := parseRoutine(p, nkMacroDef); tkMacro: result := parseRoutine(p, nkMacroDef);
tkTemplate: result := parseRoutine(p, nkTemplateDef); tkTemplate: result := parseRoutine(p, nkTemplateDef);
tkConverter: result := parseRoutine(p, nkConverterDef);
tkType: result := parseSection(p, nkTypeSection, parseTypeDef); tkType: result := parseSection(p, nkTypeSection, parseTypeDef);
tkConst: result := parseSection(p, nkConstSection, parseConstant); tkConst: result := parseSection(p, nkConstSection, parseConstant);
tkWhen: result := parseIfOrWhen(p, nkWhenStmt); tkWhen: result := parseIfOrWhen(p, nkWhenStmt);

View file

@ -26,11 +26,10 @@ begin
if (it.kind = nkExprColonExpr) and (it.sons[0].kind = nkIdent) then begin if (it.kind = nkExprColonExpr) and (it.sons[0].kind = nkIdent) then begin
case whichKeyword(it.sons[0].ident) of case whichKeyword(it.sons[0].ident) of
wAsmQuote: begin wAsmQuote: begin
case it.sons[1].kind of if it.sons[1].kind = nkCharLit then
nkCharLit, nkRCharLit: result := chr(int(it.sons[1].intVal)); result := chr(int(it.sons[1].intVal))
else invalidPragma(it) else invalidPragma(it)
end end
end
else else
invalidPragma(it) invalidPragma(it)
end end
@ -246,6 +245,8 @@ begin
sw := whichKeyword(n.sons[0].ident); sw := whichKeyword(n.sons[0].ident);
case sw of case sw of
wChecks: OnOff(c, n, checksOptions); wChecks: OnOff(c, n, checksOptions);
wObjChecks: OnOff(c, n, {@set}[optObjCheck]);
wFieldchecks: OnOff(c, n, {@set}[optFieldCheck]);
wRangechecks: OnOff(c, n, {@set}[optRangeCheck]); wRangechecks: OnOff(c, n, {@set}[optRangeCheck]);
wBoundchecks: OnOff(c, n, {@set}[optBoundsCheck]); wBoundchecks: OnOff(c, n, {@set}[optBoundsCheck]);
wOverflowchecks: OnOff(c, n, {@set}[optOverflowCheck]); wOverflowchecks: OnOff(c, n, {@set}[optOverflowCheck]);
@ -373,12 +374,12 @@ begin
end end
end; end;
procedure Breakpoint(c: PContext; n: PNode); procedure PragmaBreakpoint(c: PContext; n: PNode);
begin begin
{@discard} getOptionalStr(c, n, ''); {@discard} getOptionalStr(c, n, '');
end; end;
procedure Checkpoint(c: PContext; n: PNode); procedure PragmaCheckpoint(c: PContext; n: PNode);
// checkpoints can be used to debug the compiler; they are not documented // checkpoints can be used to debug the compiler; they are not documented
var var
info: TLineInfo; info: TLineInfo;
@ -427,7 +428,10 @@ begin
liMessage(it.info, errPowerOfTwoExpected); liMessage(it.info, errPowerOfTwoExpected);
end; end;
wNodecl: begin noVal(it); Include(sym.loc.Flags, lfNoDecl); end; wNodecl: begin noVal(it); Include(sym.loc.Flags, lfNoDecl); end;
wPure: begin noVal(it); include(sym.flags, sfPure); end; wPure: begin
noVal(it);
if sym <> nil then include(sym.flags, sfPure);
end;
wVolatile: begin noVal(it); Include(sym.flags, sfVolatile); end; wVolatile: begin noVal(it); Include(sym.flags, sfVolatile); end;
wRegister: begin noVal(it); include(sym.flags, sfRegister); end; wRegister: begin noVal(it); include(sym.flags, sfRegister); end;
wMagic: processMagic(c, it, sym); wMagic: processMagic(c, it, sym);
@ -444,7 +448,6 @@ begin
wNosideeffect: begin noVal(it); Include(sym.flags, sfNoSideEffect); end; wNosideeffect: begin noVal(it); Include(sym.flags, sfNoSideEffect); end;
wNoReturn: begin noVal(it); Include(sym.flags, sfNoReturn); end; wNoReturn: begin noVal(it); Include(sym.flags, sfNoReturn); end;
wDynLib: processDynLib(c, it, sym); wDynLib: processDynLib(c, it, sym);
wReturnsNew: begin noVal(it); Include(sym.flags, sfReturnsNew); end;
wCompilerProc: begin wCompilerProc: begin
noVal(it); // compilerproc may not get a string! noVal(it); // compilerproc may not get a string!
makeExternExport(sym, sym.name.s); makeExternExport(sym, sym.name.s);
@ -464,6 +467,14 @@ begin
noVal(it); noVal(it);
include(sym.typ.flags, tfVarargs); include(sym.typ.flags, tfVarargs);
end; end;
wFinal: begin
noVal(it);
include(sym.typ.flags, tfFinal);
end;
wTypeCheck: begin
noVal(it);
include(sym.flags, sfTypeCheck);
end;
// statement pragmas: // statement pragmas:
wHint: liMessage(it.info, hintUser, expectStrLit(c, it)); wHint: liMessage(it.info, hintUser, expectStrLit(c, it));
@ -478,6 +489,9 @@ begin
wCompile: processCompile(c, it); wCompile: processCompile(c, it);
wLink: processCommonLink(c, it, linkNormal); wLink: processCommonLink(c, it, linkNormal);
wLinkSys: processCommonLink(c, it, linkSys); wLinkSys: processCommonLink(c, it, linkSys);
wPassL: extccomp.addLinkOption(expectStrLit(c, it));
wPassC: extccomp.addCompileOption(expectStrLit(c, it));
// fixupSystem not even documented: // fixupSystem not even documented:
wFixupSystem: begin wFixupSystem: begin
if c.module = magicSys.SystemModule then if c.module = magicSys.SystemModule then
@ -485,12 +499,13 @@ begin
else else
invalidPragma(it) invalidPragma(it)
end; end;
wBreakpoint: Breakpoint(c, it); wBreakpoint: PragmaBreakpoint(c, it);
wCheckpoint: Checkpoint(c, it); wCheckpoint: PragmaCheckpoint(c, it);
wPush: begin processPush(c, n, i+1); break end; wPush: begin processPush(c, n, i+1); break end;
wPop: processPop(c, it); wPop: processPop(c, it);
wChecks, wRangechecks, wBoundchecks, wOverflowchecks, wNilchecks, wChecks, wObjChecks, wFieldChecks,
wRangechecks, wBoundchecks, wOverflowchecks, wNilchecks,
wAssertions, wWarnings, wHints, wLinedir, wStacktrace, wAssertions, wWarnings, wHints, wLinedir, wStacktrace,
wLinetrace, wOptimization, wByRef, wCallConv, wDebugger: wLinetrace, wOptimization, wByRef, wCallConv, wDebugger:
processOption(c, it); processOption(c, it);
@ -528,20 +543,28 @@ begin
wCppMethod, wDeprecated, wVarargs]); wCppMethod, wDeprecated, wVarargs]);
end; end;
procedure pragmaMacro(c: PContext; s: PSym; n: PNode);
begin
pragma(c, s, n, {@set}[FirstCallConv..LastCallConv,
wImportc, wExportc, wNostatic, wNodecl, wMagic, wNosideEffect,
wCompilerProc, wDeprecated, wTypeCheck]);
end;
procedure pragmaIterator(c: PContext; s: PSym; n: PNode); procedure pragmaIterator(c: PContext; s: PSym; n: PNode);
begin begin
pragma(c, s, n, {@set}[FirstCallConv..LastCallConv, pragma(c, s, n, {@set}[FirstCallConv..LastCallConv,
wImportc, wExportc, wNodecl, wMagic, wDeprecated]); wImportc, wExportc, wNodecl, wMagic, wDeprecated]);
end; end;
procedure pragmaStmt(c: PContext; n: PNode); procedure pragmaStmt(c: PContext; s: PSym; n: PNode);
begin begin
pragma(c, nil, n, {@set}[wChecks, wRangechecks, wBoundchecks, pragma(c, s, n, {@set}[wChecks, wObjChecks, wFieldChecks, wRangechecks,
wOverflowchecks, wNilchecks, wAssertions, wWarnings, wBoundchecks, wOverflowchecks, wNilchecks, wAssertions, wWarnings,
wHints, wLinedir, wStacktrace, wLinetrace, wOptimization, wHints, wLinedir, wStacktrace, wLinetrace, wOptimization,
wHint, wWarning, wError, wFatal, wDefine, wUndef, wHint, wWarning, wError, wFatal, wDefine, wUndef,
wCompile, wLink, wLinkSys, wCompile, wLink, wLinkSys, wPure,
wPush, wPop, wFixupSystem, wBreakpoint, wCheckpoint]); wPush, wPop, wFixupSystem, wBreakpoint, wCheckpoint,
wPassL, wPassC]);
end; end;
procedure pragmaLambda(c: PContext; s: PSym; n: PNode); procedure pragmaLambda(c: PContext; s: PSym; n: PNode);
@ -554,7 +577,7 @@ end;
procedure pragmaType(c: PContext; s: PSym; n: PNode); procedure pragmaType(c: PContext; s: PSym; n: PNode);
begin begin
pragma(c, s, n, {@set}[wImportc, wExportc, wDeprecated, wMagic, pragma(c, s, n, {@set}[wImportc, wExportc, wDeprecated, wMagic,
wNodecl, wPure, wHeader, wCompilerProc]); wNodecl, wPure, wHeader, wCompilerProc, wFinal]);
end; end;
procedure pragmaField(c: PContext; s: PSym; n: PNode); procedure pragmaField(c: PContext; s: PSym; n: PNode);

Some files were not shown because too many files have changed in this diff Show more