too many changes to list
This commit is contained in:
parent
916c25f9a7
commit
07d5a8085b
200 changed files with 24344 additions and 17809 deletions
|
|
@ -2,6 +2,10 @@
|
|||
# (c) 2008 Andreas Rumpf
|
||||
# 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 = """
|
||||
<div class="section" id="$sectionID">
|
||||
<h1><a class="toc-backref" href="#$sectionTitleID">$sectionTitle</a></h1>
|
||||
|
|
@ -52,10 +56,10 @@ $content
|
|||
"""
|
||||
|
||||
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"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<!-- This file is generated by Nimrod. -->
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<title>$title</title>
|
||||
|
|
@ -88,7 +92,7 @@ span.Command, span.Rule, span.Hyperlink, span.Label, span.Reference,
|
|||
span.Other {color: black}
|
||||
|
||||
div.navigation {
|
||||
float: left; width: 20em;
|
||||
float: left; width: 25em;
|
||||
margin: 0; padding: 0; /*
|
||||
border: 1px dashed gold; */
|
||||
outline: 3px outset #99ff99; //gold;
|
||||
|
|
@ -109,7 +113,7 @@ div.navigation ul li a:hover {
|
|||
}
|
||||
|
||||
div.content {
|
||||
margin-left: 20em;
|
||||
margin-left: 25em;
|
||||
padding: 0 1em;
|
||||
border: 1px dashed gold;
|
||||
min-width: 16em;
|
||||
|
|
@ -285,4 +289,3 @@ $content
|
|||
</html>
|
||||
"""
|
||||
|
||||
@write "used doctempl.cfg"
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
# Environment variables cannot be used in the options, however!
|
||||
|
||||
# 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"
|
||||
path="$lib/base"
|
||||
path="$lib/base/gtk"
|
||||
|
|
@ -17,13 +17,22 @@ path="$lib/base/cairo"
|
|||
path="$lib/base/x11"
|
||||
path="$lib/windows"
|
||||
path="$lib/posix"
|
||||
path="$lib/ecmas"
|
||||
path="$lib/extra"
|
||||
|
||||
@if release:
|
||||
checks:off
|
||||
stacktrace:off
|
||||
debugger:off
|
||||
line_dir:off
|
||||
@end
|
||||
|
||||
# additional defines:
|
||||
#define=""
|
||||
# additional options always passed to the compiler:
|
||||
force_build
|
||||
line_dir=off
|
||||
cfilecache=on
|
||||
|
||||
hint[LineTooLong]=off
|
||||
hint[XDeclaredButNotUsed]=off
|
||||
|
|
@ -40,7 +49,7 @@ hint[XDeclaredButNotUsed]=off
|
|||
|
||||
# Configuration for the LLVM GCC compiler:
|
||||
@if windows:
|
||||
llvm_gcc.path = r"dist\llvm-gcc4.2\bin"
|
||||
llvm_gcc.path = r"$nimrod\dist\llvm-gcc4.2\bin"
|
||||
@end
|
||||
llvm_gcc.options.debug = "-g"
|
||||
llvm_gcc.options.always = "-w"
|
||||
|
|
@ -59,14 +68,15 @@ bcc.options.size = "-O1 -6"
|
|||
|
||||
# Configuration for the Visual C/C++ compiler:
|
||||
@if vcc:
|
||||
@prepend_env path r"C:\Eigenes\compiler\vcc2005\Common7\IDE;"
|
||||
@prepend_env INCLUDE r"C:\Eigenes\compiler\vcc2005\VC\include;C:\Eigenes\compiler\vcc2005\VC\ATLMFC\INCLUDE;"
|
||||
@prepend_env LIB r"C:\Eigenes\compiler\vcc2005\VC\lib;C:\Eigenes\compiler\vcc2005\SDK\v2.0\Lib;"
|
||||
@prepend_env path r"C:\Programme\Microsoft Visual Studio 9.0\Common7\IDE;"
|
||||
@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:\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
|
||||
@if windows:
|
||||
vcc.path = r"C:\Eigenes\compiler\vcc2005\VC\bin"
|
||||
vcc.path = r"C:\Programme\Microsoft Visual Studio 9.0\VC\bin"
|
||||
@end
|
||||
vcc.options.debug = "/GZ /ZI"
|
||||
vcc.options.debug = "/RTC1 /ZI"
|
||||
vcc.options.always = "/nologo"
|
||||
vcc.options.speed = "/Ogityb2 /G7 /arch:SSE2"
|
||||
vcc.options.size = "/O1 /G7"
|
||||
|
|
@ -113,10 +123,11 @@ lcc.options.size = "-O -p6"
|
|||
|
||||
# Configuration for the Tiny C Compiler:
|
||||
@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
|
||||
tcc.options.debug = "-b"
|
||||
tcc.options.always = ""
|
||||
tcc.options.debug = ""
|
||||
tcc.options.speed = ""
|
||||
tcc.options.size = ""
|
||||
|
||||
|
|
@ -137,4 +148,9 @@ icc.options.always = "-w"
|
|||
icc.options.speed = "-O3 -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
|
||||
|
||||
|
|
|
|||
85
data/ast.yml
85
data/ast.yml
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
{
|
||||
'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
|
||||
'sfImportc', # symbol is external; imported
|
||||
'sfExportc', # symbol is exported (under a specified name)
|
||||
|
|
@ -26,7 +26,7 @@
|
|||
'sfMainModule', # module is the main module
|
||||
'sfSystemModule', # module is the system module
|
||||
'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
|
||||
'sfNoStatic', # symbol is used within an iterator (needed for codegen)
|
||||
# so it cannot be 'static' in the C code
|
||||
|
|
@ -56,32 +56,40 @@
|
|||
# is used to speed up semantic checking a bit
|
||||
'tfEnumHasWholes', # enum cannot be mapped into a range
|
||||
'tfVarargs', # procedure has C styled varargs
|
||||
'tfAssignable' # can the type be assigned to?
|
||||
'tfFinal' # is the object final?
|
||||
],
|
||||
|
||||
'TypeKind': [ # order is important!
|
||||
# Don't forget to change hti.nim if you make a change here
|
||||
'tyNone', 'tyBool', 'tyChar',
|
||||
'tyEmptySet', 'tyArrayConstr', 'tyNil', 'tyRecordConstr',
|
||||
'tyGeneric',
|
||||
'tyGenericInst', # instantiated generic type
|
||||
'tyGenericParam',
|
||||
'tyEnum', 'tyAnyEnum',
|
||||
'tyArray',
|
||||
'tyRecord',
|
||||
'tyObject',
|
||||
'tyTuple',
|
||||
'tySet',
|
||||
'tyRange',
|
||||
'tyPtr', 'tyRef',
|
||||
'tyVar',
|
||||
'tySequence',
|
||||
'tyProc',
|
||||
'tyPointer', 'tyOpenArray',
|
||||
'tyString', 'tyCString', 'tyForward',
|
||||
# numerical types:
|
||||
'tyInt', 'tyInt8', 'tyInt16', 'tyInt32', 'tyInt64', # signed integers
|
||||
'tyFloat', 'tyFloat32', 'tyFloat64', 'tyFloat128'
|
||||
'tyNone', 'tyBool', 'tyChar',
|
||||
'tyEmptySet', 'tyArrayConstr', 'tyNil',
|
||||
'tyGeneric',
|
||||
'tyGenericInst', # instantiated generic type
|
||||
'tyGenericParam',
|
||||
'tyEnum',
|
||||
'tyAnyEnum',
|
||||
'tyArray',
|
||||
'tyObject',
|
||||
'tyTuple',
|
||||
'tySet',
|
||||
'tyRange',
|
||||
'tyPtr', 'tyRef',
|
||||
'tyVar',
|
||||
'tySequence',
|
||||
'tyProc',
|
||||
'tyPointer', 'tyOpenArray',
|
||||
'tyString', 'tyCString', 'tyForward',
|
||||
# numerical types:
|
||||
'tyInt', 'tyInt8', 'tyInt16', 'tyInt32', 'tyInt64', # signed integers
|
||||
'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
|
||||
|
|
@ -97,7 +105,6 @@
|
|||
'nkType', # node is used for its typ field
|
||||
|
||||
'nkCharLit', # a character literal ''
|
||||
'nkRCharLit', # a raw character literal r''
|
||||
|
||||
'nkIntLit', # an integer literal
|
||||
'nkInt8Lit',
|
||||
|
|
@ -110,6 +117,8 @@
|
|||
'nkStrLit', # a string literal ""
|
||||
'nkRStrLit', # a raw string literal r""
|
||||
'nkTripleStrLit', # a triple string literal """
|
||||
'nkMetaNode', # difficult to explan; represents itself
|
||||
# (used for macros)
|
||||
'nkNilLit', # the nil literal
|
||||
# end of atoms
|
||||
'nkDotCall', # used to temporarily flag a nkCall node; this is used
|
||||
|
|
@ -126,7 +135,7 @@
|
|||
'nkInfix', # a call like (a + b)
|
||||
'nkPrefix', # a call like !a
|
||||
'nkPostfix', # something like a! (also used for visibility)
|
||||
'nkPar', # syntactic ()
|
||||
'nkPar', # syntactic (); may be a tuple constructor
|
||||
'nkCurly', # syntactic {}
|
||||
'nkBracket', # syntactic []
|
||||
'nkBracketExpr', # an expression like a[i..j, k]
|
||||
|
|
@ -142,14 +151,7 @@
|
|||
'nkAccQuoted', # `a` 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}
|
||||
'nkConstTableConstr', # a table constructor with only constant expressions
|
||||
'nkQualified', # describes a.b for qualified identifiers
|
||||
'nkHiddenStdConv', # an implicit standard type conversion
|
||||
'nkHiddenSubConv', # an implicit type conversion from a subtype
|
||||
|
|
@ -158,6 +160,16 @@
|
|||
'nkConv', # a type conversion
|
||||
'nkCast', # a type cast
|
||||
'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
|
||||
|
||||
'nkAsgn', # a = b
|
||||
|
|
@ -198,8 +210,6 @@
|
|||
'nkBreakStmt', # a break statement
|
||||
'nkContinueStmt', # a continue statement
|
||||
'nkBlockStmt', # a block statement
|
||||
'nkGotoStmt', # used by the transformation pass; first son is a sym
|
||||
# node containing a label
|
||||
'nkDiscardStmt', # a discard statement
|
||||
'nkStmtList', # a list of statements
|
||||
'nkImportStmt', # an import statement
|
||||
|
|
@ -218,8 +228,8 @@
|
|||
|
||||
# types as syntactic trees:
|
||||
'nkTypeOfExpr',
|
||||
'nkRecordTy',
|
||||
'nkObjectTy',
|
||||
'nkTupleTy',
|
||||
'nkRecList', # list of record/object parts
|
||||
'nkRecCase', # case section of record/object
|
||||
'nkRecWhen', # when section of record/object
|
||||
|
|
@ -228,7 +238,8 @@
|
|||
'nkVarTy',
|
||||
'nkProcTy',
|
||||
'nkEnumTy',
|
||||
'nkEnumFieldDef' # `ident = expr` in an enumeration
|
||||
'nkEnumFieldDef', # `ident = expr` in an enumeration
|
||||
'nkReturnToken', # token used for interpretation
|
||||
],
|
||||
|
||||
'SymKind': [
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ Command::
|
|||
compile compile project with default code generator (C)
|
||||
compile_to_c 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;
|
||||
with --run switch opens it with $BROWSER
|
||||
Arguments:
|
||||
|
|
@ -18,6 +19,8 @@ Options:
|
|||
--line_trace:on|off code generation for line trace ON|OFF
|
||||
--debugger:on|off turn Embedded Nimrod Debugger 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
|
||||
--bound_checks:on|off code generation for bound checks ON|OFF
|
||||
--overflow_checks:on|off code generation for over-/underflow checks ON|OFF
|
||||
|
|
|
|||
|
|
@ -10,9 +10,9 @@ macro method mod
|
|||
nil not notin
|
||||
object of or out
|
||||
proc ptr
|
||||
raise record ref return
|
||||
raise ref return
|
||||
shl shr
|
||||
template try type
|
||||
template try tuple type
|
||||
var
|
||||
when where while with without
|
||||
xor
|
||||
|
|
|
|||
|
|
@ -113,8 +113,13 @@
|
|||
'UnaryPlusF64',
|
||||
'UnaryMinusF64',
|
||||
'AbsF64',
|
||||
'Ze',
|
||||
'Ze64',
|
||||
'Ze8ToI',
|
||||
'Ze8ToI64',
|
||||
'Ze16ToI',
|
||||
'Ze16ToI64',
|
||||
'Ze32ToI64',
|
||||
'ZeIToI64',
|
||||
|
||||
'ToU8',
|
||||
'ToU16',
|
||||
'ToU32',
|
||||
|
|
@ -123,6 +128,14 @@
|
|||
'ToInt',
|
||||
'ToBiggestInt',
|
||||
|
||||
'CharToStr',
|
||||
'BoolToStr',
|
||||
'IntToStr', # $ for ints
|
||||
'Int64ToStr',
|
||||
'FloatToStr',
|
||||
'CStrToStr',
|
||||
'StrToStr',
|
||||
|
||||
# special ones:
|
||||
'And',
|
||||
'Or',
|
||||
|
|
@ -156,12 +169,12 @@
|
|||
'SetLengthSeq',
|
||||
'Assert',
|
||||
'Swap',
|
||||
'IsNil',
|
||||
|
||||
# magic type constructors:
|
||||
'Array',
|
||||
'OpenArray',
|
||||
'Range',
|
||||
'Tuple',
|
||||
'Set',
|
||||
'Seq',
|
||||
|
||||
|
|
@ -172,5 +185,38 @@
|
|||
'NimrodMajor',
|
||||
'NimrodMinor',
|
||||
'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'
|
||||
]
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
{'errInvalidToken': 'invalid token: $1'},
|
||||
{'errLineTooLong': 'line too long'},
|
||||
{'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'},
|
||||
{'errClosingBracketExpected': "closing ']' expected, but end of file reached"},
|
||||
{'errMissingFinalQuote': "missing final '"},
|
||||
|
|
@ -32,10 +32,6 @@
|
|||
{'errTokenExpected': "'$1' expected"},
|
||||
{'errStringAfterIncludeExpected': "string after 'include' expected"},
|
||||
{'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"},
|
||||
{'errNoneSpeedOrSizeExpected': "'none', 'speed' or 'size' expected"},
|
||||
{'errInvalidPragma': 'invalid pragma'},
|
||||
|
|
@ -157,13 +153,13 @@
|
|||
{'errSizeTooBig': "computing the type's size produced an overflow"},
|
||||
{'errSetTooBig': 'set is too large'},
|
||||
{'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'},
|
||||
{'errIllegalRecursionInTypeX': "illegal recursion in type '$1'"},
|
||||
{'errCannotInstantiateX': "cannot instantiate: '$1'"},
|
||||
{'errExprHasNoAddress': 'expression has no address'},
|
||||
{'errExprHasNoAddress': "expression has no address"},
|
||||
{'errVarForOutParamNeeded':
|
||||
'to an out parameter a variable needs to be passed'},
|
||||
"for a 'var' type a variable needs to be passed"},
|
||||
{'errPureTypeMismatch': 'type mismatch'},
|
||||
{'errTypeMismatch': 'type mismatch: got ('},
|
||||
{'errButExpected': 'but expected one of: '},
|
||||
|
|
@ -243,6 +239,20 @@
|
|||
{'errWhitespaceExpected': "whitespace expected, got '$1'"},
|
||||
{'errXisNoValidIndexFile': "'$1' is no valid index file"},
|
||||
{'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:
|
||||
{'errUser': '$1'},
|
||||
|
|
@ -276,6 +286,8 @@
|
|||
{'hintMo2FileInvalid': "mo2 file '$1' is invalid"},
|
||||
{'hintModuleHasChanged': "module '$1' has been changed"},
|
||||
{'hintCannotOpenMo2File': "mo2 file '$1' does not exist"},
|
||||
{'hintQuitCalled': "quit() called"},
|
||||
{'hintProcessing': "processing"},
|
||||
|
||||
# user hint message:
|
||||
{'hintUser': '$1'}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,9 @@
|
|||
|
||||
The documentation consists of several documents:
|
||||
|
||||
- | `First steps after installation <steps.html>`_
|
||||
| Read this after installation for a quick introduction.
|
||||
|
||||
- | `Nimrod manual <manual.html>`_
|
||||
| Read this to get to know the Nimrod programming system.
|
||||
|
||||
|
|
@ -23,4 +26,3 @@ The documentation consists of several documents:
|
|||
- | `Index <theindex.html>`_
|
||||
| The generated index. Often the quickest way to find the piece of
|
||||
information you need.
|
||||
|
||||
|
|
|
|||
|
|
@ -78,6 +78,7 @@ typeDescK ::= VAR typeDesc
|
|||
| REF typeDesc
|
||||
| PTR typeDesc
|
||||
| TYPE expr
|
||||
| TUPLE tupleDesc
|
||||
| PROC paramList [pragma]
|
||||
|
||||
typeDesc ::= typeDescK | primary
|
||||
|
|
@ -157,23 +158,23 @@ colonAndEquals ::= [COLON typeDesc] EQUALS expr
|
|||
constDecl ::= symbol ["*"] [pragma] colonAndEquals [COMMENT | IND COMMENT]
|
||||
| COMMENT
|
||||
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]
|
||||
|
||||
recordWhen ::= WHEN expr COLON [COMMENT] recordPart
|
||||
(ELIF expr COLON [COMMENT] recordPart)*
|
||||
[ELSE COLON [COMMENT] recordPart]
|
||||
recordCase ::= CASE expr COLON typeDesc [COMMENT]
|
||||
(OF sliceList COLON [COMMENT] recordPart)*
|
||||
[ELSE COLON [COMMENT] recordPart]
|
||||
objectWhen ::= WHEN expr COLON [COMMENT] objectPart
|
||||
(ELIF expr COLON [COMMENT] objectPart)*
|
||||
[ELSE COLON [COMMENT] objectPart]
|
||||
objectCase ::= CASE expr COLON typeDesc [COMMENT]
|
||||
(OF sliceList COLON [COMMENT] objectPart)*
|
||||
[ELSE COLON [COMMENT] objectPart]
|
||||
|
||||
recordPart ::= recordWhen | recordCase | recordIdentPart
|
||||
| indPush recordPart (SAD recordPart)* DED
|
||||
recordDef ::= RECORD [pragma] recordPart
|
||||
objectPart ::= objectWhen | objectCase | objectIdentPart
|
||||
| indPush objectPart (SAD objectPart)* DED
|
||||
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])+
|
||||
|
||||
typeDecl ::= COMMENT
|
||||
|
|
|
|||
97
doc/lib.txt
97
doc/lib.txt
|
|
@ -13,36 +13,119 @@ Advanced libraries are in the ``lib/base`` directory.
|
|||
Basic libraries
|
||||
===============
|
||||
|
||||
* `System <system.html>`_
|
||||
* `system <system.html>`_
|
||||
Basic procs and operators that every program needs. It also provides IO
|
||||
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
|
||||
magic to work.
|
||||
|
||||
* `Strutils <strutils.html>`_
|
||||
* `strutils <strutils.html>`_
|
||||
This module contains common string handling operations like converting a
|
||||
string into uppercase, splitting a string into substrings, searching for
|
||||
substrings, replacing substrings.
|
||||
|
||||
* `OS <os.html>`_
|
||||
* `os <os.html>`_
|
||||
Basic operating system facilities like retrieving environment variables,
|
||||
reading command line arguments, working with directories, running shell
|
||||
commands, etc. This module is -- like any other basic library --
|
||||
platform independant.
|
||||
|
||||
* `Math <math.html>`_
|
||||
* `math <math.html>`_
|
||||
Mathematical operations like cosine, square root.
|
||||
|
||||
* `Complex <complex.html>`_
|
||||
* `complex <complex.html>`_
|
||||
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.
|
||||
|
||||
* `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
|
||||
=================
|
||||
|
||||
* `Regexprs <regexprs.html>`_
|
||||
* `regexprs <regexprs.html>`_
|
||||
This module contains procedures and operators for handling regular
|
||||
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.
|
||||
|
|
|
|||
|
|
@ -593,7 +593,7 @@ Structured types
|
|||
~~~~~~~~~~~~~~~~
|
||||
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,
|
||||
records, objects and sets belong to the structured types.
|
||||
tuples, objects and sets belong to the structured 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.
|
||||
|
||||
|
||||
Tuples, record and object types
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
A variable of a `record`:idx: or `object`:idx: type is a heterogenous storage
|
||||
Tuples and object types
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
A variable of a `tuple`:idx: or `object`:idx: type is a heterogenous storage
|
||||
container.
|
||||
A record or object defines various named *fields* of a type. The assignment
|
||||
operator for records and objects always copies the whole record/object. The
|
||||
constructor ``()`` can be used to initialize records/objects. A field may
|
||||
be given a default value. Fields with default values do not have to be listed
|
||||
in a record construction, all other fields have to be listed.
|
||||
A tuple or object defines various named *fields* of a type. A tuple defines an
|
||||
*order* of the fields additionally. Tuples are meant for heterogenous storage
|
||||
types with no overhead and few abstraction possibilities. The constructor ``()``
|
||||
can be used to construct tuples. The order of the fields in the constructor
|
||||
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
|
||||
|
||||
type
|
||||
TPerson = record # type representing a person
|
||||
name: string # a person consists of a name
|
||||
age: int = 30 # and an age which default value is 30
|
||||
|
||||
TPerson = tuple[name: string, age: int] # type representing a person
|
||||
# a person consists of a name
|
||||
# and an age
|
||||
var
|
||||
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
|
||||
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 have access to their type at runtime, so that the ``is`` operator
|
||||
can be used to determine the object's type. Assignment from an object to its
|
||||
parents' object leads to a static or runtime error (the
|
||||
`EInvalidObjectAssignment`:idx: exception is raised).
|
||||
Objects provide many features that tuples do not. Object provide inheritance
|
||||
and information hiding. Objects have access to their type at runtime, so that
|
||||
the ``is`` operator can be used to determine the object's type.
|
||||
|
||||
.. code-block:: nimrod
|
||||
|
||||
type
|
||||
TPerson = object
|
||||
name: string
|
||||
age: int
|
||||
name*: string # the * means that `name` is accessible from the outside
|
||||
age: int # no * means that the field is hidden
|
||||
|
||||
TStudent = object of TPerson # a student is a person
|
||||
id: int # with an id field
|
||||
|
|
@ -681,10 +686,11 @@ parents' object leads to a static or runtime error (the
|
|||
var
|
||||
student: TStudent
|
||||
person: TPerson
|
||||
student = (name: "Peter", age: 89, id: 3)
|
||||
person = (name: "Mary", age: 17)
|
||||
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
|
||||
|
|
@ -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.
|
||||
Thus the usage of ``addr`` is an *unsafe* feature.
|
||||
|
||||
The ``.`` (access a record field operator) and ``[]`` (array/string/sequence
|
||||
index operator) operators perform implicit dereferencing operations for
|
||||
reference types:
|
||||
The ``.`` (access a tuple/object field operator)
|
||||
and ``[]`` (array/string/sequence index operator) operators perform implicit
|
||||
dereferencing operations for reference types:
|
||||
|
||||
.. code-block:: nimrod
|
||||
|
||||
type
|
||||
PNode = ref TNode
|
||||
TNode = record
|
||||
TNode = object
|
||||
le, ri: PNode
|
||||
data: int
|
||||
|
||||
|
|
@ -938,8 +944,8 @@ ref or pointer type nil
|
|||
procedural type nil
|
||||
sequence nil
|
||||
string nil (**not** "")
|
||||
tuple[A, B, ...] (default(A), default(B), ...)
|
||||
(analogous for objects and records)
|
||||
tuple[x: A, y: B, ...] (default(A), default(B), ...)
|
||||
(analogous for objects)
|
||||
array[0..., T] [default(T), ...]
|
||||
range[T] default(T); this may be out of the valid range
|
||||
T = enum cast[T](0); this may be an invalid value
|
||||
|
|
@ -1065,7 +1071,7 @@ exceptions:
|
|||
|
||||
The ``when`` statement enables conditional compilation techniques. As
|
||||
a special syntatic extension, the ``when`` construct is also available
|
||||
within ``record`` or ``object`` definitions.
|
||||
within ``object`` definitions.
|
||||
|
||||
|
||||
Raise statement
|
||||
|
|
@ -1117,7 +1123,7 @@ Example:
|
|||
echo("sum: " & $(parseInt(a) + parseInt(b)))
|
||||
except EOverflow:
|
||||
echo("overflow!")
|
||||
except EValue:
|
||||
except EInvalidValue:
|
||||
echo("could not convert string to integer")
|
||||
except EIO:
|
||||
echo("IO error!")
|
||||
|
|
@ -1411,7 +1417,7 @@ Type sections
|
|||
|
||||
Syntax::
|
||||
|
||||
typeDef ::= typeDesc | recordDef | objectDef | enumDef
|
||||
typeDef ::= typeDesc | objectDef | enumDef
|
||||
genericParams ::= BRACKET_LE (symbol [EQUALS typeDesc] )* BRACKET_RI
|
||||
|
||||
typeDecl ::= TYPE
|
||||
|
|
@ -1425,11 +1431,11 @@ Example:
|
|||
.. code-block:: nimrod
|
||||
type # example demonstrates mutually recursive types
|
||||
PNode = ref TNode # a traced pointer to a TNode
|
||||
TNode = record
|
||||
TNode = object
|
||||
le, ri: PNode # left and right subtrees
|
||||
sym: ref TSym # leaves contain a reference to a TSym
|
||||
|
||||
TSym = record # a symbol
|
||||
TSym = object # a symbol
|
||||
name: string # the symbol's name
|
||||
line: int # the line the symbol was declared in
|
||||
code: PNode # the symbol's abstract syntax tree
|
||||
|
|
@ -1447,7 +1453,7 @@ Example:
|
|||
|
||||
.. code-block:: nimrod
|
||||
type
|
||||
TBinaryTree[T] = record # TBinaryTree is a generic type with
|
||||
TBinaryTree[T] = object # TBinaryTree is a generic type with
|
||||
# with generic param ``T``
|
||||
le, ri: ref TBinaryTree[T] # left and right subtrees; may be nil
|
||||
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
|
||||
`separate compilation`:idx:. A module may gain access to symbols of another
|
||||
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:
|
||||
|
||||
|
|
@ -1587,13 +1594,13 @@ identifier cannot be redefined in the same block, except if valid for
|
|||
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:
|
||||
|
||||
* To the end of the record definition
|
||||
* Field designators of a variable of the given record type.
|
||||
* To the end of the tuple/object definition
|
||||
* Field designators of a variable of the given tuple/object type.
|
||||
* In all descendent types of the object type.
|
||||
|
||||
Module scope
|
||||
|
|
|
|||
|
|
@ -86,8 +86,8 @@ the C code. Thus it makes the following possible, for example:
|
|||
|
||||
.. code-block:: Nimrod
|
||||
var
|
||||
EOF {.import: "EOF", no_decl.}: cint # pretend EOF was a variable, as
|
||||
# Nimrod does not know its value
|
||||
EOF {.importc: "EOF", no_decl.}: cint # pretend EOF was a variable, as
|
||||
# Nimrod does not know its value
|
||||
|
||||
Varargs Pragma
|
||||
~~~~~~~~~~~~~~
|
||||
|
|
@ -110,7 +110,7 @@ declared but also that it leads to the inclusion of a given header file:
|
|||
|
||||
.. code-block:: Nimrod
|
||||
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
|
||||
|
||||
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
|
||||
if several different string constants are used. This is likely to be more
|
||||
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.
|
||||
|
|
|
|||
220
doc/posix.txt
220
doc/posix.txt
|
|
@ -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
|
||||
|
||||
|
||||
|
|
@ -4,8 +4,4 @@ Nimrod's documenation system
|
|||
|
||||
This folder contains Nimrod's documentation. The documentation
|
||||
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!
|
||||
|
||||
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.
|
||||
like ASCII and can be converted to HTML automatically!
|
||||
|
|
|
|||
|
|
@ -272,25 +272,3 @@ end of the subject string, whatever options are set.
|
|||
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
|
||||
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 * )
|
||||
|
|
|
|||
3856
doc/theindex.txt
3856
doc/theindex.txt
File diff suppressed because it is too large
Load diff
|
|
@ -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::
|
||||
|
||||
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
|
||||
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
|
||||
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
|
||||
type
|
||||
TMyRecord = record
|
||||
TMyRecord = object
|
||||
x, y: int
|
||||
|
||||
|
||||
|
|
|
|||
344
ide/main.nim
344
ide/main.nim
|
|
@ -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()
|
||||
|
||||
const
|
||||
GuiTemplate = "/media/hda4/nimrod/ide/nimide.glade"
|
||||
|
||||
type
|
||||
TMyTextEditor = record
|
||||
TTab = object of TObject
|
||||
textview: PGtkTextView
|
||||
filename: string
|
||||
untitled: bool
|
||||
|
||||
TMyTextEditor = object of TObject
|
||||
window: PGtkWindow
|
||||
statusbar: PGtkStatusBar
|
||||
textview: PGtkTextview
|
||||
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:
|
||||
result = $gtk_file_chooser_get_filename(chooser)
|
||||
else:
|
||||
result = ""
|
||||
gtk_widget_destroy(chooser)
|
||||
|
||||
|
||||
proc get_save_filename(e: TMyTextEditor): string =
|
||||
var
|
||||
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 on_about_menu_item_activate(menuItem: PGtkMenuItem,
|
||||
e: var TMyTextEditor) {.cdecl.} =
|
||||
gtk_show_about_dialog(e.window,
|
||||
"comments", "A fast and leight-weight IDE for Nimrod",
|
||||
"copyright", "Copyright \xc2\xa9 2008 Andreas Rumpf",
|
||||
"version", "0.1",
|
||||
"website", "http://nimrod.ethexor.com",
|
||||
"program-name", "Nimrod IDE",
|
||||
nil)
|
||||
|
||||
proc load_file(e: var TMyTextEditor, filename: string) =
|
||||
var
|
||||
|
|
@ -119,6 +94,21 @@ proc write_file(e: var TMyTextEditor, filename: string) =
|
|||
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) =
|
||||
var
|
||||
builder: PGladeXML
|
||||
|
|
@ -136,7 +126,7 @@ proc initApp(e: var TMyTextEditor) =
|
|||
|
||||
# connect the signal handlers:
|
||||
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")
|
||||
gtk_widget_modify_font(e.textview, font_desc)
|
||||
|
|
@ -162,208 +152,82 @@ proc main() =
|
|||
main()
|
||||
|
||||
|
||||
proc reset_default_status(e: var TMyTextEditor)
|
||||
gchar *file;
|
||||
gchar *status;
|
||||
|
||||
if e.filename == "":
|
||||
file = g_strdup("(UNTITLED)")
|
||||
else:
|
||||
file = g_path_get_basename(editor->filename)
|
||||
proc on_window_delete_event(widget: PGtkWidget, event: PGdkEvent,
|
||||
e: TMyTextEditor): bool {.cdecl.} =
|
||||
if check_for_save(editor):
|
||||
on_save_menu_item_activate(nil, editor)
|
||||
result = false
|
||||
|
||||
status = g_strdup_printf("File: %s", file)
|
||||
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;
|
||||
proc on_new_menu_item_activate(GtkMenuItem *menuitem, TutorialTextEditor *editor)
|
||||
GtkTextBuffer *buffer;
|
||||
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (editor->text_view));
|
||||
if (gtk_text_buffer_get_modified (buffer) == TRUE)
|
||||
|
||||
if check_for_save(editor):
|
||||
on_save_menu_item_activate(nil, editor)
|
||||
|
||||
/* clear editor for a new file */
|
||||
editor->filename = nil;
|
||||
buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW (editor->text_view));
|
||||
gtk_text_buffer_set_text(buffer, "", -1);
|
||||
gtk_text_buffer_set_modified(buffer, FALSE);
|
||||
|
||||
reset_default_status(editor);
|
||||
|
||||
|
||||
proc on_open_menu_item_activate(menuItem: PGtkMenuItem,
|
||||
TutorialTextEditor *editor) =
|
||||
gchar *filename;
|
||||
|
||||
if check_for_save(editor):
|
||||
on_save_menu_item_activate(nil, editor)
|
||||
filename = get_open_filename(editor)
|
||||
if filename != nil: load_file(editor, filename)
|
||||
|
||||
proc on_save_menu_item_activate(menuItem: PGtkMenuItem, TutorialTextEditor *editor) =
|
||||
gchar *filename;
|
||||
if (editor->filename == nil)
|
||||
{
|
||||
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);
|
||||
filename = get_save_filename(editor);
|
||||
if (filename != nil) write_file(editor, filename);
|
||||
}
|
||||
return ret;
|
||||
else write_file(editor, nil);
|
||||
|
||||
proc on_save_as_menu_item_activate(GtkMenuItem *menuitem,
|
||||
TutorialTextEditor *editor) =
|
||||
gchar *filename;
|
||||
|
||||
filename = get_save_filename(editor)
|
||||
if filename != nil: write_file(editor, filename)
|
||||
|
||||
proc on_quit_menu_item_activate(GtkMenuItem *menuitem, TutorialTextEditor *editor)
|
||||
if check_for_save(editor):
|
||||
on_save_menu_item_activate(nil, editor)
|
||||
gtk_main_quit()
|
||||
|
||||
proc on_cut_menu_item_activate(GtkMenuItem *menuitem, TutorialTextEditor *editor) =
|
||||
GtkTextBuffer *buffer;
|
||||
GtkClipboard *clipboard;
|
||||
|
||||
clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
|
||||
buffer = gtk_text_view_get_buffer(editor->text_view)
|
||||
gtk_text_buffer_cut_clipboard(buffer, clipboard, TRUE)
|
||||
|
||||
proc on_copy_menu_item_activate(GtkMenuItem *menuitem, TutorialTextEditor *editor) =
|
||||
GtkTextBuffer *buffer;
|
||||
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)
|
||||
|
||||
|
||||
/*
|
||||
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 */
|
||||
}
|
||||
proc on_paste_menu_item_activate(GtkMenuItem *menuitem, TutorialTextEditor *editor)
|
||||
GtkTextBuffer *buffer;
|
||||
GtkClipboard *clipboard;
|
||||
clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD)
|
||||
buffer = gtk_text_view_get_buffer(editor->text_view)
|
||||
gtk_text_buffer_paste_clipboard(buffer, clipboard, nil, TRUE)
|
||||
|
||||
/*
|
||||
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;
|
||||
|
||||
if (check_for_save (editor) == TRUE)
|
||||
{
|
||||
on_save_menu_item_activate (NULL, editor);
|
||||
}
|
||||
|
||||
/* clear editor for a new file */
|
||||
editor->filename = NULL;
|
||||
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (editor->text_view));
|
||||
gtk_text_buffer_set_text (buffer, "", -1);
|
||||
gtk_text_buffer_set_modified (buffer, FALSE);
|
||||
|
||||
reset_default_status (editor);
|
||||
}
|
||||
|
||||
/*
|
||||
Called when the user clicks the 'Open' menu. We need to prompt for save if the
|
||||
file has been modified, allow the user to choose a file to open, and then call
|
||||
load_file() on that file.
|
||||
*/
|
||||
void on_open_menu_item_activate (GtkMenuItem *menuitem, TutorialTextEditor *editor)
|
||||
{
|
||||
gchar *filename;
|
||||
|
||||
if (check_for_save (editor) == TRUE)
|
||||
{
|
||||
on_save_menu_item_activate (NULL, editor);
|
||||
}
|
||||
|
||||
filename = get_open_filename (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;
|
||||
|
||||
if (editor->filename == NULL)
|
||||
{
|
||||
filename = get_save_filename (editor);
|
||||
if (filename != NULL) write_file (editor, filename);
|
||||
}
|
||||
else write_file (editor, NULL);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
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;
|
||||
|
||||
filename = get_save_filename (editor);
|
||||
if (filename != NULL) write_file (editor, filename);
|
||||
}
|
||||
|
||||
/*
|
||||
Called when the user clicks the 'Quit' menu. We need to prompt for save if the
|
||||
file has been modified and then break out of the GTK+ main loop.
|
||||
*/
|
||||
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();
|
||||
}
|
||||
|
||||
/*
|
||||
Called when the user clicks the 'Cut' menu.
|
||||
*/
|
||||
void on_cut_menu_item_activate (GtkMenuItem *menuitem, TutorialTextEditor *editor)
|
||||
{
|
||||
GtkTextBuffer *buffer;
|
||||
GtkClipboard *clipboard;
|
||||
|
||||
clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
|
||||
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (editor->text_view));
|
||||
gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
Called when the user clicks the 'Copy' menu.
|
||||
*/
|
||||
void on_copy_menu_item_activate (GtkMenuItem *menuitem, TutorialTextEditor *editor)
|
||||
{
|
||||
GtkTextBuffer *buffer;
|
||||
GtkClipboard *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);
|
||||
}
|
||||
|
||||
/*
|
||||
Called when the user clicks the 'Paste' menu.
|
||||
*/
|
||||
void on_paste_menu_item_activate (GtkMenuItem *menuitem, TutorialTextEditor *editor)
|
||||
{
|
||||
GtkTextBuffer *buffer;
|
||||
GtkClipboard *clipboard;
|
||||
clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
|
||||
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (editor->text_view));
|
||||
gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
Called when the user clicks the 'Delete' menu.
|
||||
*/
|
||||
void on_delete_menu_item_activate (GtkMenuItem *menuitem, TutorialTextEditor *editor)
|
||||
{
|
||||
GtkTextBuffer *buffer;
|
||||
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (editor->text_view));
|
||||
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)
|
||||
}
|
||||
proc on_delete_menu_item_activate(GtkMenuItem *menuitem, TutorialTextEditor *editor)
|
||||
GtkTextBuffer *buffer;
|
||||
buffer = gtk_text_view_get_buffer(editor->text_view);
|
||||
gtk_text_buffer_delete_selection(buffer, FALSE, TRUE);
|
||||
|
|
|
|||
395
ide/nimide.glade
395
ide/nimide.glade
|
|
@ -1,175 +1,224 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
|
||||
<!--Generated with glade3 3.4.2 on Sat Jun 21 14:12:42 2008 -->
|
||||
<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
|
||||
<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">
|
||||
|
||||
<glade-interface>
|
||||
<widget class="GtkWindow" id="window">
|
||||
<property name="extension_events">GDK_EXTENSION_EVENTS_ALL</property>
|
||||
<signal name="destroy" handler="on_window_destroy" object="destroy"/>
|
||||
<child>
|
||||
<widget class="GtkVBox" id="mainvbox">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<widget class="GtkMenuBar" id="menubar">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<widget class="GtkMenuItem" id="menuitem1">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">_Datei</property>
|
||||
<property name="use_underline">True</property>
|
||||
<child>
|
||||
<widget class="GtkMenu" id="menu1">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="new_menu_item">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">gtk-new</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="open_menu_item">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">gtk-open</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="save_menu_item">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">gtk-save</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="save_as_menu_item">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">gtk-save-as</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkSeparatorMenuItem" id="separatormenuitem1">
|
||||
<property name="visible">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="quit_menu_item">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">gtk-quit</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkMenuItem" id="menuitem2">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">_Bearbeiten</property>
|
||||
<property name="use_underline">True</property>
|
||||
<child>
|
||||
<widget class="GtkMenu" id="menu2">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="cut_menu_item">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">gtk-cut</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="copy_menu_item">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">gtk-copy</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="paste_menu_item">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">gtk-paste</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="delete_menu_item">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">gtk-delete</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkMenuItem" id="menuitem4">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">_Hilfe</property>
|
||||
<property name="use_underline">True</property>
|
||||
<child>
|
||||
<widget class="GtkMenu" id="menu3">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="about_menu_item">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">gtk-about</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkScrolledWindow" id="scrolledwindow">
|
||||
<property name="visible">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="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
|
||||
<property name="shadow_type">GTK_SHADOW_ETCHED_IN</property>
|
||||
<child>
|
||||
<widget class="GtkTextView" id="textview">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="left_margin">2</property>
|
||||
<property name="right_margin">2</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkStatusbar" id="statusbar">
|
||||
<property name="visible">True</property>
|
||||
<property name="spacing">2</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
|
||||
<widget class="GtkWindow" id="window">
|
||||
<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"/>
|
||||
|
||||
<child>
|
||||
<widget class="GtkVBox" id="mainvbox">
|
||||
<property name="width_request">600</property>
|
||||
<property name="height_request">400</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="homogeneous">False</property>
|
||||
<property name="spacing">0</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkMenuBar" id="menubar">
|
||||
<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>
|
||||
<widget class="GtkMenuItem" id="menuitem1">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">_Datei</property>
|
||||
<property name="use_underline">True</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkMenu" id="menu1">
|
||||
<property name="visible">True</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="new_menu_item">
|
||||
<property name="visible">True</property>
|
||||
<property name="label">gtk-new</property>
|
||||
<property name="use_stock">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="open_menu_item">
|
||||
<property name="visible">True</property>
|
||||
<property name="label">gtk-open</property>
|
||||
<property name="use_stock">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="save_menu_item">
|
||||
<property name="visible">True</property>
|
||||
<property name="label">gtk-save</property>
|
||||
<property name="use_stock">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="save_as_menu_item">
|
||||
<property name="visible">True</property>
|
||||
<property name="label">gtk-save-as</property>
|
||||
<property name="use_stock">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkSeparatorMenuItem" id="separatormenuitem1">
|
||||
<property name="visible">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="quit_menu_item">
|
||||
<property name="visible">True</property>
|
||||
<property name="label">gtk-quit</property>
|
||||
<property name="use_stock">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkMenuItem" id="menuitem2">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">_Bearbeiten</property>
|
||||
<property name="use_underline">True</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkMenu" id="menu2">
|
||||
<property name="visible">True</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="cut_menu_item">
|
||||
<property name="visible">True</property>
|
||||
<property name="label">gtk-cut</property>
|
||||
<property name="use_stock">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="copy_menu_item">
|
||||
<property name="visible">True</property>
|
||||
<property name="label">gtk-copy</property>
|
||||
<property name="use_stock">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="paste_menu_item">
|
||||
<property name="visible">True</property>
|
||||
<property name="label">gtk-paste</property>
|
||||
<property name="use_stock">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="delete_menu_item">
|
||||
<property name="visible">True</property>
|
||||
<property name="label">gtk-delete</property>
|
||||
<property name="use_stock">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkMenuItem" id="menuitem4">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">_Hilfe</property>
|
||||
<property name="use_underline">True</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkMenu" id="menu3">
|
||||
<property name="visible">True</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="about_menu_item">
|
||||
<property name="visible">True</property>
|
||||
<property name="label">gtk-about</property>
|
||||
<property name="use_stock">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkScrolledWindow" id="scrolledwindow">
|
||||
<property name="border_width">1</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
|
||||
<property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
|
||||
<property name="shadow_type">GTK_SHADOW_ETCHED_IN</property>
|
||||
<property name="window_placement">GTK_CORNER_TOP_LEFT</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkTextView" id="textview">
|
||||
<property name="visible">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="right_margin">2</property>
|
||||
<property name="indent">0</property>
|
||||
<property name="text" translatable="yes"></property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkStatusbar" id="statusbar">
|
||||
<property name="visible">True</property>
|
||||
<property name="has_resize_grip">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
|
||||
</glade-interface>
|
||||
|
|
|
|||
67
install.txt
67
install.txt
|
|
@ -1,38 +1,17 @@
|
|||
Installation
|
||||
============
|
||||
|
||||
Installation on Windows - the easy way
|
||||
--------------------------------------
|
||||
|
||||
Install Nimrod by downloading the appropriate .zip file and extracting it to a
|
||||
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
|
||||
--------------------
|
||||
Installation on Linux/UNIX
|
||||
--------------------------
|
||||
|
||||
Note:
|
||||
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
|
||||
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
|
||||
install one.
|
||||
distributions do not ship with a GCC compiler preinstalled - then you have to
|
||||
install it.
|
||||
|
||||
After you have made sure that a C compiler is available, install Nimrod
|
||||
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
|
||||
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``
|
||||
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
|
||||
|
||||
|
|
@ -55,35 +34,43 @@ Installation on the Macintosh
|
|||
-----------------------------
|
||||
|
||||
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
|
||||
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
|
||||
--------------------------------------
|
||||
|
||||
Windows does not ship with a C compiler; you have to install one. The
|
||||
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++
|
||||
| http://msdn.microsoft.com/visualc
|
||||
| (You may need the SDK too - but not the full one: Essential are only
|
||||
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!)
|
||||
| http://www.mingw.org/download.shtml
|
||||
- | LLVM with GNU C/C++ frontend
|
||||
| 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
|
||||
- | Lcc-win32
|
||||
- | Lcc-win32 (bootstrapping does not work with LCC!)
|
||||
| http://www.cs.virginia.edu/~lcc-win32
|
||||
|
||||
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
|
||||
directory of your choice. The Nimrod Compiler will stay in this
|
||||
directory; do not use a temporary one! Then adapt the ``config/nimrod.cfg``
|
||||
file appropriately. Choose your C compiler and press ``OK``. You should
|
||||
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.
|
||||
file appropriately. You should add Nimrod to your ``$PATH``.
|
||||
|
|
|
|||
24
kochmod.py
24
kochmod.py
|
|
@ -2,7 +2,7 @@
|
|||
# For further documentation see koch.txt or koch.html.
|
||||
# (c) 2007 Andreas Rumpf
|
||||
|
||||
VERSION = "1.0.3"
|
||||
VERSION = "1.0.4"
|
||||
|
||||
import os, os.path, inspect, re, shutil, glob, cPickle, zlib, string, \
|
||||
getopt, sys
|
||||
|
|
@ -18,6 +18,25 @@ _FINGERPRINTS_FILE = "koch.dat"
|
|||
# has changed. This works reliably, which cannot be said from just taking
|
||||
# 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 ------------------------------------------------
|
||||
|
||||
# We support the following C compilers:
|
||||
|
|
@ -185,6 +204,9 @@ def Subs(frmt, **substitution):
|
|||
else:
|
||||
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 = _baseDir
|
||||
|
||||
|
|
|
|||
|
|
@ -17,9 +17,9 @@ proc c_memcpy(a, b: CString, size: cint) {.nodecl, importc: "memcpy".}
|
|||
proc c_strlen(a: CString): cint {.nodecl, importc: "strlen".}
|
||||
|
||||
type
|
||||
C_TextFile {.importc: "FILE", nodecl.} = record # empty record for
|
||||
# data hiding
|
||||
C_BinaryFile {.importc: "FILE", nodecl.} = record
|
||||
C_TextFile {.importc: "FILE", nodecl, final.} = object # empty record for
|
||||
# data hiding
|
||||
C_BinaryFile {.importc: "FILE", nodecl, final.} = object
|
||||
C_TextFileStar = ptr CTextFile
|
||||
C_BinaryFileStar = ptr CBinaryFile
|
||||
|
||||
|
|
|
|||
|
|
@ -18,13 +18,13 @@ proc raiseDivByZero {.exportc: "raiseDivByZero".} =
|
|||
raise newException(EDivByZero, "divison by zero")
|
||||
|
||||
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):
|
||||
return result
|
||||
raiseOverflow()
|
||||
|
||||
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):
|
||||
return result
|
||||
raiseOverflow()
|
||||
|
|
@ -74,7 +74,7 @@ proc modInt64(a, b: int64): int64 {.compilerProc, inline.} =
|
|||
proc mulInt64(a, b: int64): int64 {.compilerproc.} =
|
||||
var
|
||||
resAsFloat, floatProd: float64
|
||||
result = a * b
|
||||
result = a *% b
|
||||
floatProd = float64(a) # conversion
|
||||
floatProd = floatProd * float64(b)
|
||||
resAsFloat = float64(result)
|
||||
|
|
@ -276,13 +276,13 @@ else:
|
|||
# Platform independant versions of the above (slower!)
|
||||
|
||||
proc addInt(a, b: int): int =
|
||||
result = a + b
|
||||
result = a +% b
|
||||
if (result xor a) >= 0 or (result xor b) >= 0:
|
||||
return result
|
||||
raiseOverflow()
|
||||
|
||||
proc subInt(a, b: int): int =
|
||||
result = a - b
|
||||
result = a -% b
|
||||
if (result xor a) >= 0 or (result xor not b) >= 0:
|
||||
return result
|
||||
raiseOverflow()
|
||||
|
|
@ -327,7 +327,7 @@ else:
|
|||
var
|
||||
resAsFloat, floatProd: float
|
||||
|
||||
result = a * b
|
||||
result = a *% b
|
||||
floatProd = toFloat(a) * toFloat(b)
|
||||
resAsFloat = toFloat(result)
|
||||
|
||||
|
|
|
|||
|
|
@ -55,7 +55,8 @@ proc genericAssign(dest, src: Pointer, mt: PNimType) =
|
|||
var dstseq = cast[PGenericSeq](dst)
|
||||
dstseq.len = 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)
|
||||
of tyArray, tyArrayConstr:
|
||||
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
|
||||
|
||||
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)
|
||||
|
||||
proc genericAssignOpenArray(dest, src: pointer, len: int,
|
||||
|
|
@ -110,7 +112,7 @@ proc objectInit(dest: Pointer, typ: PNimType) =
|
|||
var pint = cast[ptr PNimType](dest)
|
||||
pint^ = typ
|
||||
objectInitAux(dest, typ.node)
|
||||
of tyRecord:
|
||||
of tyTuple, tyPureObject:
|
||||
objectInitAux(dest, typ.node)
|
||||
of tyArray, tyArrayConstr:
|
||||
for i in 0..(typ.size div typ.base.size)-1:
|
||||
|
|
|
|||
|
|
@ -149,13 +149,13 @@ type
|
|||
cdecl.}
|
||||
cairo_read_func_t* = proc (closure: Pointer, data: PByte, len: int32): cairo_status_t{.
|
||||
cdecl.}
|
||||
cairo_t* = record #OPAQUE
|
||||
cairo_surface_t* = record #OPAQUE
|
||||
cairo_pattern_t* = record #OPAQUE
|
||||
cairo_scaled_font_t* = record #OPAQUE
|
||||
cairo_font_face_t* = record #OPAQUE
|
||||
cairo_font_options_t* = record #OPAQUE
|
||||
cairo_matrix_t* = record
|
||||
cairo_t* {.final.} = object #OPAQUE
|
||||
cairo_surface_t* {.final.} = object #OPAQUE
|
||||
cairo_pattern_t* {.final.} = object #OPAQUE
|
||||
cairo_scaled_font_t* {.final.} = object #OPAQUE
|
||||
cairo_font_face_t* {.final.} = object #OPAQUE
|
||||
cairo_font_options_t* {.final.} = object #OPAQUE
|
||||
cairo_matrix_t* {.final.} = object
|
||||
xx: float64
|
||||
yx: float64
|
||||
xy: float64
|
||||
|
|
@ -163,15 +163,15 @@ type
|
|||
x0: float64
|
||||
y0: float64
|
||||
|
||||
cairo_user_data_key_t* = record
|
||||
cairo_user_data_key_t* {.final.} = object
|
||||
unused: int32
|
||||
|
||||
cairo_glyph_t* = record
|
||||
cairo_glyph_t* {.final.} = object
|
||||
index: int32
|
||||
x: float64
|
||||
y: float64
|
||||
|
||||
cairo_text_extents_t* = record
|
||||
cairo_text_extents_t* {.final.} = object
|
||||
x_bearing: float64
|
||||
y_bearing: float64
|
||||
width: float64
|
||||
|
|
@ -179,28 +179,28 @@ type
|
|||
x_advance: float64
|
||||
y_advance: float64
|
||||
|
||||
cairo_font_extents_t* = record
|
||||
cairo_font_extents_t* {.final.} = object
|
||||
ascent: float64
|
||||
descent: float64
|
||||
height: float64
|
||||
max_x_advance: float64
|
||||
max_y_advance: float64
|
||||
|
||||
cairo_path_data_t* = record #* _type : cairo_path_data_type_t;
|
||||
# length : LongInt;
|
||||
# end
|
||||
cairo_path_data_t* {.final.} = object #* _type : cairo_path_data_type_t;
|
||||
# length : LongInt;
|
||||
# end
|
||||
x: float64
|
||||
y: float64
|
||||
|
||||
cairo_path_t* = record
|
||||
cairo_path_t* {.final.} = object
|
||||
status: cairo_status_t
|
||||
data: Pcairo_path_data_t
|
||||
num_data: int32
|
||||
|
||||
cairo_rectangle_t* = record
|
||||
cairo_rectangle_t* {.final.} = object
|
||||
x, y, width, height: float64
|
||||
|
||||
cairo_rectangle_list_t* = record
|
||||
cairo_rectangle_list_t* {.final.} = object
|
||||
status: cairo_status_t
|
||||
rectangles: Pcairo_rectangle_t
|
||||
num_rectangles: int32
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ type
|
|||
ATK_LAYER_INVALID, ATK_LAYER_BACKGROUND, ATK_LAYER_CANVAS, ATK_LAYER_WIDGET,
|
||||
ATK_LAYER_MDI, ATK_LAYER_POPUP, ATK_LAYER_OVERLAY
|
||||
PAtkPropertyValues* = ptr TAtkPropertyValues
|
||||
TAtkPropertyValues* = record
|
||||
TAtkPropertyValues* {.final.} = object
|
||||
property_name*: cstring
|
||||
old_value*: TGValue
|
||||
new_value*: TGValue
|
||||
|
|
@ -379,7 +379,7 @@ type
|
|||
|
||||
TAtkAttributeSet* = TGSList
|
||||
PAtkAttribute* = ptr TAtkAttribute
|
||||
TAtkAttribute* = record
|
||||
TAtkAttribute* {.final.} = object
|
||||
name*: cstring
|
||||
value*: cstring
|
||||
|
||||
|
|
@ -453,7 +453,7 @@ type
|
|||
TAtkEventListenerInitProc* = proc ()
|
||||
TAtkEventListenerInit* = proc (para1: TAtkEventListenerInitProc){.cdecl.}
|
||||
PAtkKeyEventStruct* = ptr TAtkKeyEventStruct
|
||||
TAtkKeyEventStruct* = record
|
||||
TAtkKeyEventStruct* {.final.} = object
|
||||
`type`*: gint
|
||||
state*: guint
|
||||
keyval*: guint
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ type
|
|||
TGdkVisualClass* = object of TGObjectClass
|
||||
|
||||
PGdkColor* = ptr TGdkColor
|
||||
TGdkColor* = record
|
||||
TGdkColor* {.final.} = object
|
||||
pixel*: guint32
|
||||
red*: guint16
|
||||
green*: guint16
|
||||
|
|
@ -52,7 +52,7 @@ type
|
|||
TGdkFontType* = enum
|
||||
GDK_FONT_FONT, GDK_FONT_FONTSET
|
||||
PGdkFont* = ptr TGdkFont
|
||||
TGdkFont* = record
|
||||
TGdkFont* {.final.} = object
|
||||
`type`*: TGdkFontType
|
||||
ascent*: gint
|
||||
descent*: gint
|
||||
|
|
@ -79,7 +79,7 @@ type
|
|||
PGdkGCValuesMask* = ptr TGdkGCValuesMask
|
||||
TGdkGCValuesMask* = int32
|
||||
PGdkGCValues* = ptr TGdkGCValues
|
||||
TGdkGCValues* = record
|
||||
TGdkGCValues* {.final.} = object
|
||||
foreground*: TGdkColor
|
||||
background*: TGdkColor
|
||||
font*: PGdkFont
|
||||
|
|
@ -125,7 +125,7 @@ type
|
|||
TGdkInputCondition* = int32
|
||||
PGdkStatus* = ptr TGdkStatus
|
||||
TGdkStatus* = int32
|
||||
TGdkPoint* = record
|
||||
TGdkPoint* {.final.} = object
|
||||
x*: gint
|
||||
y*: gint
|
||||
|
||||
|
|
@ -135,14 +135,14 @@ type
|
|||
PGdkWChar* = ptr TGdkWChar
|
||||
TGdkWChar* = guint32
|
||||
PGdkSegment* = ptr TGdkSegment
|
||||
TGdkSegment* = record
|
||||
TGdkSegment* {.final.} = object
|
||||
x1*: gint
|
||||
y1*: gint
|
||||
x2*: gint
|
||||
y2*: gint
|
||||
|
||||
PGdkRectangle* = ptr TGdkRectangle
|
||||
TGdkRectangle* = record
|
||||
TGdkRectangle* {.final.} = object
|
||||
x*: gint
|
||||
y*: gint
|
||||
width*: gint
|
||||
|
|
@ -190,7 +190,7 @@ type
|
|||
PGdkCursorType* = ptr TGdkCursorType
|
||||
TGdkCursorType* = gint
|
||||
PGdkCursor* = ptr TGdkCursor
|
||||
TGdkCursor* = record
|
||||
TGdkCursor* {.final.} = object
|
||||
`type`*: TGdkCursorType
|
||||
ref_count*: guint
|
||||
|
||||
|
|
@ -220,14 +220,14 @@ type
|
|||
PGdkRegionBox* = ptr TGdkRegionBox
|
||||
TGdkRegionBox* = TGdkSegment
|
||||
PGdkRegion* = ptr TGdkRegion
|
||||
TGdkRegion* = record
|
||||
TGdkRegion* {.final.} = object
|
||||
size*: int32
|
||||
numRects*: int32
|
||||
rects*: PGdkRegionBox
|
||||
extents*: TGdkRegionBox
|
||||
|
||||
PPOINTBLOCK* = ptr TPOINTBLOCK
|
||||
TPOINTBLOCK* = record
|
||||
TPOINTBLOCK* {.final.} = object
|
||||
pts*: array[0..(NUMPTSTOBUFFER) - 1, TGdkPoint]
|
||||
next*: PPOINTBLOCK
|
||||
|
||||
|
|
@ -336,13 +336,13 @@ type
|
|||
GDK_SETTING_ACTION_NEW, GDK_SETTING_ACTION_CHANGED,
|
||||
GDK_SETTING_ACTION_DELETED
|
||||
PGdkEventAny* = ptr TGdkEventAny
|
||||
TGdkEventAny* = record
|
||||
TGdkEventAny* {.final.} = object
|
||||
`type`*: TGdkEventType
|
||||
window*: PGdkWindow
|
||||
send_event*: gint8
|
||||
|
||||
PGdkEventExpose* = ptr TGdkEventExpose
|
||||
TGdkEventExpose* = record
|
||||
TGdkEventExpose* {.final.} = object
|
||||
`type`*: TGdkEventType
|
||||
window*: PGdkWindow
|
||||
send_event*: gint8
|
||||
|
|
@ -351,20 +351,20 @@ type
|
|||
count*: gint
|
||||
|
||||
PGdkEventNoExpose* = ptr TGdkEventNoExpose
|
||||
TGdkEventNoExpose* = record
|
||||
TGdkEventNoExpose* {.final.} = object
|
||||
`type`*: TGdkEventType
|
||||
window*: PGdkWindow
|
||||
send_event*: gint8
|
||||
|
||||
PGdkEventVisibility* = ptr TGdkEventVisibility
|
||||
TGdkEventVisibility* = record
|
||||
TGdkEventVisibility* {.final.} = object
|
||||
`type`*: TGdkEventType
|
||||
window*: PGdkWindow
|
||||
send_event*: gint8
|
||||
state*: TGdkVisibilityState
|
||||
|
||||
PGdkEventMotion* = ptr TGdkEventMotion
|
||||
TGdkEventMotion* = record
|
||||
TGdkEventMotion* {.final.} = object
|
||||
`type`*: TGdkEventType
|
||||
window*: PGdkWindow
|
||||
send_event*: gint8
|
||||
|
|
@ -379,7 +379,7 @@ type
|
|||
y_root*: gdouble
|
||||
|
||||
PGdkEventButton* = ptr TGdkEventButton
|
||||
TGdkEventButton* = record
|
||||
TGdkEventButton* {.final.} = object
|
||||
`type`*: TGdkEventType
|
||||
window*: PGdkWindow
|
||||
send_event*: gint8
|
||||
|
|
@ -394,7 +394,7 @@ type
|
|||
y_root*: gdouble
|
||||
|
||||
PGdkEventScroll* = ptr TGdkEventScroll
|
||||
TGdkEventScroll* = record
|
||||
TGdkEventScroll* {.final.} = object
|
||||
`type`*: TGdkEventType
|
||||
window*: PGdkWindow
|
||||
send_event*: gint8
|
||||
|
|
@ -408,7 +408,7 @@ type
|
|||
y_root*: gdouble
|
||||
|
||||
PGdkEventKey* = ptr TGdkEventKey
|
||||
TGdkEventKey* = record
|
||||
TGdkEventKey* {.final.} = object
|
||||
`type`*: TGdkEventType
|
||||
window*: PGdkWindow
|
||||
send_event*: gint8
|
||||
|
|
@ -421,7 +421,7 @@ type
|
|||
group*: guint8
|
||||
|
||||
PGdkEventCrossing* = ptr TGdkEventCrossing
|
||||
TGdkEventCrossing* = record
|
||||
TGdkEventCrossing* {.final.} = object
|
||||
`type`*: TGdkEventType
|
||||
window*: PGdkWindow
|
||||
send_event*: gint8
|
||||
|
|
@ -437,14 +437,14 @@ type
|
|||
state*: guint
|
||||
|
||||
PGdkEventFocus* = ptr TGdkEventFocus
|
||||
TGdkEventFocus* = record
|
||||
TGdkEventFocus* {.final.} = object
|
||||
`type`*: TGdkEventType
|
||||
window*: PGdkWindow
|
||||
send_event*: gint8
|
||||
`in`*: gint16
|
||||
|
||||
PGdkEventConfigure* = ptr TGdkEventConfigure
|
||||
TGdkEventConfigure* = record
|
||||
TGdkEventConfigure* {.final.} = object
|
||||
`type`*: TGdkEventType
|
||||
window*: PGdkWindow
|
||||
send_event*: gint8
|
||||
|
|
@ -454,7 +454,7 @@ type
|
|||
height*: gint
|
||||
|
||||
PGdkEventProperty* = ptr TGdkEventProperty
|
||||
TGdkEventProperty* = record
|
||||
TGdkEventProperty* {.final.} = object
|
||||
`type`*: TGdkEventType
|
||||
window*: PGdkWindow
|
||||
send_event*: gint8
|
||||
|
|
@ -464,7 +464,7 @@ type
|
|||
|
||||
TGdkNativeWindow* = pointer
|
||||
PGdkEventSelection* = ptr TGdkEventSelection
|
||||
TGdkEventSelection* = record
|
||||
TGdkEventSelection* {.final.} = object
|
||||
`type`*: TGdkEventType
|
||||
window*: PGdkWindow
|
||||
send_event*: gint8
|
||||
|
|
@ -475,7 +475,7 @@ type
|
|||
requestor*: TGdkNativeWindow
|
||||
|
||||
PGdkEventProximity* = ptr TGdkEventProximity
|
||||
TGdkEventProximity* = record
|
||||
TGdkEventProximity* {.final.} = object
|
||||
`type`*: TGdkEventType
|
||||
window*: PGdkWindow
|
||||
send_event*: gint8
|
||||
|
|
@ -483,11 +483,11 @@ type
|
|||
device*: PGdkDevice
|
||||
|
||||
PmatDUMMY* = ptr TmatDUMMY
|
||||
TmatDUMMY* = record
|
||||
TmatDUMMY* {.final.} = object
|
||||
b*: array[0..19, char]
|
||||
|
||||
PGdkEventClient* = ptr TGdkEventClient
|
||||
TGdkEventClient* = record
|
||||
TGdkEventClient* {.final.} = object
|
||||
`type`*: TGdkEventType
|
||||
window*: PGdkWindow
|
||||
send_event*: gint8
|
||||
|
|
@ -496,7 +496,7 @@ type
|
|||
b*: array[0..19, char]
|
||||
|
||||
PGdkEventSetting* = ptr TGdkEventSetting
|
||||
TGdkEventSetting* = record
|
||||
TGdkEventSetting* {.final.} = object
|
||||
`type`*: TGdkEventType
|
||||
window*: PGdkWindow
|
||||
send_event*: gint8
|
||||
|
|
@ -504,7 +504,7 @@ type
|
|||
name*: cstring
|
||||
|
||||
PGdkEventWindowState* = ptr TGdkEventWindowState
|
||||
TGdkEventWindowState* = record
|
||||
TGdkEventWindowState* {.final.} = object
|
||||
`type`*: TGdkEventType
|
||||
window*: PGdkWindow
|
||||
send_event*: gint8
|
||||
|
|
@ -512,7 +512,7 @@ type
|
|||
new_window_state*: TGdkWindowState
|
||||
|
||||
PGdkEventDND* = ptr TGdkEventDND
|
||||
TGdkEventDND* = record
|
||||
TGdkEventDND* {.final.} = object
|
||||
`type`*: TGdkEventType
|
||||
window*: PGdkWindow
|
||||
send_event*: gint8
|
||||
|
|
@ -521,7 +521,7 @@ type
|
|||
x_root*: gshort
|
||||
y_root*: gshort
|
||||
|
||||
TGdkEvent* = record
|
||||
TGdkEvent* {.final.} = object
|
||||
data*: array[0..255, char] # union of
|
||||
# `type`: TGdkEventType
|
||||
# any: TGdkEventAny
|
||||
|
|
@ -585,12 +585,12 @@ type
|
|||
PGdkAxisUse* = ptr TGdkAxisUse
|
||||
TGdkAxisUse* = int32
|
||||
PGdkDeviceKey* = ptr TGdkDeviceKey
|
||||
TGdkDeviceKey* = record
|
||||
TGdkDeviceKey* {.final.} = object
|
||||
keyval*: guint
|
||||
modifiers*: TGdkModifierType
|
||||
|
||||
PGdkDeviceAxis* = ptr TGdkDeviceAxis
|
||||
TGdkDeviceAxis* = record
|
||||
TGdkDeviceAxis* {.final.} = object
|
||||
use*: TGdkAxisUse
|
||||
min*: gdouble
|
||||
max*: gdouble
|
||||
|
|
@ -605,12 +605,12 @@ type
|
|||
num_keys*: gint
|
||||
keys*: PGdkDeviceKey
|
||||
|
||||
TGdkTimeCoord* = record
|
||||
TGdkTimeCoord* {.final.} = object
|
||||
time*: guint32
|
||||
axes*: array[0..(GDK_MAX_TIMECOORD_AXES) - 1, gdouble]
|
||||
|
||||
PGdkKeymapKey* = ptr TGdkKeymapKey
|
||||
TGdkKeymapKey* = record
|
||||
TGdkKeymapKey* {.final.} = object
|
||||
keycode*: guint
|
||||
group*: gint
|
||||
level*: gint
|
||||
|
|
@ -624,12 +624,12 @@ type
|
|||
direction_changed*: proc (keymap: PGdkKeymap){.cdecl.}
|
||||
|
||||
PGdkPangoAttrStipple* = ptr TGdkPangoAttrStipple
|
||||
TGdkPangoAttrStipple* = record
|
||||
TGdkPangoAttrStipple* {.final.} = object
|
||||
attr*: TPangoAttribute
|
||||
stipple*: PGdkBitmap
|
||||
|
||||
PGdkPangoAttrEmbossed* = ptr TGdkPangoAttrEmbossed
|
||||
TGdkPangoAttrEmbossed* = record
|
||||
TGdkPangoAttrEmbossed* {.final.} = object
|
||||
attr*: TPangoAttribute
|
||||
embossed*: gboolean
|
||||
|
||||
|
|
@ -653,7 +653,7 @@ type
|
|||
GDK_OVERLAP_RECTANGLE_PART
|
||||
TGdkSpanFunc* = proc (span: PGdkSpan, data: gpointer){.cdecl.}
|
||||
PGdkRgbCmap* = ptr TGdkRgbCmap
|
||||
TGdkRgbCmap* = record
|
||||
TGdkRgbCmap* {.final.} = object
|
||||
colors*: array[0..255, guint32]
|
||||
n_colors*: gint
|
||||
info_list*: PGSList
|
||||
|
|
@ -698,7 +698,7 @@ type
|
|||
TGdkInputFunction* = proc (data: gpointer, source: gint,
|
||||
condition: TGdkInputCondition){.cdecl.}
|
||||
TGdkDestroyNotify* = proc (data: gpointer){.cdecl.}
|
||||
TGdkSpan* = record
|
||||
TGdkSpan* {.final.} = object
|
||||
x*: gint
|
||||
y*: gint
|
||||
width*: gint
|
||||
|
|
@ -731,7 +731,7 @@ type
|
|||
GDK_WINDOW_EDGE_SOUTH_WEST, GDK_WINDOW_EDGE_SOUTH,
|
||||
GDK_WINDOW_EDGE_SOUTH_EAST
|
||||
PGdkWindowAttr* = ptr TGdkWindowAttr
|
||||
TGdkWindowAttr* = record
|
||||
TGdkWindowAttr* {.final.} = object
|
||||
title*: cstring
|
||||
event_mask*: gint
|
||||
x*: gint
|
||||
|
|
@ -748,7 +748,7 @@ type
|
|||
override_redirect*: gboolean
|
||||
|
||||
PGdkGeometry* = ptr TGdkGeometry
|
||||
TGdkGeometry* = record
|
||||
TGdkGeometry* {.final.} = object
|
||||
min_width*: gint
|
||||
min_height*: gint
|
||||
max_width*: gint
|
||||
|
|
@ -762,7 +762,7 @@ type
|
|||
win_gravity*: TGdkGravity
|
||||
|
||||
PGdkPointerHooks* = ptr TGdkPointerHooks
|
||||
TGdkPointerHooks* = record
|
||||
TGdkPointerHooks* {.final.} = object
|
||||
get_pointer*: proc (window: PGdkWindow, x: Pgint, y: Pgint,
|
||||
mask: PGdkModifierType): PGdkWindow{.cdecl.}
|
||||
window_at_pointer*: proc (screen: PGdkScreen, win_x: Pgint, win_y: Pgint): PGdkWindow{.
|
||||
|
|
|
|||
|
|
@ -191,12 +191,12 @@ proc gdk_pixbuf_get_option*(pixbuf: PGdkPixbuf, key: cstring): cstring{.cdecl,
|
|||
dynlib: gdkpixbuflib, importc: "gdk_pixbuf_get_option".}
|
||||
type
|
||||
PGdkPixbufLoader* = ptr TGdkPixbufLoader
|
||||
TGdkPixbufLoader* = record
|
||||
TGdkPixbufLoader* {.final.} = object
|
||||
parent_instance*: TGObject
|
||||
priv*: gpointer
|
||||
|
||||
PGdkPixbufLoaderClass* = ptr TGdkPixbufLoaderClass
|
||||
TGdkPixbufLoaderClass* = record
|
||||
TGdkPixbufLoaderClass* {.final.} = object
|
||||
parent_class*: TGObjectClass
|
||||
area_prepared*: proc (loader: PGdkPixbufLoader){.cdecl.}
|
||||
area_updated*: proc (loader: PGdkPixbufLoader, x: int32, y: int32,
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ type
|
|||
TGHFunc* = proc (key, value, user_data: gpointer){.cdecl.}
|
||||
PGFreeFunc* = proc (data: gpointer){.cdecl.}
|
||||
PGTimeVal* = ptr TGTimeVal
|
||||
TGTimeVal* = record
|
||||
TGTimeVal* {.final.} = object
|
||||
tv_sec*: glong
|
||||
tv_usec*: glong
|
||||
|
||||
|
|
@ -88,17 +88,17 @@ type
|
|||
TGQuark* = guint32
|
||||
PGQuark* = ptr TGQuark
|
||||
PGTypeCValue* = ptr TGTypeCValue
|
||||
TGTypeCValue* = record
|
||||
TGTypeCValue* {.final.} = object
|
||||
v_double*: gdouble
|
||||
|
||||
GType* = gulong
|
||||
PGType* = ptr GType
|
||||
PGTypeClass* = ptr TGTypeClass
|
||||
TGTypeClass* = record
|
||||
TGTypeClass* {.final.} = object
|
||||
g_type*: GType
|
||||
|
||||
PGTypeInstance* = ptr TGTypeInstance
|
||||
TGTypeInstance* = record
|
||||
TGTypeInstance* {.final.} = object
|
||||
g_class*: PGTypeClass
|
||||
|
||||
PGTypeInterface* = ptr TGTypeInterface
|
||||
|
|
@ -107,14 +107,14 @@ type
|
|||
g_instance_type*: GType
|
||||
|
||||
PGTypeQuery* = ptr TGTypeQuery
|
||||
TGTypeQuery* = record
|
||||
TGTypeQuery* {.final.} = object
|
||||
theType*: GType
|
||||
type_name*: cstring
|
||||
class_size*: guint
|
||||
instance_size*: guint
|
||||
|
||||
PGValue* = ptr TGValue
|
||||
TGValue* = record
|
||||
TGValue* {.final.} = object
|
||||
g_type*: GType
|
||||
data*: array[0..1, gdouble]
|
||||
|
||||
|
|
@ -122,12 +122,12 @@ type
|
|||
PGData* = pointer
|
||||
PGSList* = ptr TGSList
|
||||
PPGSList* = ptr PGSList
|
||||
TGSList* = record
|
||||
TGSList* {.final.} = object
|
||||
data*: gpointer
|
||||
next*: PGSList
|
||||
|
||||
PGList* = ptr TGList
|
||||
TGList* = record
|
||||
TGList* {.final.} = object
|
||||
data*: gpointer
|
||||
next*: PGList
|
||||
prev*: PGList
|
||||
|
|
@ -136,7 +136,7 @@ type
|
|||
TGParamFlags* = int32
|
||||
PGParamSpec* = ptr TGParamSpec
|
||||
PPGParamSpec* = ptr PGParamSpec
|
||||
TGParamSpec* = record
|
||||
TGParamSpec* {.final.} = object
|
||||
g_type_instance*: TGTypeInstance
|
||||
name*: cstring
|
||||
flags*: TGParamFlags
|
||||
|
|
@ -149,7 +149,7 @@ type
|
|||
param_id*: guint
|
||||
|
||||
PGParamSpecClass* = ptr TGParamSpecClass
|
||||
TGParamSpecClass* = record
|
||||
TGParamSpecClass* {.final.} = object
|
||||
g_type_class*: TGTypeClass
|
||||
value_type*: GType
|
||||
finalize*: proc (pspec: PGParamSpec){.cdecl.}
|
||||
|
|
@ -160,7 +160,7 @@ type
|
|||
dummy*: array[0..3, gpointer]
|
||||
|
||||
PGParameter* = ptr TGParameter
|
||||
TGParameter* = record
|
||||
TGParameter* {.final.} = object
|
||||
name*: cstring
|
||||
value*: TGValue
|
||||
|
||||
|
|
@ -305,7 +305,7 @@ const
|
|||
|
||||
type
|
||||
PGTypeValueTable* = ptr TGTypeValueTable
|
||||
TGTypeValueTable* = record
|
||||
TGTypeValueTable* {.final.} = object
|
||||
value_init*: proc (value: PGValue){.cdecl.}
|
||||
value_free*: proc (value: PGValue){.cdecl.}
|
||||
value_copy*: proc (src_value: PGValue, dest_value: PGValue){.cdecl.}
|
||||
|
|
@ -320,7 +320,7 @@ type
|
|||
cdecl.}
|
||||
|
||||
PGTypeInfo* = ptr TGTypeInfo
|
||||
TGTypeInfo* = record
|
||||
TGTypeInfo* {.final.} = object
|
||||
class_size*: guint16
|
||||
base_init*: TGBaseInitFunc
|
||||
base_finalize*: TGBaseFinalizeFunc
|
||||
|
|
@ -333,11 +333,11 @@ type
|
|||
value_table*: PGTypeValueTable
|
||||
|
||||
PGTypeFundamentalInfo* = ptr TGTypeFundamentalInfo
|
||||
TGTypeFundamentalInfo* = record
|
||||
TGTypeFundamentalInfo* {.final.} = object
|
||||
type_flags*: TGTypeFundamentalFlags
|
||||
|
||||
PGInterfaceInfo* = ptr TGInterfaceInfo
|
||||
TGInterfaceInfo* = record
|
||||
TGInterfaceInfo* {.final.} = object
|
||||
interface_init*: TGInterfaceInitFunc
|
||||
interface_finalize*: TGInterfaceFinalizeFunc
|
||||
interface_data*: gpointer
|
||||
|
|
@ -449,7 +449,7 @@ const
|
|||
|
||||
type
|
||||
PGValueArray* = ptr TGValueArray
|
||||
TGValueArray* = record
|
||||
TGValueArray* {.final.} = object
|
||||
n_values*: guint
|
||||
values*: PGValue
|
||||
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".}
|
||||
type
|
||||
PGParamSpecTypeInfo* = ptr TGParamSpecTypeInfo
|
||||
TGParamSpecTypeInfo* = record
|
||||
TGParamSpecTypeInfo* {.final.} = object
|
||||
instance_size*: guint16
|
||||
n_preallocs*: guint16
|
||||
instance_init*: proc (pspec: PGParamSpec){.cdecl.}
|
||||
|
|
@ -668,7 +668,7 @@ type
|
|||
PGClosure* = ptr TGClosure
|
||||
PGClosureNotifyData* = ptr TGClosureNotifyData
|
||||
TGClosureNotify* = proc (data: gpointer, closure: PGClosure){.cdecl.}
|
||||
TGClosure* = record
|
||||
TGClosure* {.final.} = object
|
||||
flag0*: int32
|
||||
marshal*: proc (closure: PGClosure, return_value: PGValue,
|
||||
n_param_values: guint, param_values: PGValue,
|
||||
|
|
@ -682,7 +682,7 @@ type
|
|||
n_param_values: guint, param_values: PGValue,
|
||||
invocation_hint: gpointer, marshal_data: gpointer){.
|
||||
cdecl.}
|
||||
TGClosureNotifyData* = record
|
||||
TGClosureNotifyData* {.final.} = object
|
||||
data*: gpointer
|
||||
notify*: TGClosureNotify
|
||||
|
||||
|
|
@ -734,7 +734,7 @@ proc is_invalid*(a: var TGClosure): guint
|
|||
proc set_is_invalid*(a: var TGClosure, is_invalid: guint)
|
||||
type
|
||||
PGCClosure* = ptr TGCClosure
|
||||
TGCClosure* = record
|
||||
TGCClosure* {.final.} = object
|
||||
closure*: TGClosure
|
||||
callback*: gpointer
|
||||
|
||||
|
|
@ -797,13 +797,13 @@ type
|
|||
data: gpointer): gboolean{.cdecl.}
|
||||
PGSignalFlags* = ptr TGSignalFlags
|
||||
TGSignalFlags* = int32
|
||||
TGSignalInvocationHint* = record
|
||||
TGSignalInvocationHint* {.final.} = object
|
||||
signal_id*: guint
|
||||
detail*: TGQuark
|
||||
run_type*: TGSignalFlags
|
||||
|
||||
PGSignalQuery* = ptr TGSignalQuery
|
||||
TGSignalQuery* = record
|
||||
TGSignalQuery* {.final.} = object
|
||||
signal_id*: guint
|
||||
signal_name*: cstring
|
||||
itype*: GType
|
||||
|
|
@ -952,7 +952,7 @@ type
|
|||
TGTypePluginCompleteInterfaceInfo* = proc (plugin: PGTypePlugin,
|
||||
instance_type: GType, interface_type: GType, info: PGInterfaceInfo){.cdecl.}
|
||||
PGTypePluginClass* = ptr TGTypePluginClass
|
||||
TGTypePluginClass* = record
|
||||
TGTypePluginClass* {.final.} = object
|
||||
base_iface*: TGTypeInterface
|
||||
use_plugin*: TGTypePluginUse
|
||||
unuse_plugin*: TGTypePluginUnuse
|
||||
|
|
@ -1011,7 +1011,7 @@ type
|
|||
notify*: proc (anObject: PGObject, pspec: PGParamSpec){.cdecl.}
|
||||
pdummy*: array[0..7, gpointer]
|
||||
|
||||
TGObjectConstructParam* = record
|
||||
TGObjectConstructParam* {.final.} = object
|
||||
pspec*: PGParamSpec
|
||||
value*: PGValue
|
||||
|
||||
|
|
@ -1125,27 +1125,27 @@ proc GUINT32_SWAP_LE_BE_CONSTANT*(val: guint32): guint32
|
|||
type
|
||||
PGEnumClass* = ptr TGEnumClass
|
||||
PGEnumValue* = ptr TGEnumValue
|
||||
TGEnumClass* = record
|
||||
TGEnumClass* {.final.} = object
|
||||
g_type_class*: TGTypeClass
|
||||
minimum*: gint
|
||||
maximum*: gint
|
||||
n_values*: guint
|
||||
values*: PGEnumValue
|
||||
|
||||
TGEnumValue* = record
|
||||
TGEnumValue* {.final.} = object
|
||||
value*: gint
|
||||
value_name*: cstring
|
||||
value_nick*: cstring
|
||||
|
||||
PGFlagsClass* = ptr TGFlagsClass
|
||||
PGFlagsValue* = ptr TGFlagsValue
|
||||
TGFlagsClass* = record
|
||||
TGFlagsClass* {.final.} = object
|
||||
g_type_class*: TGTypeClass
|
||||
mask*: guint
|
||||
n_values*: guint
|
||||
values*: PGFlagsValue
|
||||
|
||||
TGFlagsValue* = record
|
||||
TGFlagsValue* {.final.} = object
|
||||
value*: guint
|
||||
value_name*: cstring
|
||||
value_nick*: cstring
|
||||
|
|
@ -1203,7 +1203,7 @@ const
|
|||
G_MAXUSHORT* = 2 * G_MAXSHORT + 1
|
||||
G_MAXINT* = 2147483647
|
||||
G_MININT* = - G_MAXINT - 1
|
||||
G_MAXUINT* = 4294967295
|
||||
G_MAXUINT* = -1
|
||||
G_MINLONG* = G_MININT
|
||||
G_MAXLONG* = G_MAXINT
|
||||
G_MAXULONG* = G_MAXUINT
|
||||
|
|
@ -1224,7 +1224,7 @@ const
|
|||
|
||||
type
|
||||
PGSystemThread* = ptr TGSystemThread
|
||||
TGSystemThread* = record
|
||||
TGSystemThread* {.final.} = object
|
||||
data*: array[0..3, char]
|
||||
dummy_double*: float64
|
||||
dummy_pointer*: pointer
|
||||
|
|
@ -1350,7 +1350,7 @@ proc g_set_prgname*(prgname: cstring){.cdecl, dynlib: gliblib,
|
|||
importc: "g_set_prgname".}
|
||||
type
|
||||
PGDebugKey* = ptr TGDebugKey
|
||||
TGDebugKey* = record
|
||||
TGDebugKey* {.final.} = object
|
||||
key*: cstring
|
||||
value*: guint
|
||||
|
||||
|
|
@ -1390,7 +1390,7 @@ proc g_bit_storage*(number: gulong): guint{.cdecl, dynlib: gliblib,
|
|||
type
|
||||
PPGTrashStack* = ptr PGTrashStack
|
||||
PGTrashStack* = ptr TGTrashStack
|
||||
TGTrashStack* = record
|
||||
TGTrashStack* {.final.} = object
|
||||
next*: PGTrashStack
|
||||
|
||||
|
||||
|
|
@ -1466,7 +1466,7 @@ const
|
|||
|
||||
type
|
||||
PGMemVTable* = ptr TGMemVTable
|
||||
TGMemVTable* = record
|
||||
TGMemVTable* {.final.} = object
|
||||
malloc*: proc (n_bytes: gsize): gpointer{.cdecl.}
|
||||
realloc*: proc (mem: gpointer, n_bytes: gsize): gpointer{.cdecl.}
|
||||
free*: proc (mem: gpointer){.cdecl.}
|
||||
|
|
@ -1679,7 +1679,7 @@ type
|
|||
TGCompletionStrncmpFunc* = proc (s1: cstring, s2: cstring, n: gsize): gint{.
|
||||
cdecl.}
|
||||
PGCompletion* = ptr TGCompletion
|
||||
TGCompletion* = record
|
||||
TGCompletion* {.final.} = object
|
||||
items*: PGList
|
||||
func*: TGCompletionFunc
|
||||
prefix*: cstring
|
||||
|
|
@ -1809,7 +1809,7 @@ type
|
|||
PGDateDay* = ptr TGDateDay
|
||||
TGDateDay* = guint8
|
||||
Ptm* = ptr Ttm
|
||||
Ttm* = record
|
||||
Ttm* {.final.} = object
|
||||
tm_sec*: gint
|
||||
tm_min*: gint
|
||||
tm_hour*: gint
|
||||
|
|
@ -1872,7 +1872,7 @@ const
|
|||
|
||||
type
|
||||
PGDate* = ptr TGDate
|
||||
TGDate* = record
|
||||
TGDate* {.final.} = object
|
||||
flag0*: 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".}
|
||||
type
|
||||
PGHook* = ptr TGHook
|
||||
TGHook* = record
|
||||
TGHook* {.final.} = object
|
||||
data*: gpointer
|
||||
next*: PGHook
|
||||
prev*: PGHook
|
||||
|
|
@ -2047,7 +2047,7 @@ type
|
|||
TGHookFunc* = proc (data: gpointer){.cdecl.}
|
||||
TGHookCheckFunc* = proc (data: gpointer): gboolean{.cdecl.}
|
||||
TGHookFinalizeFunc* = proc (hook_list: PGHookList, hook: PGHook){.cdecl.}
|
||||
TGHookList* = record
|
||||
TGHookList* {.final.} = object
|
||||
seq_id*: gulong
|
||||
flag0*: int32
|
||||
hooks*: PGHook
|
||||
|
|
@ -2138,7 +2138,7 @@ proc g_hook_list_marshal_check*(hook_list: PGHookList, may_recurse: gboolean,
|
|||
importc: "g_hook_list_marshal_check".}
|
||||
type
|
||||
PGThreadPool* = ptr TGThreadPool
|
||||
TGThreadPool* = record
|
||||
TGThreadPool* {.final.} = object
|
||||
func*: TGFunc
|
||||
user_data*: gpointer
|
||||
exclusive*: gboolean
|
||||
|
|
@ -2352,7 +2352,7 @@ proc g_utf8_collate_key*(str: cstring, len: gssize): cstring{.cdecl,
|
|||
dynlib: gliblib, importc: "g_utf8_collate_key".}
|
||||
type
|
||||
PGString* = ptr TGString
|
||||
TGString* = record
|
||||
TGString* {.final.} = object
|
||||
str*: cstring
|
||||
len*: gsize
|
||||
allocated_len*: gsize
|
||||
|
|
@ -2468,7 +2468,7 @@ type
|
|||
TGIOFunc* = proc (source: PGIOChannel, condition: TGIOCondition,
|
||||
data: gpointer): gboolean{.cdecl.}
|
||||
PGIOFuncs* = ptr TGIOFuncs
|
||||
TGIOFuncs* = record
|
||||
TGIOFuncs* {.final.} = object
|
||||
io_read*: proc (channel: PGIOChannel, buf: cstring, count: gsize,
|
||||
bytes_read: Pgsize, err: pointer): TGIOStatus{.cdecl.}
|
||||
io_write*: proc (channel: PGIOChannel, buf: cstring, count: gsize,
|
||||
|
|
@ -2483,7 +2483,7 @@ type
|
|||
cdecl.}
|
||||
io_get_flags*: proc (channel: PGIOChannel): TGIOFlags{.cdecl.}
|
||||
|
||||
TGIOChannel* = record
|
||||
TGIOChannel* {.final.} = object
|
||||
ref_count*: guint
|
||||
funcs*: PGIOFuncs
|
||||
encoding*: cstring
|
||||
|
|
@ -2699,7 +2699,7 @@ type
|
|||
PGMarkupParseContext* = ptr TGMarkupParseContext
|
||||
TGMarkupParseContext* = pointer
|
||||
PGMarkupParser* = ptr TGMarkupParser
|
||||
TGMarkupParser* = record
|
||||
TGMarkupParser* {.final.} = object
|
||||
start_element*: proc (context: PGMarkupParseContext, element_name: cstring,
|
||||
attribute_names: PPgchar, attribute_values: PPgchar,
|
||||
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".}
|
||||
type
|
||||
PGNode* = ptr TGNode
|
||||
TGNode* = record
|
||||
TGNode* {.final.} = object
|
||||
data*: gpointer
|
||||
next*: 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".}
|
||||
type
|
||||
PGQueue* = ptr TGQueue
|
||||
TGQueue* = record
|
||||
TGQueue* {.final.} = object
|
||||
head*: PGList
|
||||
tail*: PGList
|
||||
length*: guint
|
||||
|
|
@ -2947,7 +2947,7 @@ proc g_random_double_range*(`begin`: gdouble, `end`: gdouble): gdouble{.cdecl,
|
|||
dynlib: gliblib, importc: "g_random_double_range".}
|
||||
type
|
||||
PGTuples* = ptr TGTuples
|
||||
TGTuples* = record
|
||||
TGTuples* {.final.} = object
|
||||
len*: guint
|
||||
|
||||
PGRelation* = pointer
|
||||
|
|
@ -3003,12 +3003,12 @@ type
|
|||
PGScanner* = ptr TGScanner
|
||||
PGScannerConfig* = ptr TGScannerConfig
|
||||
PGTokenValue* = ptr TGTokenValue
|
||||
TGTokenValue* = record
|
||||
TGTokenValue* {.final.} = object
|
||||
v_float*: gdouble
|
||||
|
||||
TGScannerMsgFunc* = proc (scanner: PGScanner, message: cstring,
|
||||
error: gboolean){.cdecl.}
|
||||
TGScanner* = record
|
||||
TGScanner* {.final.} = object
|
||||
user_data*: gpointer
|
||||
max_parse_errors*: guint
|
||||
parse_errors*: guint
|
||||
|
|
@ -3031,7 +3031,7 @@ type
|
|||
scope_id*: guint
|
||||
msg_handler*: TGScannerMsgFunc
|
||||
|
||||
TGScannerConfig* = record
|
||||
TGScannerConfig* {.final.} = object
|
||||
cset_skip_characters*: cstring
|
||||
cset_identifier_first*: cstring
|
||||
cset_identifier_nth*: cstring
|
||||
|
|
|
|||
|
|
@ -155,17 +155,17 @@ type
|
|||
TGtkSignalFunc* = proc (para1: TGtkSignalFuncProc){.cdecl.}
|
||||
PGtkSignalMarshaller* = ptr TGtkSignalMarshaller
|
||||
TGtkSignalMarshaller* = TGSignalCMarshaller
|
||||
TGtkArgSignalData* = record
|
||||
TGtkArgSignalData* {.final.} = object
|
||||
f*: TGtkSignalFunc
|
||||
d*: gpointer
|
||||
|
||||
TGtkArg* = record
|
||||
TGtkArg* {.final.} = object
|
||||
`type`*: TGtkType
|
||||
name*: cstring
|
||||
d*: gdouble # was a union type
|
||||
|
||||
PGtkTypeInfo* = ptr TGtkTypeInfo
|
||||
TGtkTypeInfo* = record
|
||||
TGtkTypeInfo* {.final.} = object
|
||||
type_name*: cstring
|
||||
object_size*: guint
|
||||
class_size*: guint
|
||||
|
|
@ -188,7 +188,7 @@ type
|
|||
TGtkAllocation* = TGdkRectangle
|
||||
TGtkCallback* = proc (widget: PGtkWidget, data: gpointer){.cdecl.}
|
||||
PGtkRequisition* = ptr TGtkRequisition
|
||||
TGtkRequisition* = record
|
||||
TGtkRequisition* {.final.} = object
|
||||
width*: gint
|
||||
height*: gint
|
||||
|
||||
|
|
@ -323,7 +323,7 @@ type
|
|||
gtk_reserved8*: proc (){.cdecl.}
|
||||
|
||||
PGtkWidgetAuxInfo* = ptr TGtkWidgetAuxInfo
|
||||
TGtkWidgetAuxInfo* = record
|
||||
TGtkWidgetAuxInfo* {.final.} = object
|
||||
x*: gint
|
||||
y*: gint
|
||||
width*: gint
|
||||
|
|
@ -331,7 +331,7 @@ type
|
|||
flag0*: guint16
|
||||
|
||||
PGtkWidgetShapeInfo* = ptr TGtkWidgetShapeInfo
|
||||
TGtkWidgetShapeInfo* = record
|
||||
TGtkWidgetShapeInfo* {.final.} = object
|
||||
offset_x*: gint16
|
||||
offset_y*: gint16
|
||||
shape_mask*: PGdkBitmap
|
||||
|
|
@ -370,12 +370,12 @@ type
|
|||
gtk_reserved4: proc (){.cdecl.}
|
||||
|
||||
PGtkAccelKey* = ptr TGtkAccelKey
|
||||
TGtkAccelKey* = record
|
||||
TGtkAccelKey* {.final.} = object
|
||||
accel_key*: guint
|
||||
accel_mods*: TGdkModifierType
|
||||
flag0*: guint16
|
||||
|
||||
TGtkAccelGroupEntry* = record
|
||||
TGtkAccelGroupEntry* {.final.} = object
|
||||
key*: TGtkAccelKey
|
||||
closure*: PGClosure
|
||||
accel_path_quark*: TGQuark
|
||||
|
|
@ -595,7 +595,7 @@ type
|
|||
PGtkBindingSignal* = ptr TGtkBindingSignal
|
||||
PGtkBindingArg* = ptr TGtkBindingArg
|
||||
PGtkBindingSet* = ptr TGtkBindingSet
|
||||
TGtkBindingSet* = record
|
||||
TGtkBindingSet* {.final.} = object
|
||||
set_name*: cstring
|
||||
priority*: gint
|
||||
widget_path_pspecs*: PGSList
|
||||
|
|
@ -605,7 +605,7 @@ type
|
|||
current*: PGtkBindingEntry
|
||||
flag0*: guint16
|
||||
|
||||
TGtkBindingEntry* = record
|
||||
TGtkBindingEntry* {.final.} = object
|
||||
keyval*: guint
|
||||
modifiers*: TGdkModifierType
|
||||
binding_set*: PGtkBindingSet
|
||||
|
|
@ -614,13 +614,13 @@ type
|
|||
hash_next*: PGtkBindingEntry
|
||||
signals*: PGtkBindingSignal
|
||||
|
||||
TGtkBindingSignal* = record
|
||||
TGtkBindingSignal* {.final.} = object
|
||||
next*: PGtkBindingSignal
|
||||
signal_name*: cstring
|
||||
n_args*: guint
|
||||
args*: PGtkBindingArg
|
||||
|
||||
TGtkBindingArg* = record
|
||||
TGtkBindingArg* {.final.} = object
|
||||
arg_type*: TGtkType
|
||||
d*: gdouble
|
||||
|
||||
|
|
@ -634,7 +634,7 @@ type
|
|||
TGtkBoxClass* = object of TGtkContainerClass
|
||||
|
||||
PGtkBoxChild* = ptr TGtkBoxChild
|
||||
TGtkBoxChild* = record
|
||||
TGtkBoxChild* {.final.} = object
|
||||
widget*: PGtkWidget
|
||||
padding*: guint16
|
||||
flag0*: guint16
|
||||
|
|
@ -906,12 +906,12 @@ type
|
|||
TGtkCListCompareFunc* = proc (clist: PGtkCList, ptr1: gconstpointer,
|
||||
ptr2: gconstpointer): gint{.cdecl.}
|
||||
PGtkCListCellInfo* = ptr TGtkCListCellInfo
|
||||
TGtkCListCellInfo* = record
|
||||
TGtkCListCellInfo* {.final.} = object
|
||||
row*: gint
|
||||
column*: gint
|
||||
|
||||
PGtkCListDestInfo* = ptr TGtkCListDestInfo
|
||||
TGtkCListDestInfo* = record
|
||||
TGtkCListDestInfo* {.final.} = object
|
||||
cell*: TGtkCListCellInfo
|
||||
insert_pos*: TGtkCListDragPos
|
||||
|
||||
|
|
@ -1014,7 +1014,7 @@ type
|
|||
|
||||
PGPtrArray = pointer
|
||||
PGArray = pointer
|
||||
TGtkCListColumn* = record
|
||||
TGtkCListColumn* {.final.} = object
|
||||
title*: cstring
|
||||
area*: TGdkRectangle
|
||||
button*: PGtkWidget
|
||||
|
|
@ -1025,7 +1025,7 @@ type
|
|||
justification*: TGtkJustification
|
||||
flag0*: guint16
|
||||
|
||||
TGtkCListRow* = record
|
||||
TGtkCListRow* {.final.} = object
|
||||
cell*: PGtkCell
|
||||
state*: TGtkStateType
|
||||
foreground*: TGdkColor
|
||||
|
|
@ -1036,7 +1036,7 @@ type
|
|||
flag0*: guint16
|
||||
|
||||
PGtkCellText* = ptr TGtkCellText
|
||||
TGtkCellText* = record
|
||||
TGtkCellText* {.final.} = object
|
||||
`type`*: TGtkCellType
|
||||
vertical*: gint16
|
||||
horizontal*: gint16
|
||||
|
|
@ -1044,7 +1044,7 @@ type
|
|||
text*: cstring
|
||||
|
||||
PGtkCellPixmap* = ptr TGtkCellPixmap
|
||||
TGtkCellPixmap* = record
|
||||
TGtkCellPixmap* {.final.} = object
|
||||
`type`*: TGtkCellType
|
||||
vertical*: gint16
|
||||
horizontal*: gint16
|
||||
|
|
@ -1053,7 +1053,7 @@ type
|
|||
mask*: PGdkBitmap
|
||||
|
||||
PGtkCellPixText* = ptr TGtkCellPixText
|
||||
TGtkCellPixText* = record
|
||||
TGtkCellPixText* {.final.} = object
|
||||
`type`*: TGtkCellType
|
||||
vertical*: gint16
|
||||
horizontal*: gint16
|
||||
|
|
@ -1064,14 +1064,14 @@ type
|
|||
mask*: PGdkBitmap
|
||||
|
||||
PGtkCellWidget* = ptr TGtkCellWidget
|
||||
TGtkCellWidget* = record
|
||||
TGtkCellWidget* {.final.} = object
|
||||
`type`*: TGtkCellType
|
||||
vertical*: gint16
|
||||
horizontal*: gint16
|
||||
style*: PGtkStyle
|
||||
widget*: PGtkWidget
|
||||
|
||||
TGtkCell* = record
|
||||
TGtkCell* {.final.} = object
|
||||
`type`*: TGtkCellType
|
||||
vertical*: gint16
|
||||
horizontal*: gint16
|
||||
|
|
@ -1212,7 +1212,7 @@ type
|
|||
action: TGtkCTreeExpansionType){.cdecl.}
|
||||
|
||||
PGtkCTreeRow* = ptr TGtkCTreeRow
|
||||
TGtkCTreeRow* = record
|
||||
TGtkCTreeRow* {.final.} = object
|
||||
row*: TGtkCListRow
|
||||
parent*: PGtkCTreeNode
|
||||
sibling*: PGtkCTreeNode
|
||||
|
|
@ -1224,7 +1224,7 @@ type
|
|||
level*: guint16
|
||||
GtkCTreeRow_flag0*: guint16
|
||||
|
||||
TGtkCTreeNode* = record
|
||||
TGtkCTreeNode* {.final.} = object
|
||||
list*: TGList
|
||||
|
||||
PGtkDrawingArea* = ptr TGtkDrawingArea
|
||||
|
|
@ -1479,7 +1479,7 @@ type
|
|||
TGtkFixedClass* = object of TGtkContainerClass
|
||||
|
||||
PGtkFixedChild* = ptr TGtkFixedChild
|
||||
TGtkFixedChild* = record
|
||||
TGtkFixedChild* {.final.} = object
|
||||
widget*: PGtkWidget
|
||||
x*: gint
|
||||
y*: gint
|
||||
|
|
@ -1632,7 +1632,7 @@ type
|
|||
gtk_reserved363: proc (){.cdecl.}
|
||||
gtk_reserved364: proc (){.cdecl.}
|
||||
|
||||
TGtkRulerMetric* = record
|
||||
TGtkRulerMetric* {.final.} = object
|
||||
metric_name*: cstring
|
||||
abbrev*: cstring
|
||||
pixels_per_unit*: gdouble
|
||||
|
|
@ -1657,7 +1657,7 @@ type
|
|||
TGtkSettingsClass* = object of TGObjectClass
|
||||
|
||||
PGtkSettingsValue* = ptr TGtkSettingsValue
|
||||
TGtkSettingsValue* = record
|
||||
TGtkSettingsValue* {.final.} = object
|
||||
origin*: cstring
|
||||
value*: TGValue
|
||||
|
||||
|
|
@ -1708,7 +1708,7 @@ type
|
|||
GTK_RC_TOKEN_IM_MODULE_FILE, GTK_RC_TOKEN_STOCK, GTK_RC_TOKEN_LTR,
|
||||
GTK_RC_TOKEN_RTL, GTK_RC_TOKEN_LAST
|
||||
PGtkRcProperty* = ptr TGtkRcProperty
|
||||
TGtkRcProperty* = record
|
||||
TGtkRcProperty* {.final.} = object
|
||||
type_name*: TGQuark
|
||||
property_name*: TGQuark
|
||||
origin*: cstring
|
||||
|
|
@ -1877,7 +1877,7 @@ type
|
|||
gtk_reserved3812: proc (){.cdecl.}
|
||||
|
||||
PGtkBorder* = ptr TGtkBorder
|
||||
TGtkBorder* = record
|
||||
TGtkBorder* {.final.} = object
|
||||
left*: gint
|
||||
right*: gint
|
||||
top*: gint
|
||||
|
|
@ -1978,27 +1978,27 @@ type
|
|||
|
||||
PGtkIconSet* = pointer
|
||||
PGtkImagePixmapData* = ptr TGtkImagePixmapData
|
||||
TGtkImagePixmapData* = record
|
||||
TGtkImagePixmapData* {.final.} = object
|
||||
pixmap*: PGdkPixmap
|
||||
|
||||
PGtkImageImageData* = ptr TGtkImageImageData
|
||||
TGtkImageImageData* = record
|
||||
TGtkImageImageData* {.final.} = object
|
||||
image*: PGdkImage
|
||||
|
||||
PGtkImagePixbufData* = ptr TGtkImagePixbufData
|
||||
TGtkImagePixbufData* = record
|
||||
TGtkImagePixbufData* {.final.} = object
|
||||
pixbuf*: PGdkPixbuf
|
||||
|
||||
PGtkImageStockData* = ptr TGtkImageStockData
|
||||
TGtkImageStockData* = record
|
||||
TGtkImageStockData* {.final.} = object
|
||||
stock_id*: cstring
|
||||
|
||||
PGtkImageIconSetData* = ptr TGtkImageIconSetData
|
||||
TGtkImageIconSetData* = record
|
||||
TGtkImageIconSetData* {.final.} = object
|
||||
icon_set*: PGtkIconSet
|
||||
|
||||
PGtkImageAnimationData* = ptr TGtkImageAnimationData
|
||||
TGtkImageAnimationData* = record
|
||||
TGtkImageAnimationData* {.final.} = object
|
||||
anim*: PGdkPixbufAnimation
|
||||
iter*: PGdkPixbufAnimationIter
|
||||
frame_timeout*: guint
|
||||
|
|
@ -2111,7 +2111,7 @@ type
|
|||
gtk_reserved474: proc (){.cdecl.}
|
||||
|
||||
PGtkItemFactoryEntry* = ptr TGtkItemFactoryEntry
|
||||
TGtkItemFactoryEntry* = record
|
||||
TGtkItemFactoryEntry* {.final.} = object
|
||||
path*: cstring
|
||||
accelerator*: cstring
|
||||
callback*: TGtkItemFactoryCallback
|
||||
|
|
@ -2120,7 +2120,7 @@ type
|
|||
extra_data*: gconstpointer
|
||||
|
||||
PGtkItemFactoryItem* = ptr TGtkItemFactoryItem
|
||||
TGtkItemFactoryItem* = record
|
||||
TGtkItemFactoryItem* {.final.} = object
|
||||
path*: cstring
|
||||
widgets*: PGSList
|
||||
|
||||
|
|
@ -2173,7 +2173,7 @@ type
|
|||
cdecl.}
|
||||
PGtkTreeModelFlags* = ptr TGtkTreeModelFlags
|
||||
TGtkTreeModelFlags* = int32
|
||||
TGtkTreeIter* = record
|
||||
TGtkTreeIter* {.final.} = object
|
||||
stamp*: gint
|
||||
user_data*: gpointer
|
||||
user_data2*: gpointer
|
||||
|
|
@ -2435,12 +2435,12 @@ type
|
|||
GtkPreview_flag0*: guint16
|
||||
|
||||
PGtkPreviewInfo* = ptr TGtkPreviewInfo
|
||||
TGtkPreviewInfo* = record
|
||||
TGtkPreviewInfo* {.final.} = object
|
||||
lookup*: Pguchar
|
||||
gamma*: gdouble
|
||||
|
||||
PGtkDitherInfo* = ptr TGtkDitherInfo
|
||||
TGtkDitherInfo* = record
|
||||
TGtkDitherInfo* {.final.} = object
|
||||
c*: array[0..3, guchar]
|
||||
|
||||
PGtkPreviewClass* = ptr TGtkPreviewClass
|
||||
|
|
@ -2533,7 +2533,7 @@ type
|
|||
gtk_reserved603: proc (){.cdecl.}
|
||||
gtk_reserved604: proc (){.cdecl.}
|
||||
|
||||
TGtkSelectionData* = record
|
||||
TGtkSelectionData* {.final.} = object
|
||||
selection*: TGdkAtom
|
||||
target*: TGdkAtom
|
||||
thetype*: TGdkAtom
|
||||
|
|
@ -2543,18 +2543,18 @@ type
|
|||
display*: PGdkDisplay
|
||||
|
||||
PGtkTargetEntry* = ptr TGtkTargetEntry
|
||||
TGtkTargetEntry* = record
|
||||
TGtkTargetEntry* {.final.} = object
|
||||
target*: cstring
|
||||
flags*: guint
|
||||
info*: guint
|
||||
|
||||
PGtkTargetList* = ptr TGtkTargetList
|
||||
TGtkTargetList* = record
|
||||
TGtkTargetList* {.final.} = object
|
||||
list*: PGList
|
||||
ref_count*: guint
|
||||
|
||||
PGtkTargetPair* = ptr TGtkTargetPair
|
||||
TGtkTargetPair* = record
|
||||
TGtkTargetPair* {.final.} = object
|
||||
target*: TGdkAtom
|
||||
flags*: guint
|
||||
info*: guint
|
||||
|
|
@ -2635,7 +2635,7 @@ type
|
|||
gtk_reserved634: proc (){.cdecl.}
|
||||
|
||||
PGtkStockItem* = ptr TGtkStockItem
|
||||
TGtkStockItem* = record
|
||||
TGtkStockItem* {.final.} = object
|
||||
stock_id*: cstring
|
||||
label*: cstring
|
||||
modifier*: TGdkModifierType
|
||||
|
|
@ -2681,7 +2681,7 @@ type
|
|||
TGtkTableClass* = object of TGtkContainerClass
|
||||
|
||||
PGtkTableChild* = ptr TGtkTableChild
|
||||
TGtkTableChild* = record
|
||||
TGtkTableChild* {.final.} = object
|
||||
widget*: PGtkWidget
|
||||
left_attach*: guint16
|
||||
right_attach*: guint16
|
||||
|
|
@ -2691,7 +2691,7 @@ type
|
|||
ypadding*: guint16
|
||||
GtkTableChild_flag0*: guint16
|
||||
|
||||
TGtkTableRowCol* = record
|
||||
TGtkTableRowCol* {.final.} = object
|
||||
requisition*: guint16
|
||||
allocation*: guint16
|
||||
spacing*: guint16
|
||||
|
|
@ -2710,7 +2710,7 @@ type
|
|||
|
||||
PGtkTextFont* = pointer
|
||||
PGtkPropertyMark* = ptr TGtkPropertyMark
|
||||
TGtkPropertyMark* = record
|
||||
TGtkPropertyMark* {.final.} = object
|
||||
`property`*: PGList
|
||||
offset*: guint
|
||||
index*: guint
|
||||
|
|
@ -2764,7 +2764,7 @@ type
|
|||
PGtkTextSearchFlags* = ptr TGtkTextSearchFlags
|
||||
TGtkTextSearchFlags* = int32
|
||||
PGtkTextIter* = ptr TGtkTextIter
|
||||
TGtkTextIter* = record
|
||||
TGtkTextIter* {.final.} = object
|
||||
dummy1*: gpointer
|
||||
dummy2*: gpointer
|
||||
dummy3*: gint
|
||||
|
|
@ -2802,7 +2802,7 @@ type
|
|||
gtk_reserved664: proc (){.cdecl.}
|
||||
|
||||
PGtkTextAppearance* = ptr TGtkTextAppearance
|
||||
TGtkTextAppearance* = record
|
||||
TGtkTextAppearance* {.final.} = object
|
||||
bg_color*: TGdkColor
|
||||
fg_color*: TGdkColor
|
||||
bg_stipple*: PGdkBitmap
|
||||
|
|
@ -2811,7 +2811,7 @@ type
|
|||
padding1*: gpointer
|
||||
flag0*: guint16
|
||||
|
||||
TGtkTextAttributes* = record
|
||||
TGtkTextAttributes* {.final.} = object
|
||||
refcount*: guint
|
||||
appearance*: TGtkTextAppearance
|
||||
justification*: TGtkJustification
|
||||
|
|
@ -2860,7 +2860,7 @@ type
|
|||
gtk_reserved4: proc (){.cdecl.}
|
||||
|
||||
PGtkTextMarkBody* = ptr TGtkTextMarkBody
|
||||
TGtkTextMarkBody* = record
|
||||
TGtkTextMarkBody* {.final.} = object
|
||||
obj*: PGtkTextMark
|
||||
name*: cstring
|
||||
tree*: PGtkTextBTree
|
||||
|
|
@ -2879,11 +2879,11 @@ type
|
|||
gtk_reserved4: proc (){.cdecl.}
|
||||
|
||||
PGtkTextPixbuf* = ptr TGtkTextPixbuf
|
||||
TGtkTextPixbuf* = record
|
||||
TGtkTextPixbuf* {.final.} = object
|
||||
pixbuf*: PGdkPixbuf
|
||||
|
||||
PGtkTextChildBody* = ptr TGtkTextChildBody
|
||||
TGtkTextChildBody* = record
|
||||
TGtkTextChildBody* {.final.} = object
|
||||
obj*: PGtkTextChildAnchor
|
||||
widgets*: PGSList
|
||||
tree*: PGtkTextBTree
|
||||
|
|
@ -2892,17 +2892,17 @@ type
|
|||
PGtkTextLineSegment* = ptr TGtkTextLineSegment
|
||||
PGtkTextLineSegmentClass* = ptr TGtkTextLineSegmentClass
|
||||
PGtkTextTagInfo* = ptr TGtkTextTagInfo
|
||||
TGtkTextTagInfo* = record
|
||||
TGtkTextTagInfo* {.final.} = object
|
||||
tag*: PGtkTextTag
|
||||
tag_root*: PGtkTextBTreeNode
|
||||
toggle_count*: gint
|
||||
|
||||
PGtkTextToggleBody* = ptr TGtkTextToggleBody
|
||||
TGtkTextToggleBody* = record
|
||||
TGtkTextToggleBody* {.final.} = object
|
||||
info*: PGtkTextTagInfo
|
||||
inNodeCounts*: gboolean
|
||||
|
||||
TGtkTextLineSegment* = record
|
||||
TGtkTextLineSegment* {.final.} = object
|
||||
`type`*: PGtkTextLineSegmentClass
|
||||
next*: PGtkTextLineSegment
|
||||
char_count*: int32
|
||||
|
|
@ -2919,7 +2919,7 @@ type
|
|||
line: PGtkTextLine){.cdecl.}
|
||||
TGtkTextSegCheckFunc* = proc (seg: PGtkTextLineSegment, line: PGtkTextLine){.
|
||||
cdecl.}
|
||||
TGtkTextLineSegmentClass* = record
|
||||
TGtkTextLineSegmentClass* {.final.} = object
|
||||
name*: cstring
|
||||
leftGravity*: gboolean
|
||||
splitFunc*: TGtkTextSegSplitFunc
|
||||
|
|
@ -2929,13 +2929,13 @@ type
|
|||
checkFunc*: TGtkTextSegCheckFunc
|
||||
|
||||
PGtkTextLineData* = ptr TGtkTextLineData
|
||||
TGtkTextLineData* = record
|
||||
TGtkTextLineData* {.final.} = object
|
||||
view_id*: gpointer
|
||||
next*: PGtkTextLineData
|
||||
height*: gint
|
||||
flag0*: int32
|
||||
|
||||
TGtkTextLine* = record
|
||||
TGtkTextLine* {.final.} = object
|
||||
parent*: PGtkTextBTreeNode
|
||||
next*: PGtkTextLine
|
||||
segments*: PGtkTextLineSegment
|
||||
|
|
@ -3020,18 +3020,18 @@ type
|
|||
gtk_reserved4: proc (){.cdecl.}
|
||||
|
||||
PGtkTextAttrAppearance* = ptr TGtkTextAttrAppearance
|
||||
TGtkTextAttrAppearance* = record
|
||||
TGtkTextAttrAppearance* {.final.} = object
|
||||
attr*: TPangoAttribute
|
||||
appearance*: TGtkTextAppearance
|
||||
|
||||
PGtkTextCursorDisplay* = ptr TGtkTextCursorDisplay
|
||||
TGtkTextCursorDisplay* = record
|
||||
TGtkTextCursorDisplay* {.final.} = object
|
||||
x*: gint
|
||||
y*: gint
|
||||
height*: gint
|
||||
flag0*: guint16
|
||||
|
||||
TGtkTextLineDisplay* = record
|
||||
TGtkTextLineDisplay* {.final.} = object
|
||||
layout*: PPangoLayout
|
||||
cursors*: PGSList
|
||||
shaped_objects*: PGSList
|
||||
|
|
@ -3152,7 +3152,7 @@ type
|
|||
|
||||
PGtkTooltips* = ptr TGtkTooltips
|
||||
PGtkTooltipsData* = ptr TGtkTooltipsData
|
||||
TGtkTooltipsData* = record
|
||||
TGtkTooltipsData* {.final.} = object
|
||||
tooltips*: PGtkTooltips
|
||||
widget*: PGtkWidget
|
||||
tip_text*: cstring
|
||||
|
|
@ -3184,7 +3184,7 @@ type
|
|||
TGtkToolbarSpaceStyle* = enum
|
||||
GTK_TOOLBAR_SPACE_EMPTY, GTK_TOOLBAR_SPACE_LINE
|
||||
PGtkToolbarChild* = ptr TGtkToolbarChild
|
||||
TGtkToolbarChild* = record
|
||||
TGtkToolbarChild* {.final.} = object
|
||||
`type`*: TGtkToolbarChildType
|
||||
widget*: PGtkWidget
|
||||
icon*: PGtkWidget
|
||||
|
|
@ -3365,13 +3365,13 @@ type
|
|||
PGtkRBNode* = ptr TGtkRBNode
|
||||
TGtkRBTreeTraverseFunc* = proc (tree: PGtkRBTree, node: PGtkRBNode,
|
||||
data: gpointer){.cdecl.}
|
||||
TGtkRBTree* = record
|
||||
TGtkRBTree* {.final.} = object
|
||||
root*: PGtkRBNode
|
||||
`nil`*: PGtkRBNode
|
||||
parent_tree*: PGtkRBTree
|
||||
parent_node*: PGtkRBNode
|
||||
|
||||
TGtkRBNode* = record
|
||||
TGtkRBNode* {.final.} = object
|
||||
flag0*: guint16
|
||||
left*: PGtkRBNode
|
||||
right*: PGtkRBNode
|
||||
|
|
@ -3386,14 +3386,14 @@ type
|
|||
TGtkTreeViewSearchDialogPositionFunc* = proc (tree_view: PGtkTreeView,
|
||||
search_dialog: PGtkWidget){.cdecl.}
|
||||
PGtkTreeViewColumnReorder* = ptr TGtkTreeViewColumnReorder
|
||||
TGtkTreeViewColumnReorder* = record
|
||||
TGtkTreeViewColumnReorder* {.final.} = object
|
||||
left_align*: gint
|
||||
right_align*: gint
|
||||
left_column*: PGtkTreeViewColumn
|
||||
right_column*: PGtkTreeViewColumn
|
||||
|
||||
PGtkTreeViewPrivate* = ptr TGtkTreeViewPrivate
|
||||
TGtkTreeViewPrivate* = record
|
||||
TGtkTreeViewPrivate* {.final.} = object
|
||||
model*: PGtkTreeModel
|
||||
flags*: guint
|
||||
tree*: PGtkRBTree
|
||||
|
|
@ -11304,96 +11304,127 @@ proc GTK_FUNDAMENTAL_TYPE*(thetype: GType): GType =
|
|||
result = G_TYPE_FUNDAMENTAL(thetype)
|
||||
|
||||
proc GTK_VALUE_CHAR*(a: TGtkArg): gchar =
|
||||
var a = a
|
||||
Result = cast[ptr gchar](addr(a.d))^
|
||||
|
||||
proc GTK_VALUE_UCHAR*(a: TGtkArg): guchar =
|
||||
var a = a
|
||||
Result = cast[ptr guchar](addr(a.d))^
|
||||
|
||||
proc GTK_VALUE_BOOL*(a: TGtkArg): gboolean =
|
||||
var a = a
|
||||
Result = cast[ptr gboolean](addr(a.d))^
|
||||
|
||||
proc GTK_VALUE_INT*(a: TGtkArg): gint =
|
||||
var a = a
|
||||
Result = cast[ptr gint](addr(a.d))^
|
||||
|
||||
proc GTK_VALUE_UINT*(a: TGtkArg): guint =
|
||||
var a = a
|
||||
Result = cast[ptr guint](addr(a.d))^
|
||||
|
||||
proc GTK_VALUE_LONG*(a: TGtkArg): glong =
|
||||
var a = a
|
||||
Result = cast[ptr glong](addr(a.d))^
|
||||
|
||||
proc GTK_VALUE_ULONG*(a: TGtkArg): gulong =
|
||||
var a = a
|
||||
Result = cast[ptr gulong](addr(a.d))^
|
||||
|
||||
proc GTK_VALUE_FLOAT*(a: TGtkArg): gfloat =
|
||||
var a = a
|
||||
Result = cast[ptr gfloat](addr(a.d))^
|
||||
|
||||
proc GTK_VALUE_DOUBLE*(a: TGtkArg): gdouble =
|
||||
var a = a
|
||||
Result = cast[ptr gdouble](addr(a.d))^
|
||||
|
||||
proc GTK_VALUE_STRING*(a: TGtkArg): cstring =
|
||||
var a = a
|
||||
Result = cast[ptr cstring](addr(a.d))^
|
||||
|
||||
proc GTK_VALUE_ENUM*(a: TGtkArg): gint =
|
||||
var a = a
|
||||
Result = cast[ptr gint](addr(a.d))^
|
||||
|
||||
proc GTK_VALUE_FLAGS*(a: TGtkArg): guint =
|
||||
var a = a
|
||||
Result = cast[ptr guint](addr(a.d))^
|
||||
|
||||
proc GTK_VALUE_BOXED*(a: TGtkArg): gpointer =
|
||||
var a = a
|
||||
Result = cast[ptr gpointer](addr(a.d))^
|
||||
|
||||
proc GTK_VALUE_OBJECT*(a: TGtkArg): PGtkObject =
|
||||
var a = a
|
||||
Result = cast[ptr PGtkObject](addr(a.d))^
|
||||
|
||||
proc GTK_VALUE_POINTER*(a: TGtkArg): GPointer =
|
||||
var a = a
|
||||
Result = cast[ptr gpointer](addr(a.d))^
|
||||
|
||||
proc GTK_VALUE_SIGNAL*(a: TGtkArg): TGtkArgSignalData =
|
||||
var a = a
|
||||
Result = cast[ptr TGtkArgSignalData](addr(a.d))^
|
||||
|
||||
proc GTK_RETLOC_CHAR*(a: TGtkArg): cstring =
|
||||
var a = a
|
||||
Result = cast[ptr cstring](addr(a.d))^
|
||||
|
||||
proc GTK_RETLOC_UCHAR*(a: TGtkArg): Pguchar =
|
||||
var a = a
|
||||
Result = cast[ptr pguchar](addr(a.d))^
|
||||
|
||||
proc GTK_RETLOC_BOOL*(a: TGtkArg): Pgboolean =
|
||||
var a = a
|
||||
Result = cast[ptr pgboolean](addr(a.d))^
|
||||
|
||||
proc GTK_RETLOC_INT*(a: TGtkArg): Pgint =
|
||||
var a = a
|
||||
Result = cast[ptr pgint](addr(a.d))^
|
||||
|
||||
proc GTK_RETLOC_UINT*(a: TGtkArg): Pguint =
|
||||
var a = a
|
||||
Result = cast[ptr pguint](addr(a.d))^
|
||||
|
||||
proc GTK_RETLOC_LONG*(a: TGtkArg): Pglong =
|
||||
var a = a
|
||||
Result = cast[ptr pglong](addr(a.d))^
|
||||
|
||||
proc GTK_RETLOC_ULONG*(a: TGtkArg): Pgulong =
|
||||
var a = a
|
||||
Result = cast[ptr pgulong](addr(a.d))^
|
||||
|
||||
proc GTK_RETLOC_FLOAT*(a: TGtkArg): Pgfloat =
|
||||
var a = a
|
||||
Result = cast[ptr pgfloat](addr(a.d))^
|
||||
|
||||
proc GTK_RETLOC_DOUBLE*(a: TGtkArg): Pgdouble =
|
||||
var a = a
|
||||
Result = cast[ptr pgdouble](addr(a.d))^
|
||||
|
||||
proc GTK_RETLOC_STRING*(a: TGtkArg): Ppgchar =
|
||||
var a = a
|
||||
Result = cast[ptr Ppgchar](addr(a.d))^
|
||||
|
||||
proc GTK_RETLOC_ENUM*(a: TGtkArg): Pgint =
|
||||
var a = a
|
||||
Result = cast[ptr Pgint](addr(a.d))^
|
||||
|
||||
proc GTK_RETLOC_FLAGS*(a: TGtkArg): Pguint =
|
||||
var a = a
|
||||
Result = cast[ptr pguint](addr(a.d))^
|
||||
|
||||
proc GTK_RETLOC_BOXED*(a: TGtkArg): Pgpointer =
|
||||
var a = a
|
||||
Result = cast[ptr pgpointer](addr(a.d))^
|
||||
|
||||
proc GTK_RETLOC_OBJECT*(a: TGtkArg): PPGtkObject =
|
||||
var a = a
|
||||
Result = cast[ptr ppgtkobject](addr(a.d))^
|
||||
|
||||
proc GTK_RETLOC_POINTER*(a: TGtkArg): Pgpointer =
|
||||
var a = a
|
||||
Result = cast[ptr pgpointer](addr(a.d))^
|
||||
|
||||
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)
|
||||
if not may_be_blocked:
|
||||
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
|
||||
|
||||
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_DISPLAY_NAME = 1 shl 2, GTK_FILE_FILTER_MIME_TYPE = 1 shl 3
|
||||
PGtkFileFilterInfo* = ref TGtkFileFilterInfo
|
||||
TGtkFileFilterInfo* = record
|
||||
TGtkFileFilterInfo* {.final.} = object
|
||||
contains*: TGtkFileFilterFlags
|
||||
filename*: cstring
|
||||
uri*: cstring
|
||||
|
|
|
|||
|
|
@ -68,12 +68,12 @@ type
|
|||
exc: PDomException): PDomString{.cdecl.}
|
||||
|
||||
PDomDocument* = ptr TDomDocument
|
||||
TDomDocument* = record
|
||||
TDomDocument* {.final.} = object
|
||||
parent*: PDomNode
|
||||
iterators*: PGSList
|
||||
|
||||
PDomDocumentClass* = ptr TDomDocumentClass
|
||||
TDomDocumentClass* = record
|
||||
TDomDocumentClass* {.final.} = object
|
||||
parent_class*: PDomNodeClass
|
||||
|
||||
PHtmlFocusIterator* = ptr THtmlFocusIterator
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ type
|
|||
PPangoGlyph* = ptr TPangoGlyph
|
||||
TPangoGlyph* = guint32
|
||||
PPangoRectangle* = ptr TPangoRectangle
|
||||
TPangoRectangle* = record
|
||||
TPangoRectangle* {.final.} = object
|
||||
x*: int32
|
||||
y*: int32
|
||||
width*: int32
|
||||
|
|
@ -61,7 +61,7 @@ type
|
|||
PANGO_DIRECTION_LTR, PANGO_DIRECTION_RTL, PANGO_DIRECTION_TTB_LTR,
|
||||
PANGO_DIRECTION_TTB_RTL
|
||||
PPangoColor* = ptr TPangoColor
|
||||
TPangoColor* = record
|
||||
TPangoColor* {.final.} = object
|
||||
red*: guint16
|
||||
green*: guint16
|
||||
blue*: guint16
|
||||
|
|
@ -72,12 +72,12 @@ type
|
|||
TPangoUnderline* = int32
|
||||
PPangoAttribute* = ptr TPangoAttribute
|
||||
PPangoAttrClass* = ptr TPangoAttrClass
|
||||
TPangoAttribute* = record
|
||||
TPangoAttribute* {.final.} = object
|
||||
klass*: PPangoAttrClass
|
||||
start_index*: int
|
||||
end_index*: int
|
||||
|
||||
TPangoAttrClass* = record
|
||||
TPangoAttrClass* {.final.} = object
|
||||
`type`*: TPangoAttrType
|
||||
copy*: proc (attr: PPangoAttribute): PPangoAttribute{.cdecl.}
|
||||
destroy*: proc (attr: PPangoAttribute){.cdecl.}
|
||||
|
|
@ -85,43 +85,43 @@ type
|
|||
cdecl.}
|
||||
|
||||
PPangoAttrString* = ptr TPangoAttrString
|
||||
TPangoAttrString* = record
|
||||
TPangoAttrString* {.final.} = object
|
||||
attr*: TPangoAttribute
|
||||
value*: cstring
|
||||
|
||||
PPangoAttrLanguage* = ptr TPangoAttrLanguage
|
||||
TPangoAttrLanguage* = record
|
||||
TPangoAttrLanguage* {.final.} = object
|
||||
attr*: TPangoAttribute
|
||||
value*: PPangoLanguage
|
||||
|
||||
PPangoAttrInt* = ptr TPangoAttrInt
|
||||
TPangoAttrInt* = record
|
||||
TPangoAttrInt* {.final.} = object
|
||||
attr*: TPangoAttribute
|
||||
value*: int32
|
||||
|
||||
PPangoAttrFloat* = ptr TPangoAttrFloat
|
||||
TPangoAttrFloat* = record
|
||||
TPangoAttrFloat* {.final.} = object
|
||||
attr*: TPangoAttribute
|
||||
value*: gdouble
|
||||
|
||||
PPangoAttrColor* = ptr TPangoAttrColor
|
||||
TPangoAttrColor* = record
|
||||
TPangoAttrColor* {.final.} = object
|
||||
attr*: TPangoAttribute
|
||||
color*: TPangoColor
|
||||
|
||||
PPangoAttrShape* = ptr TPangoAttrShape
|
||||
TPangoAttrShape* = record
|
||||
TPangoAttrShape* {.final.} = object
|
||||
attr*: TPangoAttribute
|
||||
ink_rect*: TPangoRectangle
|
||||
logical_rect*: TPangoRectangle
|
||||
|
||||
PPangoAttrFontDesc* = ptr TPangoAttrFontDesc
|
||||
TPangoAttrFontDesc* = record
|
||||
TPangoAttrFontDesc* {.final.} = object
|
||||
attr*: TPangoAttribute
|
||||
desc*: PPangoFontDescription
|
||||
|
||||
PPangoLogAttr* = ptr TPangoLogAttr
|
||||
TPangoLogAttr* = record
|
||||
TPangoLogAttr* {.final.} = object
|
||||
flag0*: guint16
|
||||
|
||||
PPangoCoverageLevel* = ptr TPangoCoverageLevel
|
||||
|
|
@ -129,25 +129,25 @@ type
|
|||
PANGO_COVERAGE_NONE, PANGO_COVERAGE_FALLBACK, PANGO_COVERAGE_APPROXIMATE,
|
||||
PANGO_COVERAGE_EXACT
|
||||
PPangoBlockInfo* = ptr TPangoBlockInfo
|
||||
TPangoBlockInfo* = record
|
||||
TPangoBlockInfo* {.final.} = object
|
||||
data*: Pguchar
|
||||
level*: TPangoCoverageLevel
|
||||
|
||||
PPangoCoverage* = ptr TPangoCoverage
|
||||
TPangoCoverage* = record
|
||||
TPangoCoverage* {.final.} = object
|
||||
ref_count*: int
|
||||
n_blocks*: int32
|
||||
data_size*: int32
|
||||
blocks*: PPangoBlockInfo
|
||||
|
||||
PPangoEngineRange* = ptr TPangoEngineRange
|
||||
TPangoEngineRange* = record
|
||||
TPangoEngineRange* {.final.} = object
|
||||
start*: int32
|
||||
theEnd*: int32
|
||||
langs*: cstring
|
||||
|
||||
PPangoEngineInfo* = ptr TPangoEngineInfo
|
||||
TPangoEngineInfo* = record
|
||||
TPangoEngineInfo* {.final.} = object
|
||||
id*: cstring
|
||||
engine_type*: cstring
|
||||
render_type*: cstring
|
||||
|
|
@ -155,7 +155,7 @@ type
|
|||
n_ranges*: gint
|
||||
|
||||
PPangoEngine* = ptr TPangoEngine
|
||||
TPangoEngine* = record
|
||||
TPangoEngine* {.final.} = object
|
||||
id*: cstring
|
||||
`type`*: cstring
|
||||
length*: gint
|
||||
|
|
@ -165,7 +165,7 @@ type
|
|||
attrs: PPangoLogAttr, attrs_len: int32){.
|
||||
cdecl.}
|
||||
PPangoEngineLang* = ptr TPangoEngineLang
|
||||
TPangoEngineLang* = record
|
||||
TPangoEngineLang* {.final.} = object
|
||||
engine*: TPangoEngine
|
||||
script_break*: TPangoEngineLangScriptBreak
|
||||
|
||||
|
|
@ -176,7 +176,7 @@ type
|
|||
language: PPangoLanguage): PPangoCoverage{.
|
||||
cdecl.}
|
||||
PPangoEngineShape* = ptr TPangoEngineShape
|
||||
TPangoEngineShape* = record
|
||||
TPangoEngineShape* {.final.} = object
|
||||
engine*: TPangoEngine
|
||||
script_shape*: TPangoEngineShapeScript
|
||||
get_coverage*: TPangoEngineShapeGetCoverage
|
||||
|
|
@ -194,28 +194,28 @@ type
|
|||
PPangoGlyphUnit* = ptr TPangoGlyphUnit
|
||||
TPangoGlyphUnit* = gint32
|
||||
PPangoGlyphGeometry* = ptr TPangoGlyphGeometry
|
||||
TPangoGlyphGeometry* = record
|
||||
TPangoGlyphGeometry* {.final.} = object
|
||||
width*: TPangoGlyphUnit
|
||||
x_offset*: TPangoGlyphUnit
|
||||
y_offset*: TPangoGlyphUnit
|
||||
|
||||
PPangoGlyphVisAttr* = ptr TPangoGlyphVisAttr
|
||||
TPangoGlyphVisAttr* = record
|
||||
TPangoGlyphVisAttr* {.final.} = object
|
||||
flag0*: int16
|
||||
|
||||
PPangoGlyphInfo* = ptr TPangoGlyphInfo
|
||||
TPangoGlyphInfo* = record
|
||||
TPangoGlyphInfo* {.final.} = object
|
||||
glyph*: TPangoGlyph
|
||||
geometry*: TPangoGlyphGeometry
|
||||
attr*: TPangoGlyphVisAttr
|
||||
|
||||
TPangoGlyphString* = record
|
||||
TPangoGlyphString* {.final.} = object
|
||||
num_glyphs*: gint
|
||||
glyphs*: PPangoGlyphInfo
|
||||
log_clusters*: Pgint
|
||||
space*: gint
|
||||
|
||||
TPangoAnalysis* = record
|
||||
TPangoAnalysis* {.final.} = object
|
||||
shape_engine*: PPangoEngineShape
|
||||
lang_engine*: PPangoEngineLang
|
||||
font*: PPangoFont
|
||||
|
|
@ -223,7 +223,7 @@ type
|
|||
language*: PPangoLanguage
|
||||
extra_attrs*: PGSList
|
||||
|
||||
TPangoItem* = record
|
||||
TPangoItem* {.final.} = object
|
||||
offset*: gint
|
||||
length*: gint
|
||||
num_chars*: gint
|
||||
|
|
@ -236,14 +236,14 @@ type
|
|||
TPangoWrapMode* = enum
|
||||
PANGO_WRAP_WORD, PANGO_WRAP_CHAR
|
||||
PPangoLayoutLine* = ptr TPangoLayoutLine
|
||||
TPangoLayoutLine* = record
|
||||
TPangoLayoutLine* {.final.} = object
|
||||
layout*: PPangoLayout
|
||||
start_index*: gint
|
||||
length*: gint
|
||||
runs*: PGSList
|
||||
|
||||
PPangoLayoutRun* = ptr TPangoLayoutRun
|
||||
TPangoLayoutRun* = record
|
||||
TPangoLayoutRun* {.final.} = object
|
||||
item*: PPangoItem
|
||||
glyphs*: PPangoGlyphString
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ type
|
|||
regMN,
|
||||
regNewline
|
||||
|
||||
TRegex = record
|
||||
TRegex = object of TObject
|
||||
case kind: TRegexKind
|
||||
of regChar: c: char
|
||||
of regSet: s: ref set[char]
|
||||
|
|
|
|||
|
|
@ -162,7 +162,7 @@ type
|
|||
# Data passed back in callouts
|
||||
# Const before type ignored
|
||||
# Pointer to character tables
|
||||
Tpcre_extra* = record
|
||||
Tpcre_extra* {.final.} = object
|
||||
flags: cuint
|
||||
study_data: pointer
|
||||
match_limit: cuint
|
||||
|
|
@ -189,7 +189,7 @@ type
|
|||
# Offset to next item in the pattern
|
||||
# Length of next item in the pattern
|
||||
# ------------------------------------------------------------------
|
||||
TPcre_callout_block* = record
|
||||
TPcre_callout_block* {.final.} = object
|
||||
version: cint
|
||||
callout_number: cint
|
||||
offset_vector: ptr cint
|
||||
|
|
|
|||
|
|
@ -19,10 +19,8 @@ import
|
|||
math
|
||||
|
||||
type
|
||||
TComplex* = record ## 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
|
||||
TComplex* = tuple[re, im: float]
|
||||
## a complex number, consisting of a real and an imaginary part
|
||||
|
||||
proc `==` *(x, y: TComplex): bool =
|
||||
## Compare two complex numbers `x` and `y` for equality.
|
||||
|
|
|
|||
|
|
@ -25,23 +25,24 @@ type
|
|||
dbQuiting, # debugger wants to quit
|
||||
dbBreakpoints # debugger is only interested in breakpoints
|
||||
|
||||
TDbgBreakpoint = record
|
||||
TDbgBreakpoint {.final.} = object
|
||||
low, high: int # range from low to high; if disabled
|
||||
# both low and high are set to their negative values
|
||||
# this makes the check faster and safes memory
|
||||
filename: string
|
||||
name: string # name of breakpoint
|
||||
|
||||
TVarSlot {.compilerproc.} = record # variable slots used for debugger:
|
||||
TVarSlot {.compilerproc, final.} = object # variable slots used for debugger:
|
||||
address: pointer
|
||||
typ: PNimType
|
||||
name: cstring # for globals this is "module.name"
|
||||
|
||||
PExtendedFrame = ptr TExtendedFrame
|
||||
TExtendedFrame = record # If the debugger is enabled the compiler provides
|
||||
# an extended frame. Of course only slots that are
|
||||
# needed are allocated and not 10_000, except for
|
||||
# the global data description.
|
||||
TExtendedFrame {.final.} = object # If the debugger is enabled the compiler
|
||||
# provides an extended frame. Of course
|
||||
# only slots that are
|
||||
# needed are allocated and not 10_000,
|
||||
# except for the global data description.
|
||||
f: TFrame
|
||||
slots: array[0..10_000, TVarSlot]
|
||||
|
||||
|
|
@ -69,7 +70,7 @@ proc findBreakpoint(name: string): int =
|
|||
return -1
|
||||
|
||||
proc ListBreakPoints() =
|
||||
write(stdout, "*** emdb| Breakpoints:\n")
|
||||
write(stdout, "*** endb| Breakpoints:\n")
|
||||
for i in 0 .. dbgBPlen-1:
|
||||
write(stdout, dbgBP[i].name & ": " & $abs(dbgBP[i].low) & ".." &
|
||||
$abs(dbgBP[i].high) & dbgBP[i].filename)
|
||||
|
|
@ -101,13 +102,13 @@ proc writeVariable(stream: TFile, slot: TVarSlot) =
|
|||
writeln(stream, dbgRepr(slot.address, slot.typ))
|
||||
|
||||
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:
|
||||
writeVariable(stream, f.slots[i])
|
||||
write(stream, "***\n")
|
||||
|
||||
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:
|
||||
writeln(stream, f.slots[i].name)
|
||||
write(stream, "***\n")
|
||||
|
|
@ -115,7 +116,7 @@ proc ListVariables(stream: TFile, f: PExtendedFrame) =
|
|||
proc debugOut(msg: cstring) =
|
||||
# the *** *** markers are for easy recognition of debugger
|
||||
# output for external frontends.
|
||||
write(stdout, "*** emdb| ")
|
||||
write(stdout, "*** endb| ")
|
||||
write(stdout, msg)
|
||||
write(stdout, "***\n")
|
||||
|
||||
|
|
@ -131,14 +132,14 @@ proc findVariable(frame: PExtendedFrame, varname: cstring): int =
|
|||
|
||||
proc dbgShowCurrentProc(dbgFramePointer: PFrame) =
|
||||
if dbgFramePointer != nil:
|
||||
write(stdout, "*** emdb| now in proc: ")
|
||||
write(stdout, "*** endb| now in proc: ")
|
||||
write(stdout, dbgFramePointer.procname)
|
||||
write(stdout, " ***\n")
|
||||
else:
|
||||
write(stdout, "*** emdb| (procedure name not available) ***\n")
|
||||
write(stdout, "*** endb| (procedure name not available) ***\n")
|
||||
|
||||
proc dbgShowExecutionPoint() =
|
||||
write(stdout, "*** emdb| " & $framePtr.filename & "(" & $framePtr.line &
|
||||
write(stdout, "*** endb| " & $framePtr.filename & "(" & $framePtr.line &
|
||||
") " & $framePtr.procname & " ***\n")
|
||||
|
||||
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
|
||||
<ENTER> repeat the previous debugger command
|
||||
EXECUTING
|
||||
s, stepinto single step, stepping into routine calls
|
||||
n, stepover single step, without stepping into routine calls
|
||||
s, step single step, stepping into routine calls
|
||||
n, next single step, without stepping into routine calls
|
||||
f, skipcurrent continue execution until the current routine finishes
|
||||
c, continue continue execution until the next breakpoint
|
||||
i, ignore continue execution, ignore all breakpoints
|
||||
BREAKPOINTS
|
||||
b, setbreak <name> [fromline [toline]] [file]
|
||||
b, break <name> [fromline [toline]] [file]
|
||||
set a new breakpoint named 'name' for line and file
|
||||
if line or file are omitted the current one is used
|
||||
breakpoints display the entire breakpoint list
|
||||
disable <name> disable a breakpoint
|
||||
enable <name> enable a breakpoint
|
||||
DATA DISPLAY
|
||||
e, eval <exp> evaluate the expression <exp>
|
||||
o, out <file> <exp> evaluate <exp> and write it to <file>
|
||||
e, eval <expr> evaluate the expression <expr>
|
||||
o, out <file> <expr> evaluate <expr> and write it to <file>
|
||||
w, where display the current execution point
|
||||
stackframe [file] display current stack frame [and write it to file]
|
||||
u, up go up 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
|
||||
g, globals display available global variables
|
||||
maxdisplay <integer> set the display's recursion maximum
|
||||
|
|
@ -352,7 +353,7 @@ proc CommandPrompt() =
|
|||
dbgDown: int = 0 # how often we did go down
|
||||
|
||||
while again:
|
||||
write(stdout, "*** emdb| >>")
|
||||
write(stdout, "*** endb| >>")
|
||||
var tmp = readLine(stdin)
|
||||
if tmp.len > 0: dbgUser = tmp
|
||||
# now look what we have to do:
|
||||
|
|
@ -360,10 +361,10 @@ proc CommandPrompt() =
|
|||
var i = scanWord(dbgUser, dbgTemp, 0)
|
||||
case dbgTemp
|
||||
of "": InvalidCommand()
|
||||
of "s", "stepinto":
|
||||
of "s", "step":
|
||||
dbgState = dbStepInto
|
||||
again = false
|
||||
of "n", "stepover":
|
||||
of "n", "next":
|
||||
dbgState = dbStepOver
|
||||
dbgSkipToFrame = framePtr
|
||||
again = false
|
||||
|
|
@ -412,9 +413,9 @@ proc CommandPrompt() =
|
|||
dbgShowCurrentProc(dbgFramePtr)
|
||||
else:
|
||||
debugOut("[Warning] cannot go down any further ")
|
||||
of "callstack":
|
||||
of "bt", "backtrace":
|
||||
WriteStackTrace()
|
||||
of "b", "setbreak":
|
||||
of "b", "break":
|
||||
setBreakPoint(dbgUser, i)
|
||||
of "breakpoints":
|
||||
ListBreakPoints()
|
||||
|
|
@ -443,7 +444,7 @@ proc endbStep() =
|
|||
proc checkForBreakpoint() =
|
||||
var i = dbgBreakpointReached(framePtr.line)
|
||||
if i >= 0:
|
||||
write(stdout, "*** emdb| reached ")
|
||||
write(stdout, "*** endb| reached ")
|
||||
write(stdout, dbgBP[i].name)
|
||||
write(stdout, " in ")
|
||||
write(stdout, framePtr.filename)
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@
|
|||
#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
|
||||
Doug Lea and released to the public domain, as explained at
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2006 Andreas Rumpf
|
||||
# (c) Copyright 2008 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
|
|
@ -35,35 +35,34 @@ proc chckNil(p: pointer) {.inline, compilerproc.}
|
|||
|
||||
type
|
||||
PSafePoint = ptr TSafePoint
|
||||
TSafePoint {.compilerproc.} = record
|
||||
TSafePoint {.compilerproc, final.} = object
|
||||
prev: PSafePoint # points to next safe point ON THE STACK
|
||||
exc: ref E_Base
|
||||
status: int
|
||||
context: C_JmpBuf
|
||||
|
||||
var
|
||||
excHandler {.compilerproc, volatile.}: PSafePoint = nil
|
||||
excHandler {.compilerproc.}: PSafePoint = nil
|
||||
# list of exception handlers
|
||||
# a global variable for the root of all try blocks
|
||||
|
||||
proc reraiseException() =
|
||||
if excHandler != nil:
|
||||
if excHandler == nil:
|
||||
raise newException(ENoExceptionToReraise, "no exception to reraise")
|
||||
else:
|
||||
c_longjmp(excHandler.context, 1)
|
||||
|
||||
type
|
||||
PFrame = ptr TFrame
|
||||
TFrame {.importc, nodecl.} = record
|
||||
TFrame {.importc, nodecl, final.} = object
|
||||
prev: PFrame
|
||||
procname: CString
|
||||
line: int # current line number
|
||||
filename: CString
|
||||
len: int # length of slots (when not debugging always zero)
|
||||
|
||||
TTempFrame = record # used for recursion elimination in WriteStackTrace
|
||||
procname: CString
|
||||
line: int
|
||||
TTempFrame = tuple[ # used for recursion elimination in WriteStackTrace
|
||||
procname: CString, line: int]
|
||||
|
||||
var
|
||||
buf: string # cannot be allocated on the stack!
|
||||
|
|
@ -71,7 +70,7 @@ var
|
|||
# assert, as it raises an exception and
|
||||
# exception handler needs the buffer too
|
||||
|
||||
framePtr {.exportc, volatile.}: PFrame
|
||||
framePtr {.exportc.}: PFrame
|
||||
|
||||
tempFrames: array [0..255, TTempFrame] # cannot be allocated
|
||||
# on the stack!
|
||||
|
|
@ -82,8 +81,7 @@ proc auxWriteStackTrace(f: PFrame, s: var string) =
|
|||
i = 0
|
||||
total = 0
|
||||
while it != nil and i <= high(tempFrames):
|
||||
tempFrames[i].procname = it.procname
|
||||
tempFrames[i].line = it.line
|
||||
tempFrames[i] = (it.procname, it.line)
|
||||
inc(i)
|
||||
inc(total)
|
||||
it = it.prev
|
||||
|
|
@ -110,10 +108,10 @@ proc rawWriteStackTrace(s: var string) =
|
|||
auxWriteStackTrace(framePtr, s)
|
||||
|
||||
proc quitOrDebug() {.inline.} =
|
||||
when not defined(emdb):
|
||||
when not defined(endb):
|
||||
quit(1)
|
||||
else:
|
||||
emdbStep() # call the debugger
|
||||
endbStep() # call the debugger
|
||||
|
||||
proc raiseException(e: ref E_Base, ename: CString) =
|
||||
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
|
||||
c_longjmp(excHandler.context, 1)
|
||||
else:
|
||||
if cast[pointer](buf) != nil:
|
||||
if not isNil(buf):
|
||||
setLen(buf, 0)
|
||||
rawWriteStackTrace(buf)
|
||||
if e.msg != nil and e.msg[0] != '\0':
|
||||
|
|
@ -135,9 +133,7 @@ proc raiseException(e: ref E_Base, ename: CString) =
|
|||
add(buf, "]\n")
|
||||
writeToStdErr(buf)
|
||||
else:
|
||||
writeToStdErr("*** FATAL ERROR *** ")
|
||||
writeToStdErr(ename)
|
||||
writeToStdErr("\n")
|
||||
quitOrDebug()
|
||||
GC_enable()
|
||||
|
||||
|
|
@ -147,7 +143,8 @@ var
|
|||
proc internalAssert(file: cstring, line: int, cond: bool) {.compilerproc.} =
|
||||
if not cond:
|
||||
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)
|
||||
add(assertBuf, "[Assertion failure] file: ")
|
||||
add(assertBuf, file)
|
||||
|
|
@ -164,6 +161,11 @@ proc WriteStackTrace() =
|
|||
rawWriteStackTrace(s)
|
||||
writeToStdErr(s)
|
||||
|
||||
#proc stackTraceWrapper {.noconv.} =
|
||||
# writeStackTrace()
|
||||
|
||||
#addQuitProc(stackTraceWrapper)
|
||||
|
||||
var
|
||||
dbgAborting: bool # whether the debugger wants to abort
|
||||
|
||||
|
|
@ -171,6 +173,7 @@ proc signalHandler(sig: cint) {.exportc: "signalHandler", noconv.} =
|
|||
# print stack trace and quit
|
||||
var
|
||||
s = int(sig)
|
||||
GC_disable()
|
||||
setLen(buf, 0)
|
||||
rawWriteStackTrace(buf)
|
||||
|
||||
|
|
@ -185,6 +188,7 @@ proc signalHandler(sig: cint) {.exportc: "signalHandler", noconv.} =
|
|||
else: add(buf, "unknown signal\n")
|
||||
writeToStdErr(buf)
|
||||
dbgAborting = True # play safe here...
|
||||
GC_enable()
|
||||
quit(1) # always quit when SIGABRT
|
||||
|
||||
proc registerSignalHandler() =
|
||||
|
|
@ -204,12 +208,15 @@ assertBuf = newString(2048)
|
|||
setLen(buf, 0)
|
||||
setLen(assertBuf, 0)
|
||||
|
||||
proc raiseRangeError() {.compilerproc, noreturn.} =
|
||||
raise newException(EOutOfRange, "value out of range")
|
||||
proc raiseRangeError(val: biggestInt) {.compilerproc, noreturn.} =
|
||||
raise newException(EOutOfRange, "value " & $val & " out of range")
|
||||
|
||||
proc raiseIndexError() {.compilerproc, noreturn.} =
|
||||
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 =
|
||||
if i >= a and i <= b:
|
||||
return i
|
||||
|
|
@ -220,19 +227,19 @@ proc chckRange(i, a, b: int): int =
|
|||
if i >= a and i <= b:
|
||||
return i
|
||||
else:
|
||||
raiseRangeError()
|
||||
raiseRangeError(i)
|
||||
|
||||
proc chckRange64(i, a, b: int64): int64 {.compilerproc.} =
|
||||
if i >= a and i <= b:
|
||||
return i
|
||||
else:
|
||||
raiseRangeError()
|
||||
raiseRangeError(i)
|
||||
|
||||
proc chckRangeF(x, a, b: float): float =
|
||||
if x >= a and x <= b:
|
||||
return x
|
||||
else:
|
||||
raiseRangeError()
|
||||
raise newException(EOutOfRange, "value " & $x & " out of range")
|
||||
|
||||
proc chckNil(p: pointer) =
|
||||
if p == nil: c_raise(SIGSEGV)
|
||||
|
|
|
|||
630
lib/gc.nim
630
lib/gc.nim
|
|
@ -1,7 +1,7 @@
|
|||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2006 Andreas Rumpf
|
||||
# (c) Copyright 2008 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
|
|
@ -13,33 +13,39 @@
|
|||
# For a description of the algorithms used here see:
|
||||
# intern.html
|
||||
|
||||
#{.define: debugGC.} # we wish to debug the GC...
|
||||
{.define: debugGC.} # we wish to debug the GC...
|
||||
|
||||
#when defined(debugGC):
|
||||
# {.define: logGC.} # define if the GC should log some of its activities
|
||||
|
||||
{.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
|
||||
# wrong value, performance may be worse (this is not
|
||||
# for sure though), but GC still works; must be a power of two!
|
||||
const
|
||||
PageSize = 1024 * sizeof(int)
|
||||
RC_Increase = 7 * PageSize # is an additive increase
|
||||
PageShift = if sizeof(pointer) == 4: 12 else: 13
|
||||
PageSize = 1 shl PageShift # on 32 bit systems 4096
|
||||
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):
|
||||
const InitialThreshold = 64*1024
|
||||
const stressGC = True # GC is debugged; no need to stress it
|
||||
const stressGC = False
|
||||
else:
|
||||
const stressGC = False
|
||||
const InitialThreshold = RC_Increase
|
||||
# this may need benchmarking...
|
||||
|
||||
# things the System module thinks should be available:
|
||||
when defined(useDL) or defined(nativeDL):
|
||||
type
|
||||
TMallocInfo {.importc: "struct mallinfo", nodecl.} = record
|
||||
TMallocInfo {.importc: "struct mallinfo", nodecl, final.} = object
|
||||
arena: cint # non-mmapped space allocated from system
|
||||
ordblks: cint # number of free chunks
|
||||
smblks: cint # number of fastbin blocks
|
||||
|
|
@ -68,8 +74,7 @@ else: # not available:
|
|||
proc getTotalMem(): int = return -1
|
||||
|
||||
var
|
||||
rcThreshold: int = InitialThreshold
|
||||
cycleThreshold: int = InitialThreshold
|
||||
cycleThreshold: int = InitialCycleThreshold
|
||||
|
||||
memUsed: int = 0 # we have to keep track how much we have allocated
|
||||
|
||||
|
|
@ -113,11 +118,12 @@ type
|
|||
waNone, waRelease, waZctDecRef, waCycleDecRef, waCycleIncRef, waDebugIncRef
|
||||
|
||||
TCollectorData = int
|
||||
TCell = record
|
||||
TCell {.final.} = object
|
||||
refcount: TCollectorData # the refcount and bit flags
|
||||
typ: PNimType
|
||||
stackcount: int # stack counter for debugging
|
||||
drefc: int # real reference counter for debugging
|
||||
when stressGC:
|
||||
stackcount: int # stack counter for debugging
|
||||
drefc: int # real reference counter for debugging
|
||||
|
||||
PCell = ptr TCell
|
||||
|
||||
|
|
@ -145,6 +151,7 @@ proc extGetCellType(c: pointer): PNimType {.compilerproc.} =
|
|||
|
||||
proc internRefcount(p: pointer): int {.exportc: "getRefcount".} =
|
||||
result = int(usrToCell(p).refcount)
|
||||
if result < 0: result = 0
|
||||
|
||||
proc gcAlloc(size: int): pointer =
|
||||
result = alloc0(size)
|
||||
|
|
@ -162,7 +169,7 @@ proc GC_setStrategy(strategy: TGC_Strategy) =
|
|||
of gcOptimizeTime: nil
|
||||
|
||||
proc GC_enableMarkAndSweep() =
|
||||
cycleThreshold = InitialThreshold
|
||||
cycleThreshold = InitialCycleThreshold
|
||||
|
||||
proc GC_disableMarkAndSweep() =
|
||||
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
|
||||
# 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
|
||||
# can only be worse):
|
||||
|
|
@ -200,8 +207,7 @@ when BitsPerPage mod BitsPerUnit != 0:
|
|||
|
||||
# ------------------- cell set handling ------------------------------
|
||||
# A cellset consists of a hash table of page descriptors. A page
|
||||
# descriptor has a bit for
|
||||
# every Memalignment'th byte in the page.
|
||||
# descriptor has a bit for every Memalignment'th byte in the page.
|
||||
# However, only bits corresponding to addresses that start memory blocks
|
||||
# are set.
|
||||
# Page descriptors are also linked to a list; the list
|
||||
|
|
@ -217,17 +223,59 @@ type
|
|||
|
||||
TBitIndex = range[0..UnitsPerPage-1]
|
||||
|
||||
TPageDesc = record
|
||||
TPageDesc {.final.} = object
|
||||
next: PPageDesc # all nodes are connected with this pointer
|
||||
key: TAddress # start address at bit 0
|
||||
bits: array[TBitIndex, int] # a bit vector
|
||||
|
||||
PPageDescArray = ptr array[0..1000_000, PPageDesc]
|
||||
TCellSet = record
|
||||
TCellSet {.final.} = object
|
||||
counter, max: int
|
||||
head: PPageDesc
|
||||
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
|
||||
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
|
||||
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)
|
||||
h = cast[int](key) and 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
|
||||
t: PPageDesc
|
||||
u = cast[TAddress](cell)
|
||||
t = CellSetGet(s, u /% PageSize)
|
||||
t = CellSetGet(s, u shr PageShift)
|
||||
if t != nil:
|
||||
u = (u %% PageSize) /% MemAlignment
|
||||
result = (t.bits[u /% BitsPerUnit] and (1 shl (u %% BitsPerUnit))) != 0
|
||||
|
|
@ -315,7 +364,7 @@ proc incl(s: var TCellSet, cell: PCell) =
|
|||
u: TAddress
|
||||
t: PPageDesc
|
||||
u = cast[TAddress](cell)
|
||||
t = CellSetPut(s, u /% PageSize)
|
||||
t = CellSetPut(s, u shr PageShift)
|
||||
u = (u %% PageSize) /% MemAlignment
|
||||
t.bits[u /% BitsPerUnit] = t.bits[u /% BitsPerUnit] or
|
||||
(1 shl (u %% BitsPerUnit))
|
||||
|
|
@ -325,7 +374,7 @@ proc excl(s: var TCellSet, cell: PCell) =
|
|||
u: TAddress
|
||||
t: PPageDesc
|
||||
u = cast[TAddress](cell)
|
||||
t = CellSetGet(s, u /% PageSize)
|
||||
t = CellSetGet(s, u shr PageShift)
|
||||
if t != nil:
|
||||
u = (u %% PageSize) /% MemAlignment
|
||||
t.bits[u /% BitsPerUnit] = (t.bits[u /% BitsPerUnit] and
|
||||
|
|
@ -342,7 +391,7 @@ iterator elements(t: TCellSet): PCell {.inline.} =
|
|||
var j = 0
|
||||
while w != 0: # test all remaining bits for zero
|
||||
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)
|
||||
inc(j)
|
||||
w = w shr 1
|
||||
|
|
@ -354,68 +403,121 @@ iterator elements(t: TCellSet): PCell {.inline.} =
|
|||
proc testPageDescs() =
|
||||
var root: TCellSet
|
||||
CellSetInit(root)
|
||||
var u = 10_000
|
||||
while u <= 20_000:
|
||||
incl(root, cast[PCell](u))
|
||||
inc(u, 8)
|
||||
for cell in elements(root):
|
||||
c_fprintf(c_stdout, "%ld\n", cast[int](cell))
|
||||
#var u = 10_000
|
||||
#while u <= 20_000:
|
||||
# incl(root, cast[PCell](u))
|
||||
# inc(u, 8)
|
||||
|
||||
# testPageDescs()
|
||||
incl(root, cast[PCell](0x81cdfb8))
|
||||
for cell in elements(root):
|
||||
c_fprintf(c_stdout, "%p\n", cast[int](cell))
|
||||
|
||||
#testPageDescs()
|
||||
|
||||
when defined(debugGC):
|
||||
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) =
|
||||
c_fprintf(c_stdout, "%s: %p\n", msg, p)
|
||||
|
||||
|
||||
when traceGC:
|
||||
# traceGC is a special switch to enable extensive debugging
|
||||
type
|
||||
TCellState = enum
|
||||
csAllocated, csZctFreed, csCycFreed
|
||||
|
||||
proc cellSetInit(s: var TSlowSet) =
|
||||
s.L = 0
|
||||
s.cap = 4096
|
||||
s.d = cast[PCellArray](gcAlloc(s.cap * sizeof(PCell)))
|
||||
|
||||
proc cellSetDeinit(s: var TSlowSet) =
|
||||
s.L = 0
|
||||
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
|
||||
states: array[TCellState, TSlowSet] # TCellSet]
|
||||
|
||||
proc traceCell(c: PCell, state: TCellState) =
|
||||
case state
|
||||
of csAllocated:
|
||||
if c in states[csAllocated]:
|
||||
writeCell("attempt to alloc a already allocated cell", c)
|
||||
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)
|
||||
|
||||
template gcTrace(cell, state: expr): stmt =
|
||||
when traceGC: traceCell(cell, state)
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
type
|
||||
PStackCells = ptr array[0..1000_0000, PCell]
|
||||
TCountTables = record # this contains the zero count and
|
||||
# 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
|
||||
# forward declarations:
|
||||
proc collectCT(gch: var TGcHeap)
|
||||
proc IsOnStack(p: pointer): bool
|
||||
proc forAllChildren(cell: PCell, op: TWalkOp)
|
||||
proc collectCycles(gch: var TGcHeap)
|
||||
|
||||
proc addStackCell(ct: var TCountTables, cell: PCell) =
|
||||
if ct.stackLen >= ct.stackMax:
|
||||
ct.stackMax = ct.stackMax * 3 div 2
|
||||
ct.stackCells = cast[PStackCells](realloc(ct.stackCells, ct.stackMax *
|
||||
sizeof(PCell)))
|
||||
if ct.stackCells == nil: raiseOutOfMem()
|
||||
ct.stackCells[ct.stackLen] = cell
|
||||
inc(ct.stackLen)
|
||||
|
||||
var
|
||||
stackBottom: pointer
|
||||
ct: TCountTables
|
||||
|
||||
proc GC_invariant(): bool =
|
||||
result = True
|
||||
when stressGC:
|
||||
if recGcLock == 0:
|
||||
GC_disable()
|
||||
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)
|
||||
|
||||
dbgLineHook = GCdebugHook
|
||||
proc reprAny(p: pointer, typ: PNimType): string {.compilerproc.}
|
||||
# we need the prototype here for debugging purposes
|
||||
|
||||
proc prepareDealloc(cell: PCell) =
|
||||
if cell.typ.finalizer != nil:
|
||||
|
|
@ -433,79 +535,95 @@ proc prepareDealloc(cell: PCell) =
|
|||
else:
|
||||
memUsed = memUsed - cell.typ.size
|
||||
|
||||
proc checkZCT(): bool =
|
||||
if recGcLock >= 1: return true # prevent endless recursion
|
||||
inc(recGcLock)
|
||||
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)
|
||||
|
||||
proc GC_invariant(): bool =
|
||||
if recGcLock >= 1: return true # prevent endless recursion
|
||||
inc(recGcLock)
|
||||
result = True
|
||||
block checks:
|
||||
if not checkZCT():
|
||||
result = false
|
||||
break checks
|
||||
# set counters back to zero:
|
||||
for c in elements(gch.AT):
|
||||
var t = c.typ
|
||||
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)
|
||||
when stressGC:
|
||||
for c in elements(gch.AT):
|
||||
var rc = c.refcount
|
||||
if rc < 0: rc = 0
|
||||
if c.drefc > rc + c.stackcount:
|
||||
result = false # failed
|
||||
c_fprintf(c_stdout,
|
||||
"broken cell: %p, refc: %ld, stack: %ld, real: %ld\n",
|
||||
c, c.refcount, c.stackcount, c.drefc)
|
||||
break checks
|
||||
dec(recGcLock)
|
||||
|
||||
when stressGC:
|
||||
proc GCdebugHook() =
|
||||
if not GC_invariant():
|
||||
assert(false)
|
||||
|
||||
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
|
||||
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
|
||||
init(gch.zct)
|
||||
CellSetInit(gch.at)
|
||||
init(gch.stackCells)
|
||||
gch.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)
|
||||
write(stdout, reprAny(cellToUsr(c), c.typ))
|
||||
dec(recGcLock)
|
||||
|
||||
proc writeGraph() =
|
||||
{.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
|
||||
inc(recGcLock)
|
||||
result = True
|
||||
# set counters back to zero:
|
||||
for c in elements(ct.AT):
|
||||
c.drefc = 0
|
||||
for c in elements(ct.AT):
|
||||
forAllChildren(c, waDebugIncRef)
|
||||
for c in elements(ct.AT):
|
||||
if c.drefc > c.refcount - c.stackcount:
|
||||
result = false # failed
|
||||
c_fprintf(c_stdout,
|
||||
"broken cell: %p, refc: %ld, stack: %ld, real: %ld\n",
|
||||
c, c.refcount, c.stackcount, c.drefc)
|
||||
dec(recGcLock)
|
||||
|
||||
proc seqCheck(cell: PCell): bool =
|
||||
assert(cell.typ != nil)
|
||||
if cell.typ.kind in {tySequence, tyString}:
|
||||
result = cell.refcount - cell.stackcount <= 1
|
||||
else:
|
||||
result = true
|
||||
|
||||
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(seqCheck(cell))
|
||||
when stressGC: assert(cell in gch.AT)
|
||||
dec(cell.refcount)
|
||||
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.} =
|
||||
assert(seqCheck(cell))
|
||||
inc(cell.refcount)
|
||||
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)
|
||||
when stressGC: assert(checkZCT())
|
||||
|
||||
proc asgnRef(dest: ppointer, src: pointer) =
|
||||
# the code generator calls this proc!
|
||||
|
|
@ -514,18 +632,18 @@ proc asgnRef(dest: ppointer, src: pointer) =
|
|||
if src != nil: incRef(usrToCell(src))
|
||||
if dest^ != nil: decRef(usrToCell(dest^))
|
||||
dest^ = src
|
||||
#assert(checkRefc())
|
||||
when stressGC: assert(GC_invariant())
|
||||
|
||||
proc unsureAsgnRef(dest: ppointer, src: pointer) =
|
||||
if not IsOnStack(dest):
|
||||
if src != nil: incRef(usrToCell(src))
|
||||
if dest^ != nil: decRef(usrToCell(dest^))
|
||||
dest^ = src
|
||||
#assert(checkRefc())
|
||||
when stressGC: assert(GC_invariant())
|
||||
|
||||
proc restore(cell: PCell) =
|
||||
if cell notin ct.newAT:
|
||||
incl(ct.newAT, Cell)
|
||||
if cell notin gch.newAT:
|
||||
incl(gch.newAT, Cell)
|
||||
forAllChildren(cell, waCycleIncRef)
|
||||
|
||||
proc doOperation(p: pointer, op: TWalkOp) =
|
||||
|
|
@ -536,19 +654,15 @@ proc doOperation(p: pointer, op: TWalkOp) =
|
|||
of waNone: assert(false)
|
||||
of waRelease: decRef(cell) # DEAD CODE!
|
||||
of waZctDecRef:
|
||||
assert(cell.refcount > 0)
|
||||
assert(seqCheck(cell))
|
||||
dec(cell.refcount)
|
||||
if cell.refcount == 0:
|
||||
incl(ct.newZCT, cell)
|
||||
decRef(cell)
|
||||
of waCycleDecRef:
|
||||
assert(cell.refcount != 0)
|
||||
assert(cell.refcount > 0)
|
||||
dec(cell.refcount)
|
||||
of waCycleIncRef:
|
||||
inc(cell.refcount) # restore proper reference counts!
|
||||
restore(cell)
|
||||
of waDebugIncRef:
|
||||
inc(cell.drefc)
|
||||
when stressGC: inc(cell.drefc)
|
||||
|
||||
type
|
||||
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)
|
||||
|
||||
proc forAllChildrenAux(dest: Pointer, mt: PNimType, op: TWalkOp) =
|
||||
const
|
||||
handledTypes = {tyArray, tyArrayConstr, tyOpenArray, tyRef,
|
||||
tyString, tySequence, tyObject, tyPureObject, tyTuple}
|
||||
var
|
||||
d = cast[TAddress](dest)
|
||||
if dest == nil: return # nothing to do
|
||||
case mt.Kind
|
||||
of tyArray, tyArrayConstr, tyOpenArray:
|
||||
for i in 0..(mt.size div mt.base.size)-1:
|
||||
forAllChildrenAux(cast[pointer](d +% i *% mt.base.size), mt.base, op)
|
||||
if mt.base.kind in handledTypes:
|
||||
for i in 0..(mt.size div mt.base.size)-1:
|
||||
forAllChildrenAux(cast[pointer](d +% i *% mt.base.size), mt.base, op)
|
||||
of tyRef, tyString, tySequence: # leaf:
|
||||
doOperation(cast[ppointer](d)^, op)
|
||||
of tyRecord, tyObject, tyTuple:
|
||||
of tyObject, tyTuple, tyPureObject:
|
||||
forAllSlotsAux(dest, mt.node, op)
|
||||
else: nil
|
||||
|
||||
|
|
@ -608,6 +726,13 @@ proc forAllChildren(cell: PCell, op: TWalkOp) =
|
|||
when defined(debugGC):
|
||||
if cell.typ == nil:
|
||||
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)
|
||||
case cell.typ.Kind
|
||||
of tyRef: # common case
|
||||
|
|
@ -625,36 +750,36 @@ proc forAllChildren(cell: PCell, op: TWalkOp) =
|
|||
proc checkCollection() {.inline.} =
|
||||
# checks if a collection should be done
|
||||
if recGcLock == 0:
|
||||
if memUsed >= rcThreshold or stressGC:
|
||||
collectCT(ct)
|
||||
when defined(debugGC):
|
||||
write(stdout, "threshold is now: ")
|
||||
writeln(stdout, rcThreshold)
|
||||
collectCT(gch)
|
||||
|
||||
proc newObj(typ: PNimType, size: int): pointer =
|
||||
# generates a new object and sets its reference counter to 0
|
||||
var
|
||||
res: PCell
|
||||
when stressGC: assert(checkZCT())
|
||||
assert(typ.kind in {tyRef, tyString, tySequence})
|
||||
# check if we have to collect:
|
||||
checkCollection()
|
||||
res = cast[PCell](Alloc0(size + sizeof(TCell)))
|
||||
when stressGC: assert((cast[TAddress](res) and (MemAlignment-1)) == 0)
|
||||
if res == nil: raiseOutOfMem()
|
||||
when defined(nimSize):
|
||||
memUsed = memUsed + nimSize(res)
|
||||
else:
|
||||
memUsed = memUsed + size
|
||||
|
||||
res.refcount = 0
|
||||
# now it is buffered in the ZCT
|
||||
res.typ = typ
|
||||
incl(ct.zct, res) # its refcount is zero, so add it to the ZCT
|
||||
incl(ct.at, res) # add it to the any table too
|
||||
ct.mask = ct.mask or cast[TAddress](res)
|
||||
res.refcount = -gch.zct.len
|
||||
add(gch.zct, res) # its refcount is zero, so add it to the ZCT
|
||||
incl(gch.at, res) # add it to the any table too
|
||||
gch.mask = gch.mask or cast[TAddress](res)
|
||||
when defined(debugGC):
|
||||
writeCell("new cell", res)
|
||||
assert(gcInvariant())
|
||||
when defined(logGC): writeCell("new cell", res)
|
||||
gcTrace(res, csAllocated)
|
||||
result = cellToUsr(res)
|
||||
assert(res.typ == typ)
|
||||
when stressGC: assert(checkZCT())
|
||||
|
||||
proc newSeq(typ: PNimType, len: int): pointer =
|
||||
# XXX: overflow checks!
|
||||
|
|
@ -665,16 +790,19 @@ proc newSeq(typ: PNimType, len: int): pointer =
|
|||
proc growObj(old: pointer, newsize: int): pointer =
|
||||
var
|
||||
res, ol: PCell
|
||||
when stressGC: assert(checkZCT())
|
||||
checkCollection()
|
||||
ol = usrToCell(old)
|
||||
assert(ol.typ.kind in {tyString, tySequence})
|
||||
assert(seqCheck(ol))
|
||||
when defined(nimSize):
|
||||
memUsed = memUsed - nimSize(ol)
|
||||
else:
|
||||
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](gcAlloc(newsize + sizeof(TCell)))
|
||||
#copyMem(res, ol, nimSize(ol))
|
||||
assert((cast[TAddress](res) and (MemAlignment-1)) == 0)
|
||||
when defined(nimSize):
|
||||
memUsed = memUsed + nimSize(res)
|
||||
else:
|
||||
|
|
@ -682,74 +810,69 @@ proc growObj(old: pointer, newsize: int): pointer =
|
|||
|
||||
if res != ol:
|
||||
if res == nil: raiseOutOfMem()
|
||||
excl(ct.zct, ol) # remove old pointer in any case:
|
||||
# It may have a refcount > 0 and is still in the ZCT.
|
||||
# So do it safe here and remove it anyway.
|
||||
excl(ct.at, ol)
|
||||
if res.refcount == 0:
|
||||
# store new pointer in ZCT, if refcount == 0:
|
||||
incl(ct.zct, res)
|
||||
incl(ct.at, res)
|
||||
ct.mask = ct.mask or cast[TAddress](res)
|
||||
when defined(debugGC):
|
||||
if res.refcount <= 0:
|
||||
assert(gch.zct.d[-res.refcount] == ol)
|
||||
gch.zct.d[-res.refcount] = res
|
||||
excl(gch.at, ol)
|
||||
incl(gch.at, res)
|
||||
gch.mask = gch.mask or cast[TAddress](res)
|
||||
when defined(logGC):
|
||||
writeCell("growObj old cell", ol)
|
||||
writeCell("growObj new cell", res)
|
||||
gcTrace(ol, csZctFreed)
|
||||
gcTrace(res, csAllocated)
|
||||
result = cellToUsr(res)
|
||||
#assert(checkRefc())
|
||||
when stressGC: assert(checkZCT())
|
||||
|
||||
proc collectCycles() =
|
||||
when defined(debugGC):
|
||||
echo("collecting cycles!\n")
|
||||
proc collectCycles(gch: var TGcHeap) =
|
||||
when defined(logGC):
|
||||
c_fprintf(c_stdout, "collecting cycles!\n")
|
||||
|
||||
# step 1: pretend that any node is dead
|
||||
for c in elements(ct.at):
|
||||
for c in elements(gch.at):
|
||||
forallChildren(c, waCycleDecRef)
|
||||
CellSetInit(ct.newAt)
|
||||
CellSetInit(gch.newAt)
|
||||
# step 2: restore life cells
|
||||
for c in elements(ct.at):
|
||||
for c in elements(gch.at):
|
||||
if c.refcount > 0: restore(c)
|
||||
# step 3: free dead cells:
|
||||
for cell in elements(ct.at):
|
||||
for cell in elements(gch.at):
|
||||
if cell.refcount == 0:
|
||||
assert(cell notin ct.zct)
|
||||
# We free an object that is part of a cycle here. Its children
|
||||
# may have been freed already. Thus the finalizer could access
|
||||
# garbage. To handle this case properly we need two passes for
|
||||
# freeing here which is too expensive. We just don't call the
|
||||
# finalizer for now. YYY: Any better ideas?
|
||||
prepareDealloc(cell)
|
||||
dealloc(cell)
|
||||
when defined(debugGC):
|
||||
gcTrace(cell, csCycFreed)
|
||||
when defined(logGC):
|
||||
writeCell("cycle collector dealloc cell", cell)
|
||||
CellSetDeinit(ct.at)
|
||||
ct.at = ct.newAt
|
||||
#ct.newAt = nil
|
||||
when reallyDealloc: dealloc(cell)
|
||||
CellSetDeinit(gch.at)
|
||||
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:
|
||||
var cell = usrToCell(p)
|
||||
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
|
||||
# always in the AT)
|
||||
inc(cell.refcount)
|
||||
inc(cell.stackcount)
|
||||
addStackCell(ct, cell)
|
||||
incRef(cell)
|
||||
when stressGC: inc(cell.stackcount)
|
||||
add(gch.stackCells, cell)
|
||||
|
||||
proc unmarkStackAndRegisters() =
|
||||
for i in 0 .. ct.stackLen-1:
|
||||
var cell = ct.stackCells[i]
|
||||
proc unmarkStackAndRegisters(gch: var TGcHeap) =
|
||||
when stressGC: assert(checkZCT())
|
||||
for i in 0 .. gch.stackCells.len-1:
|
||||
var cell = gch.stackCells.d[i]
|
||||
assert(cell.refcount > 0)
|
||||
when defined(debugGC):
|
||||
if cell.stackcount == 0:
|
||||
writeGraph()
|
||||
writePtr("broken stackcount", cellToUsr(cell))
|
||||
assert(cell.stackcount > 0)
|
||||
dec(cell.refcount)
|
||||
dec(cell.stackcount)
|
||||
if cell.refcount == 0:
|
||||
incl(ct.zct, cell)
|
||||
ct.stackLen = 0 # reset to zero
|
||||
when stressGC:
|
||||
assert(cell.stackcount > 0)
|
||||
dec(cell.stackcount)
|
||||
decRef(cell)
|
||||
gch.stackCells.len = 0 # reset to zero
|
||||
when stressGC: assert(checkZCT())
|
||||
|
||||
# ----------------- stack management --------------------------------------
|
||||
# inspired from Smart Eiffel (c)
|
||||
|
|
@ -765,7 +888,7 @@ when defined(sparc): # For SPARC architecture.
|
|||
stackTop: array[0..1, pointer]
|
||||
result = p >= addr(stackTop[0]) and p <= stackBottom
|
||||
|
||||
proc markStackAndRegisters() =
|
||||
proc markStackAndRegisters(gch: var TGcHeap) =
|
||||
when defined(sparcv9):
|
||||
asm " flushw"
|
||||
else:
|
||||
|
|
@ -780,7 +903,7 @@ when defined(sparc): # For SPARC architecture.
|
|||
sp = addr(stackTop[0])
|
||||
# Addresses decrease as the stack grows.
|
||||
while sp <= max:
|
||||
gcMark(sp^)
|
||||
gcMark(gch, sp^)
|
||||
sp = cast[ppointer](cast[TAddress](sp) +% sizeof(pointer))
|
||||
|
||||
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
|
||||
# in a platform independant way
|
||||
|
||||
proc markStackAndRegisters() =
|
||||
proc markStackAndRegisters(gch: var TGcHeap) =
|
||||
var
|
||||
max = stackBottom
|
||||
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,
|
||||
# otherwise sp would be below the registers structure).
|
||||
while sp >= max:
|
||||
gcMark(sp^)
|
||||
gcMark(gch, sp^)
|
||||
sp = cast[ppointer](cast[TAddress](sp) -% sizeof(pointer))
|
||||
|
||||
else:
|
||||
|
|
@ -826,7 +949,7 @@ else:
|
|||
stackTop: array [0..1, pointer]
|
||||
result = p >= addr(stackTop[0]) and p <= stackBottom
|
||||
|
||||
proc markStackAndRegisters() =
|
||||
proc markStackAndRegisters(gch: var TGcHeap) =
|
||||
var
|
||||
max = stackBottom
|
||||
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.
|
||||
sp = cast[ppointer](addr(registers))
|
||||
while sp <= max:
|
||||
gcMark(sp^)
|
||||
gcMark(gch, sp^)
|
||||
sp = cast[ppointer](cast[TAddress](sp) +% sizeof(pointer))
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# end of non-portable code
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
proc CollectZCT =
|
||||
CellSetInit(ct.newZCT)
|
||||
for c in elements(ct.zct):
|
||||
if c.refcount == 0:
|
||||
# if != 0 the reference count has been increased, so this does not
|
||||
# belong to the ZCT. We simply do nothing - it won't appear in the newZCT
|
||||
# anyway.
|
||||
# We are about to free the object, call the finalizer BEFORE its
|
||||
# children are deleted as well, because otherwise the finalizer may
|
||||
# access invalid memory. This is done by prepareDealloc():
|
||||
prepareDealloc(c)
|
||||
forAllChildren(c, waZctDecRef)
|
||||
assert(c.refcount == 0) # should still be zero
|
||||
excl(ct.at, c)
|
||||
excl(ct.newZCT, c) # BUGFIX
|
||||
when defined(debugGC):
|
||||
writeCell("zct dealloc cell", c)
|
||||
dealloc(c)
|
||||
CellSetDeinit(ct.zct)
|
||||
ct.zct = ct.newZCT
|
||||
#ct.newZCT = nil
|
||||
proc CollectZCT(gch: var TGcHeap) =
|
||||
while gch.zct.len > 0:
|
||||
var c = gch.zct.d[0]
|
||||
assert(c.refcount <= 0)
|
||||
# remove from ZCT:
|
||||
gch.zct.d[0] = gch.zct.d[gch.zct.len-1]
|
||||
gch.zct.d[0].refcount = 0
|
||||
dec(gch.zct.len)
|
||||
# We are about to free the object, call the finalizer BEFORE its
|
||||
# children are deleted as well, because otherwise the finalizer may
|
||||
# access invalid memory. This is done by prepareDealloc():
|
||||
gcTrace(c, csZctFreed)
|
||||
prepareDealloc(c)
|
||||
forAllChildren(c, waZctDecRef)
|
||||
excl(gch.at, c)
|
||||
when defined(logGC):
|
||||
writeCell("zct dealloc cell", c)
|
||||
#when defined(debugGC) and defined(nimSize): zeroMem(c, nimSize(c))
|
||||
when reallyDealloc: dealloc(c)
|
||||
|
||||
proc collectCT(ct: var TCountTables) =
|
||||
when defined(debugGC):
|
||||
proc collectCT(gch: var TGcHeap) =
|
||||
when defined(logGC):
|
||||
c_fprintf(c_stdout, "collecting zero count table; stack size: %ld\n",
|
||||
stackSize())
|
||||
markStackAndRegisters()
|
||||
assert(GC_invariant())
|
||||
while True:
|
||||
collectZCT()
|
||||
if ct.zct.counter == 0: break
|
||||
# ``counter`` counts the pages, but zero pages means zero cells
|
||||
|
||||
when defined(cycleGC):
|
||||
# still over the cycle threshold?
|
||||
if memUsed >= cycleThreshold or stressGC:
|
||||
# collect the cyclic things:
|
||||
assert(ct.zct.counter == 0)
|
||||
assert(GC_invariant())
|
||||
collectCycles()
|
||||
|
||||
# recompute the thresholds:
|
||||
rcThreshold = (memUsed div RC_increase + 1) * RC_Increase
|
||||
cycleThreshold = memUsed * cycleIncrease
|
||||
|
||||
assert(GC_invariant())
|
||||
unmarkStackAndRegisters()
|
||||
when stressGC: assert(checkZCT())
|
||||
if gch.zct.len >= ZctThreshold or memUsed >= cycleThreshold or stressGC:
|
||||
markStackAndRegisters(gch)
|
||||
when stressGC: assert(GC_invariant())
|
||||
collectZCT(gch)
|
||||
when stressGC: assert(GC_invariant())
|
||||
assert(gch.zct.len == 0)
|
||||
when defined(cycleGC):
|
||||
if memUsed >= cycleThreshold or stressGC:
|
||||
when defined(logGC):
|
||||
c_fprintf(c_stdout, "collecting cycles; memory used: %ld\n", memUsed)
|
||||
collectCycles(gch)
|
||||
cycleThreshold = max(InitialCycleThreshold, memUsed * cycleIncrease)
|
||||
when defined(logGC):
|
||||
c_fprintf(c_stdout, "now used: %ld; threshold: %ld\n",
|
||||
memUsed, cycleThreshold)
|
||||
unmarkStackAndRegisters(gch)
|
||||
when stressGC: assert(GC_invariant())
|
||||
|
||||
proc GC_fullCollect() =
|
||||
var oldThreshold = cycleThreshold
|
||||
cycleThreshold = 0 # forces cycle collection
|
||||
collectCT(ct)
|
||||
collectCT(gch)
|
||||
cycleThreshold = oldThreshold
|
||||
|
|
|
|||
51
lib/hti.nim
51
lib/hti.nim
|
|
@ -10,29 +10,38 @@
|
|||
type # This should be he same as ast.TTypeKind
|
||||
# some enum fields are not used at runtime
|
||||
TNimKind = enum
|
||||
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,
|
||||
tyNone, # 0
|
||||
tyBool, # 1
|
||||
tyChar, # 2
|
||||
tyEmptySet, # 3
|
||||
tyArrayConstr, # 4
|
||||
tyNil, # 5
|
||||
tyGeneric, # 6
|
||||
tyGenericInst, # 7
|
||||
tyGenericParam, # 8
|
||||
tyEnum, # 9
|
||||
tyAnyEnum, # 10
|
||||
tyArray, # 11
|
||||
tyObject, # 12
|
||||
tyTuple, # 13
|
||||
tySet, # 14
|
||||
tyRange, # 15
|
||||
tyPtr, # 16
|
||||
tyRef, # 17
|
||||
tyVar, # 18
|
||||
tySequence, # 19
|
||||
tyProc, # 20
|
||||
tyPointer, # 21
|
||||
tyOpenArray, # 22
|
||||
tyString, # 23
|
||||
tyCString, # 24
|
||||
tyForward, # 25
|
||||
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
|
||||
TNimNode {.compilerproc.} = record
|
||||
TNimNode {.compilerproc, final.} = object
|
||||
kind: TNimNodeKind
|
||||
offset: int
|
||||
typ: ptr TNimType
|
||||
|
|
@ -40,7 +49,7 @@ type # This should be he same as ast.TTypeKind
|
|||
len: int
|
||||
sons: ptr array [0..0x7fff, ptr TNimNode]
|
||||
|
||||
TNimType {.compilerproc.} = record
|
||||
TNimType {.compilerproc, final.} = object
|
||||
size: int
|
||||
kind: TNimKind
|
||||
base: ptr TNimType
|
||||
|
|
|
|||
|
|
@ -10,8 +10,7 @@
|
|||
# 64 bit integers for platforms that don't have those
|
||||
|
||||
type
|
||||
IInt64 = record # "internal" int64
|
||||
lo, hi: int32
|
||||
IInt64 = tuple[lo, hi: int32]
|
||||
|
||||
proc cmpI64(x, y: IInt64): int32 {.compilerproc.} =
|
||||
result = x.hi -% y.hi
|
||||
|
|
|
|||
218
lib/math.nim
218
lib/math.nim
|
|
@ -1,75 +1,22 @@
|
|||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2006 Andreas Rumpf
|
||||
# (c) Copyright 2008 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
|
||||
|
||||
# math routines
|
||||
|
||||
# interface
|
||||
## Basic math routines for Nimrod.
|
||||
## This module is available for the ECMAScript target.
|
||||
|
||||
{.push debugger:off .} # the user does not want to trace a part
|
||||
# of the standard library!
|
||||
|
||||
{.push checks:off, line_dir:off, stack_trace:off.}
|
||||
|
||||
proc nextPowerOfTwo*(x: int): int
|
||||
## returns the nearest power of two, so that
|
||||
## 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.
|
||||
when defined(Posix):
|
||||
{.passl: "-lm".}
|
||||
|
||||
type
|
||||
TFloatClass* = enum ## describes the class a floating point value belongs to.
|
||||
|
|
@ -82,34 +29,11 @@ type
|
|||
fcInf, ## value is positive 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
|
||||
## `TFloatClass`
|
||||
## `TFloatClass`.
|
||||
|
||||
# implementation
|
||||
|
||||
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 =
|
||||
# ECMAScript and most C compilers have no classify:
|
||||
if x == 0.0:
|
||||
if 1.0/x == 1.0/0.0:
|
||||
return fcZero
|
||||
|
|
@ -122,10 +46,130 @@ proc classify(x: float): TFloatClass =
|
|||
return fcNormal
|
||||
# XXX: fcSubnormal is not detected!
|
||||
|
||||
proc randomize() = srand(gettime(nil))
|
||||
proc random(max: int): int = return rand() mod max
|
||||
|
||||
proc isPowerOfTwo(x: int): bool = return (x and -x) == x
|
||||
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 random(max: int): int = return rand() mod max
|
||||
|
||||
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.}
|
||||
|
|
|
|||
203
lib/memman.nim
203
lib/memman.nim
|
|
@ -37,24 +37,24 @@ const
|
|||
realFli = MaxFli - fliOffset
|
||||
|
||||
type
|
||||
TFreePtr = record
|
||||
TFreePtr {.final.} = object
|
||||
prev, next: PBhdr
|
||||
Pbhdr = ptr Tbhdr
|
||||
Tbhdr = record
|
||||
Tbhdr {.final.} = object
|
||||
prevHdr: Pbhdr # this is just valid if the first bit of size is set
|
||||
size: int # the size is stored in bytes
|
||||
# bit 0 indicates whether the block is used and
|
||||
# bit 1 allows to know whether the previous block is free
|
||||
freePtr: TFreePtr # at this offset bhdr.buffer starts (was a union in the
|
||||
# C version)
|
||||
TAreaInfo = record # This structure is embedded at the beginning of each
|
||||
# area, giving us enough information to cope with a set
|
||||
# of areas
|
||||
TAreaInfo {.final.} = object # This structure is embedded at the beginning
|
||||
# of each area, giving us enough information
|
||||
# to cope with a set of areas
|
||||
theEnd: Pbhdr
|
||||
next: PAreaInfo
|
||||
PAreaInfo = ptr TAreaInfo
|
||||
|
||||
TLSF = record
|
||||
TLSF {.final.} = object
|
||||
tlsf_signature: int32 # the TLSF's structure signature
|
||||
usedSize, maxSize: int
|
||||
areaHead: PAreaInfo # A linked list holding all the existing areas
|
||||
|
|
@ -147,6 +147,7 @@ elif defined(windows):
|
|||
if result == nil: raiseOutOfMem()
|
||||
|
||||
else:
|
||||
{.warning: "Generic code for allocating pages is used".}
|
||||
# generic implementation relying on malloc:
|
||||
proc malloc(size: int): pointer {.nodecl, importc.}
|
||||
|
||||
|
|
@ -155,6 +156,124 @@ else:
|
|||
result = malloc(size)
|
||||
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
|
||||
|
||||
|
|
@ -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.} =
|
||||
b.freePtr.prev = nil
|
||||
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] = b
|
||||
set_bit(sl, t.slBitmap[fl])
|
||||
|
|
@ -295,9 +414,6 @@ proc processArea(area: pointer, size: int): Pbhdr =
|
|||
# ----------------------------------------------------------------------------
|
||||
# Begin of the allocator code
|
||||
|
||||
var
|
||||
mp: pointer # default memory pool.
|
||||
|
||||
proc initMemoryPool(memPoolSize: int, memPool: pointer): int =
|
||||
var
|
||||
t: PLSF
|
||||
|
|
@ -307,16 +423,14 @@ proc initMemoryPool(memPoolSize: int, memPool: pointer): int =
|
|||
writeToStdErr("initMemoryPool(): memory_pool invalid\n")
|
||||
return -1
|
||||
|
||||
if (memPool and ptrMask) != 0:
|
||||
if (cast[TAddress](memPool) and ptrMask) != 0:
|
||||
writeToStdErr("initMemoryPool(): memPool must be aligned to a word\n")
|
||||
return -1
|
||||
t = cast[PLSF](memPool)
|
||||
# Check if already initialised
|
||||
if t.signature == tlsfSignature:
|
||||
mp = memPool
|
||||
b = getNextBlock(mp, roundupSize(sizeof(TLSF)))
|
||||
b = getNextBlock(memPool, roundupSize(sizeof(TLSF)))
|
||||
return b.size and blockSize
|
||||
mp = memPool
|
||||
zeroMem(memPool, sizeof(TLSF))
|
||||
|
||||
t.signature = tlsfSignature
|
||||
|
|
@ -456,7 +570,7 @@ proc freeEx(p: pointer, t: var TLSF) =
|
|||
b.freePtr.prev = nil
|
||||
b.freePtr.next = nil
|
||||
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)
|
||||
extractBlock(tmpB, t, fl, sl)
|
||||
inc(b.size, (tmpB.size and blockSize) + bhdrOverhead)
|
||||
|
|
@ -549,51 +663,30 @@ proc ansiCrealloc(p: pointer, newSize: int, t: var TLSF): pointer =
|
|||
else:
|
||||
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
|
||||
initMemoryPool(areaSize, 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)
|
||||
}
|
||||
#endif
|
||||
var
|
||||
t: PLSF
|
||||
b, ib: Pbhdr
|
||||
|
||||
TLSF_ACQUIRE_LOCK(&((tlsf_t *)mp)->lock)
|
||||
t = cast[PLSF](memPool)
|
||||
|
||||
ret = malloc_ex(size, mp)
|
||||
zeroMem(area, areaSize)
|
||||
|
||||
TLSF_RELEASE_LOCK(&((tlsf_t *)mp)->lock)
|
||||
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))
|
||||
|
||||
return ret
|
||||
}
|
||||
t.used_size = memPoolSize - (b.size and blockSize)
|
||||
t.max_size = t.used_size
|
||||
|
||||
void tlsf_free(void *p)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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
|
||||
}
|
||||
# XXX
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
|
||||
Nimrod's Runtime Library
|
||||
(c) Copyright 2006 Andreas Rumpf
|
||||
(c) Copyright 2008 Andreas Rumpf
|
||||
|
||||
See the file "copying.txt", included in this
|
||||
distribution, for details about the copyright.
|
||||
|
|
@ -11,7 +11,8 @@
|
|||
#define NIMBASE_H
|
||||
|
||||
/* 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 */
|
||||
/* the test for __POCC__ has to come before the test for _MSC_VER,
|
||||
because PellesC defines _MSC_VER too. This is brain-dead. */
|
||||
|
|
@ -30,10 +31,18 @@
|
|||
# define N_INLINE(rettype, name) rettype __inline name
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#if defined(__POCC__) || defined(_MSC_VER)
|
||||
# define HAVE_LRINT 1
|
||||
#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: ----------- */
|
||||
#if defined(__GNUC__) || defined(__LCC__) || \
|
||||
defined(__POCC__) || defined(__DMC__)
|
||||
|
|
@ -136,8 +145,7 @@
|
|||
** long int lrint (double x);
|
||||
*/
|
||||
|
||||
#if defined(__LCC__) || defined(__POCC__) \
|
||||
|| (defined(__GNUC__) && defined(WIN32))
|
||||
#if defined(__LCC__) || (defined(__GNUC__) && defined(WIN32))
|
||||
/* Linux' GCC does not seem to have these. Why? */
|
||||
# define HAVE_LRINT
|
||||
# define HAVE_LRINTF
|
||||
|
|
@ -159,7 +167,7 @@
|
|||
# include <math.h>
|
||||
|
||||
#elif (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) \
|
||||
&& !defined(__BORLANDC__)
|
||||
&& !defined(__BORLANDC__) && !defined(__POCC__)
|
||||
|
||||
# include <math.h>
|
||||
|
||||
|
|
@ -206,6 +214,17 @@ static N_INLINE(long int, lrintf)(float flt) {
|
|||
#include <signal.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:
|
||||
__BORLANDC__
|
||||
_MSC_VER
|
||||
|
|
@ -214,6 +233,7 @@ __LCC__
|
|||
__GNUC__
|
||||
__DMC__
|
||||
__POCC__
|
||||
__TINYC__
|
||||
*/
|
||||
|
||||
/* C99 compiler? */
|
||||
|
|
@ -250,50 +270,41 @@ __POCC__
|
|||
#endif
|
||||
|
||||
#define NIM_NIL ((void*)0) /* C's NULL is fucked up in some C compilers, so
|
||||
the generated code does not rely on it anymore */
|
||||
the generated code does not rely on it anymore */
|
||||
|
||||
#if defined(HAVE_STDINT_H)
|
||||
# include <stdint.h>
|
||||
typedef int8_t NS8;
|
||||
typedef int16_t NS16;
|
||||
typedef int32_t NS32;
|
||||
typedef int64_t NS64;
|
||||
typedef int8_t NI8;
|
||||
typedef int16_t NI16;
|
||||
typedef int32_t NI32;
|
||||
typedef int64_t NI64;
|
||||
typedef uint64_t NU64;
|
||||
typedef uint8_t NU8;
|
||||
typedef uint16_t NU16;
|
||||
typedef uint32_t NU32;
|
||||
#elif defined(__BORLANDC__) || defined(__DMC__) \
|
||||
|| defined(__WATCOMC__) || defined(_MSC_VER)
|
||||
typedef signed char NS8;
|
||||
typedef signed short int NS16;
|
||||
typedef signed int NS32;
|
||||
typedef signed char NI8;
|
||||
typedef signed short int NI16;
|
||||
typedef signed int NI32;
|
||||
/* XXX: Float128? */
|
||||
typedef unsigned char NU8;
|
||||
typedef unsigned short int NU16;
|
||||
typedef unsigned __int64 NU64;
|
||||
typedef __int64 NS64;
|
||||
typedef __int64 NI64;
|
||||
typedef unsigned int NU32;
|
||||
#else
|
||||
typedef signed char NS8;
|
||||
typedef signed short int NS16;
|
||||
typedef signed int NS32;
|
||||
typedef signed char NI8;
|
||||
typedef signed short int NI16;
|
||||
typedef signed int NI32;
|
||||
/* XXX: Float128? */
|
||||
typedef unsigned char NU8;
|
||||
typedef unsigned short int NU16;
|
||||
typedef unsigned long long int NU64;
|
||||
typedef long long int NS64;
|
||||
typedef long long int NI64;
|
||||
typedef unsigned int NU32;
|
||||
#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 double NF64;
|
||||
typedef double NF;
|
||||
|
|
@ -307,13 +318,13 @@ typedef char* NCSTRING;
|
|||
# define NIM_IMAN 0
|
||||
#endif
|
||||
|
||||
static N_INLINE(NS32, float64ToInt32)(double val) {
|
||||
static N_INLINE(NI32, float64ToInt32)(double val) {
|
||||
val = val + 68719476736.0*1.5;
|
||||
/* 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);
|
||||
}
|
||||
|
||||
|
|
@ -322,7 +333,7 @@ static N_INLINE(NS32, float32ToInt32)(float val) {
|
|||
|
||||
#define STRING_LITERAL(name, str, length) \
|
||||
static const struct { \
|
||||
NS len, space; \
|
||||
NI len, space; \
|
||||
NIM_CHAR data[length + 1]; \
|
||||
} name = {length, length, str}
|
||||
|
||||
|
|
@ -357,7 +368,7 @@ typedef struct TStringDesc* string;
|
|||
/*
|
||||
typedef struct TSafePoint TSafePoint;
|
||||
struct TSafePoint {
|
||||
NS exc;
|
||||
NI exc;
|
||||
NCSTRING excname;
|
||||
NCSTRING msg;
|
||||
TSafePoint* prev;
|
||||
|
|
@ -368,19 +379,19 @@ typedef struct TFrame TFrame;
|
|||
struct TFrame {
|
||||
TFrame* prev;
|
||||
NCSTRING procname;
|
||||
NS line;
|
||||
NI line;
|
||||
NCSTRING filename;
|
||||
NS len;
|
||||
NI len;
|
||||
};
|
||||
|
||||
extern TFrame* volatile framePtr;
|
||||
/*extern TSafePoint* volatile excHandler; */
|
||||
extern TFrame* framePtr;
|
||||
/*extern TSafePoint* excHandler; */
|
||||
|
||||
#if defined(__cplusplus)
|
||||
struct NimException {
|
||||
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.prev = excHandler;
|
||||
excHandler = &sp;
|
||||
|
|
@ -389,13 +400,13 @@ struct NimException {
|
|||
#endif
|
||||
|
||||
typedef struct TStringDesc {
|
||||
NS len;
|
||||
NS space;
|
||||
NI len;
|
||||
NI space;
|
||||
NIM_CHAR data[1]; /* SEQ_DECL_SIZE]; */
|
||||
} TStringDesc;
|
||||
|
||||
typedef struct {
|
||||
NS len, space;
|
||||
NI len, space;
|
||||
} TGenericSeq;
|
||||
|
||||
typedef TGenericSeq* PGenericSeq;
|
||||
|
|
|
|||
|
|
@ -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.}
|
||||
76
lib/os.nim
76
lib/os.nim
|
|
@ -1,7 +1,7 @@
|
|||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2006 Andreas Rumpf
|
||||
# (c) Copyright 2008 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
|
|
@ -10,7 +10,9 @@
|
|||
## Basic operating system facilities like retrieving environment variables,
|
||||
## reading command line arguments, working with directories, running shell
|
||||
## 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.}
|
||||
|
||||
|
|
@ -371,8 +373,11 @@ proc UnixToNativePath(path: string): string =
|
|||
|
||||
# interface to C library:
|
||||
|
||||
const
|
||||
cunder = if defined(pcc): "_" else: ""
|
||||
|
||||
type
|
||||
TStat {.importc: "struct stat".} = record
|
||||
TStat {.importc: "struct " & cunder & "stat", final.} = object
|
||||
st_dev: int16
|
||||
st_ino: int16
|
||||
st_mode: int16
|
||||
|
|
@ -397,7 +402,8 @@ else:
|
|||
{.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):
|
||||
proc mkdir(dir: CString, theAccess: cint): cint {.
|
||||
|
|
@ -412,7 +418,7 @@ elif defined(windows):
|
|||
proc fullpath(buffer, file: CString, size: int): CString {.
|
||||
importc: "_fullpath", header: "<stdlib.h>".}
|
||||
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 {.
|
||||
importc: "CreateDirectory", header: "<windows.h>".}
|
||||
|
|
@ -421,7 +427,8 @@ else:
|
|||
{.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
|
||||
# time.h which is needed for stat(). stat() needs time.h and
|
||||
# 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 stat(f: CString, res: var TStat): cint {.
|
||||
importc: "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
|
||||
importc: cunder & "stat", header: "<sys/stat.h>".}
|
||||
|
||||
when defined(windows):
|
||||
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):
|
||||
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 =
|
||||
# Linux: /proc/<pid>/exe
|
||||
|
|
@ -491,6 +495,12 @@ proc getApplicationFilename(): string =
|
|||
result = getApplAux("/proc/" & $getpid() & "/path/a.out")
|
||||
elif defined(bsd):
|
||||
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:
|
||||
# little heuristic that may work on other POSIX-like systems:
|
||||
result = getEnv("_")
|
||||
|
|
@ -612,7 +622,7 @@ when defined(wcc):
|
|||
proc cputenv(env: CString): cint {.importc: "putenv", header: "<process.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.}
|
||||
|
||||
|
|
@ -621,7 +631,7 @@ proc cgetenv(env: CString): CString {.importc: "getenv", noDecl.}
|
|||
#int _findclose(long);
|
||||
when defined(windows):
|
||||
type
|
||||
TFindData {.importc: "struct _finddata_t".} = record
|
||||
TFindData {.importc: "struct _finddata_t", final.} = object
|
||||
attrib {.importc: "attrib".}: cint
|
||||
time_create {.importc: "time_create".}: cint
|
||||
time_access {.importc: "time_access".}: cint
|
||||
|
|
@ -636,7 +646,7 @@ when defined(windows):
|
|||
proc findclose(handle: cint) {.importc: "_findclose", header: "<io.h>".}
|
||||
else:
|
||||
type
|
||||
TFindData {.importc: "glob_t".} = record
|
||||
TFindData {.importc: "glob_t", final.} = object
|
||||
gl_pathc: int # count of paths matched by pattern
|
||||
gl_pathv: ptr array[0..1000_000, CString] # list of matched path names
|
||||
gl_offs: int # slots to reserve at beginning of gl_pathv
|
||||
|
|
@ -649,6 +659,30 @@ else:
|
|||
proc globfree(pglob: PFindData) {.
|
||||
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 crename(oldname, newname: CString): cint {.importc: "rename", noDecl.}
|
||||
|
||||
|
|
@ -787,7 +821,7 @@ proc existsEnv(key: string): bool =
|
|||
if cgetenv(key) != nil: return true
|
||||
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
|
||||
## tuple is the name of the current variable stored, in the second its value.
|
||||
getEnvVarsC()
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
## This is a raw POSIX interface module. It does not not provide any
|
||||
## convenience: cstrings are used instead of proper Nimrod strings and
|
||||
## 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:
|
||||
## 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;
|
||||
|
||||
type
|
||||
Taiocb* {.importc: "struct aiocb", header: "<aio.h>".} = record
|
||||
Taiocb* {.importc: "struct aiocb", header: "<aio.h>", final.} = object
|
||||
aio_fildes*: cint ## File descriptor.
|
||||
aio_offset*: TOff ## File offset.
|
||||
aio_buf*: pointer ## Location of buffer.
|
||||
|
|
@ -69,14 +69,14 @@ type
|
|||
aio_sigevent*: TSigEvent ## Signal number and value.
|
||||
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.
|
||||
|
||||
Tdirent* {.importc: "struct dirent", header: "<dirent.h>".} = record
|
||||
Tdirent* {.importc: "struct dirent", header: "<dirent.h>", final.} = object
|
||||
d_ino*: TIno ## File serial number.
|
||||
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_whence*: cshort ## Flag for starting offset.
|
||||
l_start*: Toff ## Relative offset in bytes.
|
||||
|
|
@ -84,13 +84,13 @@ type
|
|||
l_pid*: TPid ## Process ID of the process holding the lock;
|
||||
## returned with F_GETLK.
|
||||
|
||||
Tfenv* {.importc: "fenv_t", header: "<fenv.h>".} =
|
||||
record ## Represents the entire floating-point environment. The
|
||||
Tfenv* {.importc: "fenv_t", header: "<fenv.h>", final.} =
|
||||
object ## Represents the entire floating-point environment. The
|
||||
## floating-point environment refers collectively to any
|
||||
## floating-point status flags and control modes supported
|
||||
## by the implementation.
|
||||
Tfexcept* {.importc: "fexcept_t", header: "<fenv.h>".} =
|
||||
record ## Represents the floating-point status flags collectively,
|
||||
Tfexcept* {.importc: "fexcept_t", header: "<fenv.h>", final.} =
|
||||
object ## Represents the floating-point status flags collectively,
|
||||
## including any status the implementation associates with the
|
||||
## flags. A floating-point status flag is a system variable
|
||||
## 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
|
||||
## behavior of floating-point arithmetic.
|
||||
|
||||
TFTW* {.importc: "struct FTW", header: "<ftw.h>".} = record
|
||||
TFTW* {.importc: "struct FTW", header: "<ftw.h>", final.} = object
|
||||
base*: 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_pathv*: ptr cstring ## Pointer to a list of matched pathnames.
|
||||
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_gid*: TGid ## Numerical group ID.
|
||||
gr_mem*: cstringArray ## Pointer to a null-terminated array of character
|
||||
## pointers to member names.
|
||||
|
||||
Ticonv* {.importc: "iconv_t", header: "<iconv.h>".} =
|
||||
record ## Identifies the conversion from one codeset to another.
|
||||
Ticonv* {.importc: "iconv_t", header: "<iconv.h>", final.} =
|
||||
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
|
||||
decimal_point*: cstring
|
||||
frac_digits*: char
|
||||
|
|
@ -144,14 +144,14 @@ type
|
|||
p_sign_posn*: char
|
||||
thousands_sep*: cstring
|
||||
|
||||
TMqd* {.importc: "mqd_t", header: "<mqueue.h>".} = record
|
||||
TMqAttr* {.importc: "struct mq_attr", header: "<mqueue.h>".} = record
|
||||
TMqd* {.importc: "mqd_t", header: "<mqueue.h>", final.} = object
|
||||
TMqAttr* {.importc: "struct mq_attr", header: "<mqueue.h>", final.} = object
|
||||
mq_flags*: int ## Message queue flags.
|
||||
mq_maxmsg*: int ## Maximum number of messages.
|
||||
mq_msgsize*: int ## Maximum message size.
|
||||
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_uid*: TUid ## Numerical user ID.
|
||||
pw_gid*: TGid ## Numerical group ID.
|
||||
|
|
@ -198,7 +198,7 @@ type
|
|||
Tuid* {.importc: "uid_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.
|
||||
nodename*, ## Name of this node within the communications
|
||||
## 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
|
||||
## system is running.
|
||||
|
||||
TSem* {.importc: "sem_t", header: "<semaphore.h>".} = record
|
||||
Tipc_perm* {.importc: "struct ipc_perm", header: "<sys/ipc.h>".} = record
|
||||
TSem* {.importc: "sem_t", header: "<semaphore.h>", final.} = object
|
||||
Tipc_perm* {.importc: "struct ipc_perm", header: "<sys/ipc.h>", final.} = object
|
||||
uid*: tuid ## Owner's user ID.
|
||||
gid*: tgid ## Owner's group ID.
|
||||
cuid*: Tuid ## Creator's user ID.
|
||||
cgid*: Tgid ## Creator's group ID.
|
||||
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_ino*: TIno ## File serial number.
|
||||
st_mode*: TMode ## Mode of file (see below).
|
||||
|
|
@ -239,7 +239,7 @@ type
|
|||
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_frsize*: int ## Fundamental file system block size.
|
||||
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.
|
||||
|
||||
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
|
||||
|
||||
Ttm* {.importc: "struct tm", header: "<time.h>".} = record
|
||||
Ttm* {.importc: "struct tm", header: "<time.h>", final.} = object
|
||||
tm_sec*: cint ## Seconds [0,60].
|
||||
tm_min*: cint ## Minutes [0,59].
|
||||
tm_hour*: cint ## Hour [0,23].
|
||||
|
|
@ -268,10 +268,10 @@ type
|
|||
tm_wday*: cint ## Day of week [0,6] (Sunday =0).
|
||||
tm_yday*: cint ## Day of year [0,365].
|
||||
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_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_value*: ttimespec ## Timer expiration.
|
||||
|
||||
|
|
@ -279,19 +279,19 @@ type
|
|||
## Possibly volatile-qualified integer type of an object that can be
|
||||
## accessed as an atomic entity, even in the presence of asynchronous
|
||||
## 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_signo*: cint ## Signal number.
|
||||
sigev_value*: Tsigval ## Signal value.
|
||||
sigev_notify_function*: proc (x: TSigval) {.noconv.} ## Notification function.
|
||||
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;
|
||||
## 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
|
||||
## function or one of the macros
|
||||
## SIG_IGN or SIG_DFL.
|
||||
|
|
@ -300,16 +300,16 @@ type
|
|||
sa_flags*: cint ## Special flags.
|
||||
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_size*: int ## Stack size.
|
||||
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_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_code*: cint ## Signal code.
|
||||
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_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_ss_low_priority*: cint ## Low scheduling priority for
|
||||
## sporadic server.
|
||||
|
|
@ -334,15 +334,15 @@ type
|
|||
sched_ss_max_repl*: cint ## Maximum pending replenishments for
|
||||
## 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_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_spawn_file_actions* {.importc: "posix_spawn_file_actions_t", header: "<spawn.h>".} = cint
|
||||
Tmcontext* {.importc: "mcontext_t", header: "<ucontext.h>".} = record
|
||||
Tucontext* {.importc: "ucontext_t", header: "<ucontext.h>".} = record
|
||||
Tmcontext* {.importc: "mcontext_t", header: "<ucontext.h>", final.} = object
|
||||
Tucontext* {.importc: "ucontext_t", header: "<ucontext.h>", final.} = object
|
||||
uc_link*: ptr Tucontext ## Pointer to the context that is resumed
|
||||
## when this context returns.
|
||||
uc_sigmask*: Tsigset ## The set of signals that are blocked when this
|
||||
|
|
@ -729,7 +729,7 @@ var
|
|||
GLOB_NOSORT* {.importc, header: "<glob.h>".}: cint
|
||||
## Do not sort the pathnames returned.
|
||||
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.
|
||||
GLOB_NOMATCH* {.importc, header: "<glob.h>".}: cint
|
||||
## The pattern does not match any existing pathname, and GLOB_NOCHECK
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2006 Andreas Rumpf
|
||||
# (c) Copyright 2008 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ type
|
|||
PPointer = ptr pointer
|
||||
|
||||
TCollectorData = int
|
||||
TCell = record
|
||||
TCell {.final.} = object
|
||||
refcount: TCollectorData # the refcount and bit flags
|
||||
typ: PNimType
|
||||
stackcount: int # stack counter for debugging
|
||||
|
|
@ -67,18 +67,18 @@ type
|
|||
|
||||
TBitIndex = range[0..UnitsPerPage-1]
|
||||
|
||||
TPageDesc = record
|
||||
TPageDesc {.final.} = object
|
||||
next: PPageDesc # all nodes are connected with this pointer
|
||||
key: TAddress # start address at bit 0
|
||||
bits: array[TBitIndex, int] # a bit vector
|
||||
|
||||
PPageDescArray = ptr array[0..1000_000, PPageDesc]
|
||||
TCellSet = record
|
||||
TCellSet {.final.} = object
|
||||
counter, max: int
|
||||
head: PPageDesc
|
||||
data: PPageDescArray
|
||||
|
||||
TSetNode = record
|
||||
TSetNode {.final.} = object
|
||||
n: array[0.. (1 shl bitsPerNode)-1, PSetNode]
|
||||
PSetNode = ptr TSetNode
|
||||
|
||||
|
|
|
|||
28
lib/repr.nim
28
lib/repr.nim
|
|
@ -81,9 +81,9 @@ proc reprSetAux(result: var string, p: pointer, typ: PNimType) =
|
|||
of 1: u = ze64(cast[ptr int8](p)^)
|
||||
of 2: u = ze64(cast[ptr int16](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:
|
||||
var a = cast[pbyteArray](p)^
|
||||
var a = cast[pbyteArray](p)
|
||||
for i in 0 .. typ.size*8-1:
|
||||
if (a[i div 8] and (1 shl (i mod 8))) != 0:
|
||||
if elemCounter > 0: add result, ", "
|
||||
|
|
@ -102,8 +102,8 @@ proc reprSet(p: pointer, typ: PNimType): string {.compilerproc.} =
|
|||
reprSetAux(result, p, typ)
|
||||
|
||||
type
|
||||
TReprClosure = record # we cannot use a global variable here
|
||||
# as this wouldn't be thread-safe
|
||||
TReprClosure {.final.} = object # we cannot use a global variable here
|
||||
# as this wouldn't be thread-safe
|
||||
marked: TCellSet
|
||||
recdepth: int # do not recurse endless
|
||||
indent: int # indentation
|
||||
|
|
@ -189,8 +189,8 @@ proc reprAux(result: var string, p: pointer, typ: PNimType,
|
|||
case typ.kind
|
||||
of tySet: reprSetAux(result, p, typ)
|
||||
of tyArray: reprArray(result, p, typ, cl)
|
||||
of tyRecord: reprRecord(result, p, typ, cl)
|
||||
of tyObject: # result = reprRecord(p, typ, cl)
|
||||
of tyTuple, tyPureObject: reprRecord(result, p, typ, cl)
|
||||
of tyObject:
|
||||
var t = cast[ptr PNimType](p)^
|
||||
reprRecord(result, p, t, cl)
|
||||
of tyRef, tyPtr:
|
||||
|
|
@ -220,14 +220,28 @@ proc reprAux(result: var string, p: pointer, typ: PNimType,
|
|||
add result, "(invalid data!)"
|
||||
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 =
|
||||
var
|
||||
cl: TReprClosure
|
||||
initReprClosure(cl)
|
||||
result = ""
|
||||
if typ.kind in {tyObject, tyRecord, tyArray, tySet}:
|
||||
if typ.kind in {tyObject, tyPureObject, tyTuple, tyArray, tySet}:
|
||||
reprAux(result, p, typ, cl)
|
||||
else:
|
||||
var p = p
|
||||
reprAux(result, addr(p), typ, cl)
|
||||
add result, "\n"
|
||||
deinitReprClosure(cl)
|
||||
|
|
|
|||
|
|
@ -7,10 +7,10 @@
|
|||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
|
||||
|
||||
## This module contains various string utility routines.
|
||||
## 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
|
||||
# of the standard library!
|
||||
|
|
@ -153,6 +153,10 @@ proc ParseInt*(s: string): int {.noSideEffect.}
|
|||
## a valid integer, `EInvalidValue` is raised.
|
||||
# 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.}
|
||||
## Parses a decimal floating point value contained in `s`. If `s` is not
|
||||
## 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
|
||||
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 =
|
||||
var i = 0
|
||||
|
|
@ -262,7 +272,7 @@ proc findNormalized(x: string, inArray: openarray[string]): int =
|
|||
while i < high(inArray):
|
||||
if cmpIgnoreStyle(x, inArray[i]) == 0: return i
|
||||
inc(i, 2) # incrementing by 1 would probably result in a
|
||||
# security whole ...
|
||||
# security whole ...
|
||||
return -1
|
||||
|
||||
proc `%`(formatstr: string, a: openarray[string]): string =
|
||||
|
|
@ -306,11 +316,9 @@ proc `%`(formatstr: string, a: openarray[string]): string =
|
|||
|
||||
proc cmpIgnoreCase(a, b: string): int =
|
||||
# makes usage of the fact that strings are zero-terminated
|
||||
var
|
||||
aa, bb: char
|
||||
for i in 0..len(a)-1:
|
||||
aa = toLower(a[i])
|
||||
bb = toLower(b[i])
|
||||
var aa = toLower(a[i])
|
||||
var bb = toLower(b[i])
|
||||
result = ord(aa) - ord(bb)
|
||||
if result != 0: break
|
||||
|
||||
|
|
@ -319,14 +327,13 @@ proc cmpIgnoreCase(a, b: string): int =
|
|||
|
||||
proc cmpIgnoreStyle(a, b: string): int =
|
||||
var
|
||||
aa, bb: char
|
||||
i = 0
|
||||
j = 0
|
||||
while True:
|
||||
while a[i] == '_': inc(i)
|
||||
while b[j] == '_': inc(j) # BUGFIX: typo
|
||||
aa = toLower(a[i])
|
||||
bb = toLower(b[j])
|
||||
var aa = toLower(a[i])
|
||||
var bb = toLower(b[j])
|
||||
result = ord(aa) - ord(bb)
|
||||
if result != 0 or aa == '\0': break
|
||||
inc(i)
|
||||
|
|
@ -475,15 +482,12 @@ proc deleteStr(s: var string, first, last: int) =
|
|||
|
||||
# parsing numbers:
|
||||
|
||||
proc sprintf(buf, frmt: CString) {.nodecl, importc: "sprintf", varargs.}
|
||||
|
||||
proc toHex(x: BiggestInt, len: int): string =
|
||||
const
|
||||
HexChars = "0123456789ABCDEF"
|
||||
var
|
||||
shift: BiggestInt
|
||||
result = newString(len)
|
||||
shift = 0
|
||||
for j in countdown(len-1, 0):
|
||||
result[j] = HexChars[toU32(x shr shift) and 0xF]
|
||||
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
|
||||
# computation as a negative number and then change the sign at the end.
|
||||
var
|
||||
i: int
|
||||
sign: BiggestInt
|
||||
i = index
|
||||
# a local i is more efficient than accessing an in out parameter
|
||||
sign = -1
|
||||
i: int = index # a local i is more efficient than accessing a var parameter
|
||||
sign: BiggestInt = -1
|
||||
if s[i] == '+':
|
||||
inc(i)
|
||||
elif s[i] == '-':
|
||||
|
|
@ -523,10 +524,8 @@ proc rawParseInt(s: string, index: var int): BiggestInt =
|
|||
|
||||
proc parseInt(s: string): int =
|
||||
var
|
||||
index: int
|
||||
res: BiggestInt
|
||||
index = strStart
|
||||
res = rawParseInt(s, index)
|
||||
index: int = 0
|
||||
res = rawParseInt(s, index)
|
||||
if index == -1:
|
||||
raise newException(EInvalidValue, "invalid integer: " & s)
|
||||
elif (sizeof(int) <= 4) and
|
||||
|
|
@ -535,17 +534,20 @@ proc parseInt(s: string): int =
|
|||
else:
|
||||
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 =
|
||||
var
|
||||
hd, esign, sign: float
|
||||
esign = 1.0
|
||||
sign = 1.0
|
||||
exponent, i: int
|
||||
flags: int
|
||||
result = 0.0
|
||||
i = 0
|
||||
exponent = 0
|
||||
esign = 1.0
|
||||
flags = 0
|
||||
sign = 1.0
|
||||
if s[i] == '+': inc(i)
|
||||
elif s[i] == '-':
|
||||
sign = -1.0
|
||||
|
|
@ -558,7 +560,7 @@ proc ParseFloat(s: string): float =
|
|||
while s[i] == '_': inc(i)
|
||||
# Decimal?
|
||||
if s[i] == '.':
|
||||
hd = 1.0
|
||||
var hd = 1.0
|
||||
inc(i)
|
||||
while s[i] in {'0'..'9'}:
|
||||
# Read fractional part
|
||||
|
|
@ -586,7 +588,7 @@ proc ParseFloat(s: string): float =
|
|||
inc(i)
|
||||
while s[i] == '_': inc(i)
|
||||
# Calculate Exponent
|
||||
hd = 1.0
|
||||
var hd = 1.0
|
||||
for j in 1..exponent:
|
||||
hd = hd * 10.0
|
||||
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
|
||||
## always `len` characters long. No leading ``0c`` prefix is generated.
|
||||
var
|
||||
mask, shift: BiggestInt
|
||||
mask: BiggestInt = 7
|
||||
shift: BiggestInt = 0
|
||||
assert(len > 0)
|
||||
result = newString(len)
|
||||
mask = 7
|
||||
shift = 0
|
||||
for j in countdown(len-1, 0):
|
||||
result[j] = chr(int((x and mask) shr shift) + ord('0'))
|
||||
shift = shift + 3
|
||||
|
|
@ -614,11 +615,10 @@ proc toBin*(x: BiggestInt, len: int): string =
|
|||
## converts `x` into its binary representation. The resulting string is
|
||||
## always `len` characters long. No leading ``0b`` prefix is generated.
|
||||
var
|
||||
mask, shift: BiggestInt
|
||||
mask: BiggestInt = 1
|
||||
shift: BiggestInt = 0
|
||||
assert(len > 0)
|
||||
result = newString(len)
|
||||
mask = 1
|
||||
shift = 0
|
||||
for j in countdown(len-1, 0):
|
||||
result[j] = chr(int((x and mask) shr shift) + ord('0'))
|
||||
shift = shift + 1
|
||||
|
|
|
|||
|
|
@ -33,10 +33,6 @@ var
|
|||
IOFBF {.importc: "_IOFBF", 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.} =
|
||||
# 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
|
||||
|
|
@ -81,6 +77,8 @@ proc write(f: TFile, b: bool) =
|
|||
else: write(f, "false")
|
||||
proc write(f: TFile, r: float) = fprintf(f, "%g", r)
|
||||
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 =
|
||||
# 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) =
|
||||
write(f, x)
|
||||
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)
|
||||
|
||||
# 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 {.
|
||||
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 =
|
||||
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)
|
||||
|
||||
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 =
|
||||
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 =
|
||||
result = fwrite(buffer, 1, len, f)
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
# the programmer may not want
|
||||
|
||||
type
|
||||
TStringDesc {.importc, nodecl.} = record
|
||||
TStringDesc {.importc, nodecl, final.} = object
|
||||
len, space: int # len and space without counting the terminating zero
|
||||
data: array[0..0, char] # for the '\0' character
|
||||
|
||||
|
|
@ -25,7 +25,6 @@ type
|
|||
# implementation:
|
||||
|
||||
proc resize(old: int): int {.inline.} =
|
||||
assert(old < 65536 * 4)
|
||||
if old <= 0: return 1
|
||||
elif old < 65536: return old * 2
|
||||
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))
|
||||
|
||||
proc copyString(src: mstring): mstring {.compilerProc.} =
|
||||
if src == nil: return nil
|
||||
result = rawNewString(src.space)
|
||||
result.len = src.len
|
||||
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
|
||||
|
||||
# --------------- other string routines ----------------------------------
|
||||
proc `$`(x: int): string =
|
||||
proc nimIntToStr(x: int): string {.compilerproc.} =
|
||||
result = newString(sizeof(x)*4)
|
||||
var i = 0
|
||||
var y = x
|
||||
|
|
@ -238,14 +238,12 @@ proc `$`(x: int): string =
|
|||
for j in 0..i div 2 - 1:
|
||||
swap(result[j], result[i-j-1])
|
||||
|
||||
{.push warnings: off.}
|
||||
proc `$`(x: float): string =
|
||||
proc nimFloatToStr(x: float): string {.compilerproc.} =
|
||||
var buf: array [0..59, char]
|
||||
c_sprintf(buf, "%#g", x)
|
||||
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
|
||||
# int64 support is weak
|
||||
result = newString(sizeof(x)*4)
|
||||
|
|
@ -265,19 +263,13 @@ proc `$`(x: int64): string =
|
|||
for j in 0..i div 2 - 1:
|
||||
swap(result[j], result[i-j-1])
|
||||
|
||||
proc `$`(x: bool): string =
|
||||
if x: result = "true"
|
||||
else: result = "false"
|
||||
proc nimBoolToStr(x: bool): string {.compilerproc.} =
|
||||
return if x: "true" else: "false"
|
||||
|
||||
proc `$`(x: char): string =
|
||||
proc nimCharToStr(x: char): string {.compilerproc.} =
|
||||
result = newString(1)
|
||||
result[0] = x
|
||||
|
||||
proc `$`(x: string): string =
|
||||
# this is useful for generic code!
|
||||
return x
|
||||
|
||||
|
||||
proc binaryStrSearch(x: openarray[string], y: string): int {.compilerproc.} =
|
||||
var
|
||||
a = 0
|
||||
|
|
|
|||
578
lib/system.nim
578
lib/system.nim
|
|
@ -86,7 +86,6 @@ type
|
|||
## length field.
|
||||
seq*{.magic: "Seq".}[T] ## Generic type to construct sequences.
|
||||
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
|
||||
## int 8 bits wide.
|
||||
|
|
@ -110,8 +109,9 @@ type
|
|||
name*: cstring ## The exception's name is its Nimrod identifier.
|
||||
## This field is filled automatically in the
|
||||
## ``raise`` statement.
|
||||
msg*: cstring ## the exception's message. Not providing an
|
||||
## exception message is bad style.
|
||||
msg* {.exportc: "message".}: cstring ## the exception's message. Not
|
||||
## providing an
|
||||
## exception message is bad style.
|
||||
|
||||
EAsynch* = object of E_Base ## Abstract exception class for
|
||||
## *asynchronous exceptions* (interrupts).
|
||||
|
|
@ -129,18 +129,21 @@ type
|
|||
## could not be fullfilled.
|
||||
EArithmetic* = object of ESynch ## raised if any kind of arithmetic
|
||||
## error occured.
|
||||
EDivByZero* = object of EArithmetic ## is the exception class for integer
|
||||
## divide-by-zero errors.
|
||||
EOverflow* = object of EArithmetic ## is the exception class for integer
|
||||
## calculations whose results are too
|
||||
## large to fit in the provided bits.
|
||||
EDivByZero* {.compilerproc.} =
|
||||
object of EArithmetic ## is the exception class for integer divide-by-zero
|
||||
## errors.
|
||||
EOverflow* {.compilerproc.} =
|
||||
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
|
||||
## invalid memory access errors
|
||||
EAccessViolation* {.compilerproc.} =
|
||||
object of ESynch ## the exception class for invalid memory access errors
|
||||
|
||||
EAssertionFailed* = object of ESynch ## is the exception class for Assert
|
||||
## procedures that is raised if the
|
||||
## assertion proves wrong
|
||||
EAssertionFailed* {.compilerproc.} =
|
||||
object of ESynch ## is the exception class for Assert
|
||||
## procedures that is raised if the
|
||||
## assertion proves wrong
|
||||
|
||||
EControlC* = object of EAsynch ## is the exception class for Ctrl+C
|
||||
## key presses in console applications.
|
||||
|
|
@ -154,6 +157,9 @@ type
|
|||
|
||||
EInvalidIndex* = object of ESynch ## is raised if an array index is out
|
||||
## 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
|
||||
## occured.
|
||||
|
|
@ -164,13 +170,13 @@ type
|
|||
ENoExceptionToReraise* = object of ESynch ## is raised if there is no
|
||||
## exception to reraise.
|
||||
|
||||
EInvalidObjectAssignment* = object of ESynch ## is raised if an object
|
||||
## gets assigned to its
|
||||
## farther's object.
|
||||
EInvalidObjectAssignment* =
|
||||
object of ESynch ## is raised if an object gets assigned to its
|
||||
## farther's object.
|
||||
|
||||
EInvalidObjectConversion* = object of ESynch ## is raised if an object is
|
||||
## converted to an incompatible
|
||||
## object type.
|
||||
EInvalidObjectConversion* =
|
||||
object of ESynch ## is raised if an object is converted to an incompatible
|
||||
## object type.
|
||||
|
||||
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)
|
||||
##
|
||||
## 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
|
||||
## is achieved by reversing the parameters for ``in_operator``; ``in`` then
|
||||
## 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.
|
||||
|
||||
# concat operator:
|
||||
proc `&` * (x: string, y: char): string {.
|
||||
magic: "ConStrStr", noSideEffect, returnsNew.}
|
||||
proc `&` * (x: char, y: char): string {.
|
||||
magic: "ConStrStr", noSideEffect, returnsNew.}
|
||||
proc `&` * (x, y: string): string {.
|
||||
magic: "ConStrStr", noSideEffect, returnsNew.}
|
||||
proc `&` * (x: char, y: string): string {.
|
||||
magic: "ConStrStr", noSideEffect, returnsNew.}
|
||||
## is the `concatenation operator`. It
|
||||
## concatenates `x` and `y`.
|
||||
proc `&` * (x: string, y: char): string {.magic: "ConStrStr", noSideEffect.}
|
||||
proc `&` * (x: char, y: char): string {.magic: "ConStrStr", noSideEffect.}
|
||||
proc `&` * (x, y: string): string {.magic: "ConStrStr", noSideEffect.}
|
||||
proc `&` * (x: char, y: string): string {.magic: "ConStrStr", noSideEffect.}
|
||||
## is the `concatenation operator`. It concatenates `x` and `y`.
|
||||
|
||||
proc add * (x: var string, y: char) {.magic: "AppendStrCh".}
|
||||
proc add * (x: var string, y: string) {.magic: "AppendStrStr".}
|
||||
|
||||
proc add* (x: var string, y: cstring) =
|
||||
var i = 0
|
||||
while y[i] != '\0':
|
||||
add(x, y[i])
|
||||
inc(i)
|
||||
when not defined(ECMAScript):
|
||||
proc add* (x: var string, y: cstring) =
|
||||
var i = 0
|
||||
while y[i] != '\0':
|
||||
add(x, y[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: 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
|
||||
## ``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
|
||||
## 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
|
||||
## 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
|
||||
## 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
|
||||
## 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.}
|
||||
## 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.
|
||||
## 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`
|
||||
## 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`
|
||||
## 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`
|
||||
## 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`
|
||||
## 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`
|
||||
## 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`
|
||||
## 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`
|
||||
## 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:
|
||||
proc getRefcount*[T](x: ref T): int {.importc: "getRefcount".}
|
||||
|
|
@ -790,10 +809,12 @@ proc getCurrentExceptionMsg*(): string {.exportc.}
|
|||
|
||||
# new constants:
|
||||
const
|
||||
inf* = 1.0 / 0.0
|
||||
inf* {.magic: "Inf".} = 0.0
|
||||
## contains the IEEE floating point value of positive infinity.
|
||||
nan* = 0.0 / 0.0
|
||||
## contains the IEEE floating point value of *Not A Number*. Note
|
||||
neginf* {.magic: "NegInf".} = 0.0
|
||||
## 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
|
||||
## and expect a reasonable result - use the `classify` procedure
|
||||
## in the module ``math`` for checking for NaN.
|
||||
|
|
@ -885,11 +906,22 @@ iterator items*(a: cstring): char {.inline.} =
|
|||
yield a[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_system.} # This is an undocumented pragma that can only be used
|
||||
# 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 = []
|
||||
setLen(result, x.len + y.len)
|
||||
for i in 0..x.len-1:
|
||||
|
|
@ -897,85 +929,49 @@ proc `&` *[T](x, y: seq[T]): seq[T] {.noSideEffect, returnsNew.} =
|
|||
for i in 0..y.len-1:
|
||||
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 = []
|
||||
setLen(x.len + 1)
|
||||
for i in 0..x.len-1:
|
||||
result[i] = x[i]
|
||||
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 = []
|
||||
setLen(y.len + 1)
|
||||
for i in 0..y.len-1:
|
||||
result[i] = y[i]
|
||||
result[y.len] = x
|
||||
|
||||
proc `&` *[T](x, y: T): seq[T] {.noSideEffect, returnsNew.} =
|
||||
proc `&` *[T](x, y: T): seq[T] {.noSideEffect.} =
|
||||
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.} =
|
||||
## Generic equals operator for sequences: relies on a equals operator for
|
||||
## the element type `T`.
|
||||
if cast[pointer](x) == cast[pointer](y):
|
||||
if seqToPtr(x) == seqToPtr(y):
|
||||
result = true
|
||||
elif cast[pointer](x) == nil or cast[pointer](y) == nil:
|
||||
elif seqToPtr(x) == nil or seqToPtr(y) == nil:
|
||||
result = false
|
||||
elif x.len == y.len:
|
||||
for i in 0..x.len-1:
|
||||
if x[i] != y[i]: return false
|
||||
result = true
|
||||
|
||||
{.push checks: off, line_dir: off, debugger: off,
|
||||
assertions: on.} # obviously we cannot generate checking operations here :-)
|
||||
# because it would yield into an endless recursion
|
||||
# however, stack-traces are available for most parts
|
||||
# of the code
|
||||
# ----------------- FPU ------------------------------------------------------
|
||||
|
||||
include hti
|
||||
#proc disableFPUExceptions*()
|
||||
# disables all floating point unit exceptions
|
||||
|
||||
proc initGC()
|
||||
|
||||
var
|
||||
strDesc: TNimType
|
||||
|
||||
strDesc.size = sizeof(string)
|
||||
strDesc.kind = tyString
|
||||
initGC() # BUGFIX: need to be called here!
|
||||
|
||||
{.push stack_trace: off.}
|
||||
|
||||
include ansi_c
|
||||
|
||||
proc cmp(x, y: string): int =
|
||||
return c_strcmp(x, y)
|
||||
|
||||
when defined(windows):
|
||||
# work-around C's sucking abstraction:
|
||||
# BUGFIX: stdin and stdout should be binary files!
|
||||
const pccHack = if defined(pcc): "_" else: "" # Hack for PCC
|
||||
proc setmode(handle, mode: int) {.importc: pccHack & "setmode",
|
||||
header: "<io.h>".}
|
||||
proc fileno(f: C_TextFileStar): int {.importc: pccHack & "fileno",
|
||||
header: "<fcntl.h>".}
|
||||
var
|
||||
O_BINARY {.importc: pccHack & "O_BINARY", nodecl.}: int
|
||||
|
||||
# we use binary mode in Windows:
|
||||
setmode(fileno(c_stdin), O_BINARY)
|
||||
setmode(fileno(c_stdout), O_BINARY)
|
||||
|
||||
when defined(endb):
|
||||
proc endbStep()
|
||||
|
||||
|
||||
template newException(exceptn, message: expr): expr =
|
||||
block: # open a new scope
|
||||
var
|
||||
e: ref exceptn
|
||||
new(e)
|
||||
e.msg = message
|
||||
e
|
||||
#proc enableFPUExceptions*()
|
||||
# enables all floating point unit exceptions
|
||||
|
||||
# ----------------- GC interface ---------------------------------------------
|
||||
|
||||
|
|
@ -993,7 +989,7 @@ proc GC_fullCollect*()
|
|||
|
||||
type
|
||||
TGC_Strategy* = enum ## the strategy the GC should use for the application
|
||||
gcThroughput , ## optimize for throughput
|
||||
gcThroughput, ## optimize for throughput
|
||||
gcResponsiveness, ## optimize for responsiveness (default)
|
||||
gcOptimizeTime, ## optimize for speed
|
||||
gcOptimizeSpace ## optimize for memory footprint
|
||||
|
|
@ -1010,175 +1006,241 @@ proc GC_disableMarkAndSweep*()
|
|||
## and activated separately from the rest of the GC.
|
||||
|
||||
|
||||
# ----------------- IO Part --------------------------------------------------
|
||||
{.push checks: off, line_dir: off, debugger: off,
|
||||
assertions: on.} # obviously we cannot generate checking operations here :-)
|
||||
# because it would yield into an endless recursion
|
||||
# however, stack-traces are available for most parts
|
||||
# of the code
|
||||
|
||||
type
|
||||
CFile {.importc: "FILE", nodecl.} = record # empty record for
|
||||
# data hiding
|
||||
TFile* = ptr CFile ## The type representing a file handle.
|
||||
|
||||
TFileMode* = enum ## The file mode when opening a file.
|
||||
fmRead, ## Open the file for read access only.
|
||||
fmWrite, ## Open the file for write access only.
|
||||
fmReadWrite, ## Open the file for read and write access.
|
||||
## If the file does not exist, it will be
|
||||
## created.
|
||||
fmReadWriteExisting, ## Open the file for read and write access.
|
||||
## If the file does not exist, it will not be
|
||||
## created.
|
||||
fmAppend ## Open the file for writing only; append data
|
||||
## at the end.
|
||||
|
||||
# text file handling:
|
||||
var
|
||||
stdin* {.importc: "stdin", noDecl.}: TFile ## The standard input stream.
|
||||
stdout* {.importc: "stdout", noDecl.}: TFile ## The standard output stream.
|
||||
stderr* {.importc: "stderr", noDecl.}: TFile
|
||||
## The standard error stream.
|
||||
##
|
||||
## Note: In my opinion, this should not be used -- the concept of a
|
||||
## separate error stream is a design flaw of UNIX. A seperate *message
|
||||
## stream* is a good idea, but since it is named ``stderr`` there are few
|
||||
## programs out there that distinguish properly between ``stdout`` and
|
||||
## ``stderr``. So, that's what you get if you don't name your variables
|
||||
## appropriately. It also annoys people if redirection via ``>output.txt``
|
||||
## does not work because the program writes to ``stderr``.
|
||||
|
||||
proc OpenFile*(f: var TFile, filename: string,
|
||||
mode: TFileMode = fmRead, bufSize: int = -1): Bool
|
||||
## Opens a file named `filename` with given `mode`.
|
||||
##
|
||||
## Default mode is readonly. Returns true iff the file could be opened.
|
||||
## This throws no exception if the file could not be opened. The reason is
|
||||
## that the programmer needs to provide an appropriate error message anyway
|
||||
## (yes, even in scripts).
|
||||
|
||||
proc CloseFile*(f: TFile) {.importc: "fclose", nodecl.}
|
||||
## Closes the file.
|
||||
proc EndOfFile*(f: TFile): Bool
|
||||
## Returns true iff `f` is at the end.
|
||||
proc readChar*(f: TFile): char {.importc: "fgetc", nodecl.}
|
||||
## Reads a single character from the stream `f`. If the stream
|
||||
## has no more characters, `EEndOfFile` is raised.
|
||||
proc FlushFile*(f: TFile) {.importc: "fflush", noDecl.}
|
||||
## Flushes `f`'s buffer.
|
||||
|
||||
proc readFile*(filename: string): string
|
||||
## Opens a file name `filename` for reading. Then reads the
|
||||
## file's content completely into a string and
|
||||
## closes the file afterwards. Returns the string. Returns nil if there was
|
||||
## an error. Does not throw an IO exception.
|
||||
|
||||
proc write*(f: TFile, r: float)
|
||||
proc write*(f: TFile, i: int)
|
||||
proc write*(f: TFile, s: string)
|
||||
proc write*(f: TFile, b: Bool)
|
||||
proc write*(f: TFile, c: char)
|
||||
proc write*(f: TFile, c: cstring)
|
||||
## Writes a value to the file `f`. May throw an IO exception.
|
||||
|
||||
proc readLine*(f: TFile): string
|
||||
## reads a line of text from the file `f`. May throw an IO exception.
|
||||
## Reading from an empty file buffer, does not throw an exception, but
|
||||
## returns nil. A line of text may be delimited by ``CR``, ``LF`` or
|
||||
## ``CRLF``. The newline character(s) are not part of the returned string.
|
||||
|
||||
proc writeln*[Ty](f: TFile, x: Ty) {.inline.}
|
||||
## writes a value `x` to `f` and then writes "\n". May throw an IO exception.
|
||||
proc echo*[Ty](x: Ty) {.inline.}
|
||||
## equivalent to ``writeln(stdout, x); flush(stdout)``.
|
||||
## equivalent to ``writeln(stdout, x); flush(stdout)``. BUT: This is
|
||||
## available for the ECMAScript target too!
|
||||
|
||||
proc getFileSize*(f: TFile): int64
|
||||
## retrieves the file size (in bytes) of `f`.
|
||||
|
||||
proc ReadBytes*(f: TFile, a: var openarray[byte], start, len: int): int
|
||||
## reads `len` bytes into the buffer `a` starting at ``a[start]``. Returns
|
||||
## the actual number of bytes that have been read which may be less than
|
||||
## `len` (if not as many bytes are remaining), but not greater.
|
||||
template newException(exceptn, message: expr): expr =
|
||||
block: # open a new scope
|
||||
var
|
||||
e: ref exceptn
|
||||
new(e)
|
||||
e.msg = message
|
||||
e
|
||||
|
||||
proc ReadChars*(f: TFile, a: var openarray[char], start, len: int): int
|
||||
## reads `len` bytes into the buffer `a` starting at ``a[start]``. Returns
|
||||
## the actual number of bytes that have been read which may be less than
|
||||
## `len` (if not as many bytes are remaining), but not greater.
|
||||
when not defined(EcmaScript):
|
||||
|
||||
proc readBuffer*(f: TFile, buffer: pointer, len: int): int
|
||||
## reads `len` bytes into the buffer pointed to by `buffer`. Returns
|
||||
## the actual number of bytes that have been read which may be less than
|
||||
## `len` (if not as many bytes are remaining), but not greater.
|
||||
include hti
|
||||
|
||||
proc writeBytes*(f: TFile, a: openarray[byte], start, len: int): int
|
||||
## writes the bytes of ``a[start..start+len-1]`` to the file `f`. Returns
|
||||
## the number of actual written bytes, which may be less than `len` in case
|
||||
## of an error.
|
||||
proc initGC()
|
||||
|
||||
proc writeChars*(f: tFile, a: openarray[char], start, len: int): int
|
||||
## writes the bytes of ``a[start..start+len-1]`` to the file `f`. Returns
|
||||
## the number of actual written bytes, which may be less than `len` in case
|
||||
## of an error.
|
||||
|
||||
proc writeBuffer*(f: TFile, buffer: pointer, len: int): int
|
||||
## writes the bytes of buffer pointed to by the parameter `buffer` to the
|
||||
## file `f`. Returns the number of actual written bytes, which may be less
|
||||
## than `len` in case of an error.
|
||||
|
||||
proc setFilePos*(f: TFile, pos: int64)
|
||||
## sets the position of the file pointer that is used for read/write
|
||||
## operations. The file's first byte has the index zero.
|
||||
|
||||
proc getFilePos*(f: TFile): int64
|
||||
## retrieves the current position of the file pointer that is used to
|
||||
## read from the file `f`. The file's first byte has the index zero.
|
||||
|
||||
include sysio
|
||||
|
||||
iterator lines*(filename: string): string =
|
||||
## Iterate over any line in the file named `filename`.
|
||||
## If the file does not exist `EIO` is raised.
|
||||
var
|
||||
f: TFile
|
||||
if not openFile(f, filename):
|
||||
raise newException(EIO, "cannot open: " & filename)
|
||||
var res = ""
|
||||
while not endOfFile(f):
|
||||
rawReadLine(f, res)
|
||||
yield res
|
||||
CloseFile(f)
|
||||
strDesc: TNimType
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
strDesc.size = sizeof(string)
|
||||
strDesc.kind = tyString
|
||||
initGC() # BUGFIX: need to be called here!
|
||||
|
||||
include excpt
|
||||
# we cannot compile this with stack tracing on
|
||||
# as it would recurse endlessly!
|
||||
include arithm
|
||||
{.pop.} # stack trace
|
||||
{.push stack_trace: off.}
|
||||
|
||||
# sequence type declarations here because the GC needs them too:
|
||||
type
|
||||
TGenericSeq {.importc, nodecl.} = record
|
||||
len, space: int
|
||||
include ansi_c
|
||||
|
||||
PGenericSeq {.importc, nodecl.} = ptr TGenericSeq
|
||||
proc cmp(x, y: string): int =
|
||||
return c_strcmp(x, y)
|
||||
|
||||
const
|
||||
GenericSeqSize = (2 * sizeof(int))
|
||||
when defined(windows):
|
||||
# work-around C's sucking abstraction:
|
||||
# BUGFIX: stdin and stdout should be binary files!
|
||||
const pccHack = if defined(pcc): "_" else: "" # Hack for PCC
|
||||
proc setmode(handle, mode: int) {.importc: pccHack & "setmode",
|
||||
header: "<io.h>".}
|
||||
proc fileno(f: C_TextFileStar): int {.importc: pccHack & "fileno",
|
||||
header: "<fcntl.h>".}
|
||||
var
|
||||
O_BINARY {.importc: pccHack & "O_BINARY", nodecl.}: int
|
||||
|
||||
when not defined(boehmgc) and not defined(nogc):
|
||||
include gc
|
||||
# we use binary mode in Windows:
|
||||
setmode(fileno(c_stdin), O_BINARY)
|
||||
setmode(fileno(c_stdout), O_BINARY)
|
||||
|
||||
include sysstr
|
||||
include assign
|
||||
include dyncalls
|
||||
include repr
|
||||
when defined(endb):
|
||||
proc endbStep()
|
||||
|
||||
# we have to implement it here after gentostr for the cstrToNimStrDummy proc
|
||||
proc getCurrentExceptionMsg(): string =
|
||||
if excHandler == nil: return ""
|
||||
return $excHandler.exc.msg
|
||||
# ----------------- IO Part --------------------------------------------------
|
||||
|
||||
type
|
||||
CFile {.importc: "FILE", nodecl, final.} = object # empty record for
|
||||
# data hiding
|
||||
TFile* = ptr CFile ## The type representing a file handle.
|
||||
|
||||
TFileMode* = enum ## The file mode when opening a file.
|
||||
fmRead, ## Open the file for read access only.
|
||||
fmWrite, ## Open the file for write access only.
|
||||
fmReadWrite, ## Open the file for read and write access.
|
||||
## If the file does not exist, it will be
|
||||
## created.
|
||||
fmReadWriteExisting, ## Open the file for read and write access.
|
||||
## If the file does not exist, it will not be
|
||||
## created.
|
||||
fmAppend ## Open the file for writing only; append data
|
||||
## at the end.
|
||||
|
||||
# text file handling:
|
||||
var
|
||||
stdin* {.importc: "stdin", noDecl.}: TFile ## The standard input stream.
|
||||
stdout* {.importc: "stdout", noDecl.}: TFile ## The standard output stream.
|
||||
stderr* {.importc: "stderr", noDecl.}: TFile
|
||||
## The standard error stream.
|
||||
##
|
||||
## Note: In my opinion, this should not be used -- the concept of a
|
||||
## separate error stream is a design flaw of UNIX. A seperate *message
|
||||
## stream* is a good idea, but since it is named ``stderr`` there are few
|
||||
## programs out there that distinguish properly between ``stdout`` and
|
||||
## ``stderr``. So, that's what you get if you don't name your variables
|
||||
## appropriately. It also annoys people if redirection via ``>output.txt``
|
||||
## does not work because the program writes to ``stderr``.
|
||||
|
||||
proc OpenFile*(f: var TFile, filename: string,
|
||||
mode: TFileMode = fmRead, bufSize: int = -1): Bool
|
||||
## Opens a file named `filename` with given `mode`.
|
||||
##
|
||||
## Default mode is readonly. Returns true iff the file could be opened.
|
||||
## This throws no exception if the file could not be opened. The reason is
|
||||
## that the programmer needs to provide an appropriate error message anyway
|
||||
## (yes, even in scripts).
|
||||
|
||||
proc CloseFile*(f: TFile) {.importc: "fclose", nodecl.}
|
||||
## Closes the file.
|
||||
proc EndOfFile*(f: TFile): Bool
|
||||
## Returns true iff `f` is at the end.
|
||||
proc readChar*(f: TFile): char {.importc: "fgetc", nodecl.}
|
||||
## Reads a single character from the stream `f`. If the stream
|
||||
## has no more characters, `EEndOfFile` is raised.
|
||||
proc FlushFile*(f: TFile) {.importc: "fflush", noDecl.}
|
||||
## Flushes `f`'s buffer.
|
||||
|
||||
proc readFile*(filename: string): string
|
||||
## Opens a file name `filename` for reading. Then reads the
|
||||
## file's content completely into a string and
|
||||
## closes the file afterwards. Returns the string. Returns nil if there was
|
||||
## an error. Does not throw an IO exception.
|
||||
|
||||
proc write*(f: TFile, r: float)
|
||||
proc write*(f: TFile, i: int)
|
||||
proc write*(f: TFile, s: string)
|
||||
proc write*(f: TFile, b: Bool)
|
||||
proc write*(f: TFile, c: char)
|
||||
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.
|
||||
|
||||
proc readLine*(f: TFile): string
|
||||
## reads a line of text from the file `f`. May throw an IO exception.
|
||||
## Reading from an empty file buffer, does not throw an exception, but
|
||||
## returns nil. A line of text may be delimited by ``CR``, ``LF`` or
|
||||
## ``CRLF``. The newline character(s) are not part of the returned string.
|
||||
|
||||
proc writeln*[Ty](f: TFile, x: Ty) {.inline.}
|
||||
## writes a value `x` to `f` and then writes "\n".
|
||||
## May throw an IO exception.
|
||||
|
||||
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
|
||||
## retrieves the file size (in bytes) of `f`.
|
||||
|
||||
proc ReadBytes*(f: TFile, a: var openarray[byte], start, len: int): int
|
||||
## reads `len` bytes into the buffer `a` starting at ``a[start]``. Returns
|
||||
## the actual number of bytes that have been read which may be less than
|
||||
## `len` (if not as many bytes are remaining), but not greater.
|
||||
|
||||
proc ReadChars*(f: TFile, a: var openarray[char], start, len: int): int
|
||||
## reads `len` bytes into the buffer `a` starting at ``a[start]``. Returns
|
||||
## the actual number of bytes that have been read which may be less than
|
||||
## `len` (if not as many bytes are remaining), but not greater.
|
||||
|
||||
proc readBuffer*(f: TFile, buffer: pointer, len: int): int
|
||||
## reads `len` bytes into the buffer pointed to by `buffer`. Returns
|
||||
## the actual number of bytes that have been read which may be less than
|
||||
## `len` (if not as many bytes are remaining), but not greater.
|
||||
|
||||
proc writeBytes*(f: TFile, a: openarray[byte], start, len: int): int
|
||||
## writes the bytes of ``a[start..start+len-1]`` to the file `f`. Returns
|
||||
## the number of actual written bytes, which may be less than `len` in case
|
||||
## of an error.
|
||||
|
||||
proc writeChars*(f: tFile, a: openarray[char], start, len: int): int
|
||||
## writes the bytes of ``a[start..start+len-1]`` to the file `f`. Returns
|
||||
## the number of actual written bytes, which may be less than `len` in case
|
||||
## of an error.
|
||||
|
||||
proc writeBuffer*(f: TFile, buffer: pointer, len: int): int
|
||||
## writes the bytes of buffer pointed to by the parameter `buffer` to the
|
||||
## file `f`. Returns the number of actual written bytes, which may be less
|
||||
## than `len` in case of an error.
|
||||
|
||||
proc setFilePos*(f: TFile, pos: int64)
|
||||
## sets the position of the file pointer that is used for read/write
|
||||
## operations. The file's first byte has the index zero.
|
||||
|
||||
proc getFilePos*(f: TFile): int64
|
||||
## retrieves the current position of the file pointer that is used to
|
||||
## read from the file `f`. The file's first byte has the index zero.
|
||||
|
||||
include sysio
|
||||
|
||||
iterator lines*(filename: string): string =
|
||||
## Iterate over any line in the file named `filename`.
|
||||
## If the file does not exist `EIO` is raised.
|
||||
var
|
||||
f: TFile
|
||||
if not openFile(f, filename):
|
||||
raise newException(EIO, "cannot open: " & filename)
|
||||
var res = ""
|
||||
while not endOfFile(f):
|
||||
rawReadLine(f, res)
|
||||
yield res
|
||||
CloseFile(f)
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
include excpt
|
||||
# we cannot compile this with stack tracing on
|
||||
# as it would recurse endlessly!
|
||||
include arithm
|
||||
{.pop.} # stack trace
|
||||
|
||||
# sequence type declarations here because the GC needs them too:
|
||||
type
|
||||
TGenericSeq {.importc, nodecl, final.} = object
|
||||
len, space: int
|
||||
|
||||
PGenericSeq {.importc, nodecl.} = ptr TGenericSeq
|
||||
|
||||
const
|
||||
GenericSeqSize = (2 * sizeof(int))
|
||||
|
||||
when not defined(boehmgc) and not defined(nogc):
|
||||
include gc
|
||||
|
||||
include sysstr
|
||||
include assign
|
||||
include dyncalls
|
||||
include repr
|
||||
|
||||
# we have to implement it here after gentostr for the cstrToNimStrDummy proc
|
||||
proc getCurrentExceptionMsg(): string =
|
||||
if excHandler == nil: return ""
|
||||
return $excHandler.exc.msg
|
||||
|
||||
{.push stack_trace: off.}
|
||||
when defined(endb):
|
||||
include debugger
|
||||
{.pop.} # stacktrace
|
||||
|
||||
else:
|
||||
include ecmasys
|
||||
|
||||
include macros
|
||||
|
||||
{.push stack_trace: off.}
|
||||
when defined(endb):
|
||||
include debugger
|
||||
{.pop.} # stacktrace
|
||||
{.pop.} # checks
|
||||
|
||||
{.pop.} # hints
|
||||
|
|
|
|||
256
lib/times.nim
256
lib/times.nim
|
|
@ -1,7 +1,7 @@
|
|||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2006 Andreas Rumpf
|
||||
# (c) Copyright 2008 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
|
||||
## 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
|
||||
# of the standard library!
|
||||
|
|
@ -22,9 +23,49 @@ type
|
|||
TWeekDay* = enum ## represents a weekday
|
||||
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,
|
||||
## normally in the range 0 to 59, but can
|
||||
## be up to 61 to allow for leap seconds.
|
||||
|
|
@ -38,6 +79,7 @@ type
|
|||
weekday*: TWeekDay ## The current day of the week.
|
||||
yearday*: range[0..365] ## The number of days since January 1,
|
||||
## in the range 0 to 365.
|
||||
## Always 0 if the target is ECMAScript.
|
||||
|
||||
proc getTime*(): TTime ## gets the current calendar time
|
||||
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.
|
||||
|
||||
proc `$` *(timeInfo: TTimeInfo): string
|
||||
## converts a `TTimeInfo` record to a
|
||||
## converts a `TTimeInfo` object to a
|
||||
## string representation.
|
||||
proc `$` *(time: TTime): string
|
||||
## converts a calendar time to a
|
||||
|
|
@ -72,92 +114,149 @@ proc `-` *(a, b: TTime): int64
|
|||
proc getStartMilsecs*(): int
|
||||
## get the miliseconds from the start of the program
|
||||
|
||||
#implementation
|
||||
|
||||
# C wrapper:
|
||||
type
|
||||
structTM {.importc: "struct tm".} = record
|
||||
second {.importc: "tm_sec".},
|
||||
minute {.importc: "tm_min".},
|
||||
hour {.importc: "tm_hour".},
|
||||
monthday {.importc: "tm_mday".},
|
||||
month {.importc: "tm_mon".},
|
||||
year {.importc: "tm_year".},
|
||||
weekday {.importc: "tm_wday".},
|
||||
yearday {.importc: "tm_yday".},
|
||||
isdst {.importc: "tm_isdst".}: cint
|
||||
when not defined(ECMAScript):
|
||||
|
||||
PTimeInfo = ptr structTM
|
||||
PTime = ptr TTime
|
||||
# C wrapper:
|
||||
type
|
||||
structTM {.importc: "struct tm", final.} = object
|
||||
second {.importc: "tm_sec".},
|
||||
minute {.importc: "tm_min".},
|
||||
hour {.importc: "tm_hour".},
|
||||
monthday {.importc: "tm_mday".},
|
||||
month {.importc: "tm_mon".},
|
||||
year {.importc: "tm_year".},
|
||||
weekday {.importc: "tm_wday".},
|
||||
yearday {.importc: "tm_yday".},
|
||||
isdst {.importc: "tm_isdst".}: cint
|
||||
|
||||
TClock {.importc: "clock_t".} = range[low(int)..high(int)]
|
||||
PTimeInfo = ptr structTM
|
||||
PTime = ptr TTime
|
||||
|
||||
proc localtime(timer: PTime): PTimeInfo {.
|
||||
importc: "localtime", header: "<time.h>".}
|
||||
proc gmtime(timer: PTime): PTimeInfo {.importc: "gmtime", header: "<time.h>".}
|
||||
proc timec(timer: PTime): TTime {.importc: "time", header: "<time.h>".}
|
||||
proc mktime(t: structTM): TTime {.importc: "mktime", header: "<time.h>".}
|
||||
proc asctime(tblock: structTM): CString {.
|
||||
importc: "asctime", header: "<time.h>".}
|
||||
proc ctime(time: PTime): CString {.importc: "ctime", header: "<time.h>".}
|
||||
# strftime(s: CString, maxsize: int, fmt: CString, t: tm): int {.
|
||||
# importc: "strftime", header: "<time.h>".}
|
||||
proc clock(): TClock {.importc: "clock", header: "<time.h>".}
|
||||
proc difftime(a, b: TTime): float {.importc: "difftime", header: "<time.h>".}
|
||||
TClock {.importc: "clock_t".} = range[low(int)..high(int)]
|
||||
|
||||
var
|
||||
clocksPerSec {.importc: "CLOCKS_PER_SEC", nodecl.}: int
|
||||
proc localtime(timer: PTime): PTimeInfo {.
|
||||
importc: "localtime", header: "<time.h>".}
|
||||
proc gmtime(timer: PTime): PTimeInfo {.importc: "gmtime", header: "<time.h>".}
|
||||
proc timec(timer: PTime): TTime {.importc: "time", header: "<time.h>".}
|
||||
proc mktime(t: structTM): TTime {.importc: "mktime", header: "<time.h>".}
|
||||
proc asctime(tblock: structTM): CString {.
|
||||
importc: "asctime", header: "<time.h>".}
|
||||
proc ctime(time: PTime): CString {.importc: "ctime", header: "<time.h>".}
|
||||
# strftime(s: CString, maxsize: int, fmt: CString, t: tm): int {.
|
||||
# importc: "strftime", header: "<time.h>".}
|
||||
proc clock(): TClock {.importc: "clock", header: "<time.h>".}
|
||||
proc difftime(a, b: TTime): float {.importc: "difftime", header: "<time.h>".}
|
||||
|
||||
var
|
||||
clocksPerSec {.importc: "CLOCKS_PER_SEC", nodecl.}: int
|
||||
|
||||
|
||||
# our own procs on top of that:
|
||||
proc tmToTimeInfo(tm: structTM): TTimeInfo =
|
||||
# our own procs on top of that:
|
||||
proc tmToTimeInfo(tm: structTM): TTimeInfo =
|
||||
const
|
||||
weekDays: array [0..6, TWeekDay] = [
|
||||
dSun, dMon, dTue, dWed, dThu, dFri, dSat]
|
||||
result.second = int(tm.second)
|
||||
result.minute = int(tm.minute)
|
||||
result.hour = int(tm.hour)
|
||||
result.monthday = int(tm.monthday)
|
||||
result.month = TMonth(tm.month)
|
||||
result.year = tm.year + 1900
|
||||
result.weekday = weekDays[int(tm.weekDay)]
|
||||
result.yearday = int(tm.yearday)
|
||||
|
||||
proc timeInfoToTM(t: TTimeInfo): structTM =
|
||||
const
|
||||
weekDays: array [TWeekDay, int] = [1, 2, 3, 4, 5, 6, 0]
|
||||
result.second = t.second
|
||||
result.minute = t.minute
|
||||
result.hour = t.hour
|
||||
result.monthday = t.monthday
|
||||
result.month = ord(t.month)
|
||||
result.year = t.year - 1900
|
||||
result.weekday = weekDays[t.weekDay]
|
||||
result.yearday = t.yearday
|
||||
result.isdst = -1
|
||||
|
||||
proc `-` (a, b: TTime): int64 =
|
||||
return toInt(difftime(a, b)) # XXX: toBiggestInt is needed here, but
|
||||
# Nim does not support it!
|
||||
|
||||
proc getStartMilsecs(): int = return clock() div (clocksPerSec div 1000)
|
||||
proc getTime(): TTime = return timec(nil)
|
||||
proc getLocalTime(t: TTime): TTimeInfo =
|
||||
var a = t
|
||||
result = tmToTimeInfo(localtime(addr(a))^)
|
||||
# copying is needed anyway to provide reentrancity; thus
|
||||
# the convertion is not expensive
|
||||
|
||||
proc getGMTime(t: TTime): TTimeInfo =
|
||||
var a = t
|
||||
result = tmToTimeInfo(gmtime(addr(a))^)
|
||||
# copying is needed anyway to provide reentrancity; thus
|
||||
# the convertion is not expensive
|
||||
|
||||
proc TimeInfoToTime(timeInfo: TTimeInfo): TTime =
|
||||
var cTimeInfo = timeInfo # for C++ we have to make a copy,
|
||||
# because the header of mktime is broken in my version of libc
|
||||
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]
|
||||
result.second = int(tm.second)
|
||||
result.minute = int(tm.minute)
|
||||
result.hour = int(tm.hour)
|
||||
result.monthday = int(tm.monthday)
|
||||
result.month = TMonth(tm.month)
|
||||
result.year = tm.year + 1900
|
||||
result.weekday = weekDays[int(tm.weekDay)]
|
||||
result.yearday = int(tm.yearday)
|
||||
|
||||
proc timeInfoToTM(t: TTimeInfo): structTM =
|
||||
const
|
||||
weekDays: array [TWeekDay, int] = [1, 2, 3, 4, 5, 6, 0]
|
||||
result.second = t.second
|
||||
result.minute = t.minute
|
||||
result.hour = t.hour
|
||||
result.monthday = t.monthday
|
||||
result.month = ord(t.month)
|
||||
result.year = t.year - 1900
|
||||
result.weekday = weekDays[t.weekDay]
|
||||
result.yearday = t.yearday
|
||||
result.isdst = -1
|
||||
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 `-` (a, b: TTime): int64 =
|
||||
return toInt(difftime(a, b)) # XXX: toBiggestInt is needed here, but
|
||||
# Nim does not support it!
|
||||
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 getStartMilsecs(): int = return clock() div (clocksPerSec div 1000)
|
||||
proc getTime(): TTime = return timec(nil)
|
||||
proc getLocalTime(t: TTime): TTimeInfo =
|
||||
var a = t
|
||||
result = tmToTimeInfo(localtime(addr(a))^)
|
||||
# copying is needed anyway to provide reentrancity; thus
|
||||
# the convertion is not expensive
|
||||
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 getGMTime(t: TTime): TTimeInfo =
|
||||
var a = t
|
||||
result = tmToTimeInfo(gmtime(addr(a))^)
|
||||
# copying is needed anyway to provide reentrancity; thus
|
||||
# the convertion is not expensive
|
||||
proc `$`(timeInfo: TTimeInfo): string = return $(TimeInfoToTIme(timeInfo))
|
||||
proc `$`(time: TTime): string = $time.toLocaleString()
|
||||
|
||||
proc TimeInfoToTime(timeInfo: TTimeInfo): TTime =
|
||||
var cTimeInfo = timeInfo # for C++ we have to make a copy,
|
||||
# because the header of mktime is broken in my version of libc
|
||||
return mktime(timeInfoToTM(cTimeInfo))
|
||||
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 =
|
||||
var ti = getLocalTime(getTime())
|
||||
|
|
@ -169,11 +268,4 @@ proc getClockStr(): string =
|
|||
result = intToStr(ti.hour, 2) & ':' & intToStr(ti.minute, 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.}
|
||||
|
|
|
|||
221
lib/typeinfo.nim
221
lib/typeinfo.nim
|
|
@ -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
|
||||
|
|
@ -980,7 +980,7 @@ const
|
|||
#/////////////////////////////////////////////////////////
|
||||
|
||||
type
|
||||
mmtime* = record
|
||||
mmtime* {.final.} = object
|
||||
wType*: UINT
|
||||
hour*, min*, sec*, frame*, fps*, dummy*: int8
|
||||
pad*: array[0..1, int8]
|
||||
|
|
@ -990,7 +990,7 @@ type
|
|||
LPMMTIME* = ptr mmtime
|
||||
PWAVEHDR* = ptr wavehdr
|
||||
TMMTime* = mmtime
|
||||
wavehdr* = record
|
||||
wavehdr* {.final.} = object
|
||||
lpData*: cstring
|
||||
dwBufferLength*: DWORD
|
||||
dwBytesRecorded*: DWORD
|
||||
|
|
@ -1003,7 +1003,7 @@ type
|
|||
TWAVEHDR* = WAVEHDR
|
||||
NPWAVEHDR* = ptr wavehdr
|
||||
LPWAVEHDR* = ptr wavehdr
|
||||
WAVEOUTCAPSA* = record
|
||||
WAVEOUTCAPSA* {.final.} = object
|
||||
wMid*: int16
|
||||
wPid*: int16
|
||||
vDriverVersion*: MMVERSION
|
||||
|
|
@ -1017,7 +1017,7 @@ type
|
|||
PWAVEOUTCAPSA* = ptr WAVEOUTCAPSA
|
||||
NPWAVEOUTCAPSA* = ptr WAVEOUTCAPSA
|
||||
LPWAVEOUTCAPSA* = ptr WAVEOUTCAPSA
|
||||
WAVEOUTCAPSW* = record
|
||||
WAVEOUTCAPSW* {.final.} = object
|
||||
wMid*: int16
|
||||
wPid*: int16
|
||||
vDriverVersion*: MMVERSION
|
||||
|
|
@ -1046,7 +1046,7 @@ else:
|
|||
LPWAVEOUTCAPS* = LPWAVEOUTCAPSA
|
||||
type
|
||||
TWAVEOUTCAPS* = WAVEOUTCAPS
|
||||
WAVEINCAPSA* = record
|
||||
WAVEINCAPSA* {.final.} = object
|
||||
wMid*: int16
|
||||
wPid*: int16
|
||||
vDriverVersion*: MMVERSION
|
||||
|
|
@ -1059,7 +1059,7 @@ type
|
|||
NPWAVEINCAPSA* = ptr WAVEINCAPSA
|
||||
LPWAVEINCAPSA* = ptr WAVEINCAPSA
|
||||
TWAVEINCAPSA* = WAVEINCAPSA
|
||||
WAVEINCAPSW* = record
|
||||
WAVEINCAPSW* {.final.} = object
|
||||
wMid*: int16
|
||||
wPid*: int16
|
||||
vDriverVersion*: MMVERSION
|
||||
|
|
@ -1087,7 +1087,7 @@ else:
|
|||
LPWAVEINCAPS* = LPWAVEINCAPSA
|
||||
type
|
||||
TWAVEINCAPS* = WAVEINCAPS
|
||||
waveformat* = record
|
||||
waveformat* {.final.} = object
|
||||
wFormatTag*: int16
|
||||
nChannels*: int16
|
||||
nSamplesPerSec*: DWORD
|
||||
|
|
@ -1103,7 +1103,7 @@ const
|
|||
WAVE_FORMAT_PCM* = 1
|
||||
|
||||
type
|
||||
pcmwaveformat* = record
|
||||
pcmwaveformat* {.final.} = object
|
||||
wf*: WAVEFORMAT
|
||||
wBitsPerSample*: int16
|
||||
|
||||
|
|
@ -1111,7 +1111,7 @@ type
|
|||
NPPCMWAVEFORMAT* = ptr pcmwaveformat
|
||||
LPPCMWAVEFORMAT* = ptr pcmwaveformat
|
||||
TPCMWAVEFORMAT* = PCMWAVEFORMAT
|
||||
WAVEFORMATEX* = record
|
||||
WAVEFORMATEX* {.final.} = object
|
||||
wFormatTag*: int16
|
||||
nChannels*: int16
|
||||
nSamplesPerSec*: DWORD
|
||||
|
|
@ -1143,7 +1143,7 @@ type
|
|||
LPPATCHARRAY* = ptr int16
|
||||
KEYARRAY* = array[0..Pred(MIDIPATCHSIZE), int16]
|
||||
LPKEYARRAY* = ptr int16
|
||||
MIDIOUTCAPSA* = record
|
||||
MIDIOUTCAPSA* {.final.} = object
|
||||
wMid*: int16
|
||||
wPid*: int16
|
||||
vDriverVersion*: MMVERSION
|
||||
|
|
@ -1158,7 +1158,7 @@ type
|
|||
NPMIDIOUTCAPSA* = ptr MIDIOUTCAPSA
|
||||
LPMIDIOUTCAPSA* = ptr MIDIOUTCAPSA
|
||||
TMIDIOUTCAPSA* = MIDIOUTCAPSA
|
||||
MIDIOUTCAPSW* = record
|
||||
MIDIOUTCAPSW* {.final.} = object
|
||||
wMid*: int16
|
||||
wPid*: int16
|
||||
vDriverVersion*: MMVERSION
|
||||
|
|
@ -1173,7 +1173,7 @@ type
|
|||
NPMIDIOUTCAPSW* = ptr MIDIOUTCAPSW
|
||||
LPMIDIOUTCAPSW* = ptr MIDIOUTCAPSW
|
||||
TMIDIOUTCAPSW* = MIDIOUTCAPSW
|
||||
MIDIINCAPSA* = record
|
||||
MIDIINCAPSA* {.final.} = object
|
||||
wMid*: int16
|
||||
wPid*: int16
|
||||
vDriverVersion*: MMVERSION
|
||||
|
|
@ -1184,7 +1184,7 @@ type
|
|||
NPMIDIINCAPSA* = ptr MIDIINCAPSA
|
||||
LPMIDIINCAPSA* = ptr MIDIINCAPSA
|
||||
TMIDIINCAPSA* = MIDIINCAPSA
|
||||
MIDIINCAPSW* = record
|
||||
MIDIINCAPSW* {.final.} = object
|
||||
wMid*: int16
|
||||
wPid*: int16
|
||||
vDriverVersion*: MMVERSION
|
||||
|
|
@ -1219,7 +1219,7 @@ else:
|
|||
type
|
||||
TMIDIINCAPS* = MIDIINCAPS
|
||||
PMIDIHDR* = ptr midihdr
|
||||
midihdr* = record
|
||||
midihdr* {.final.} = object
|
||||
lpData*: cstring
|
||||
dwBufferLength*: DWORD
|
||||
dwBytesRecorded*: DWORD
|
||||
|
|
@ -1233,30 +1233,30 @@ type
|
|||
NPMIDIHDR* = ptr midihdr
|
||||
LPMIDIHDR* = ptr midihdr
|
||||
TMIDIHDR* = MIDIHDR
|
||||
midievent* = record
|
||||
midievent* {.final.} = object
|
||||
dwDeltaTime*: DWORD
|
||||
dwStreamID*: DWORD
|
||||
dwEvent*: DWORD
|
||||
dwParms*: array[0..Pred(1), DWORD]
|
||||
|
||||
TMIDIEVENT* = MIDIEVENT
|
||||
midistrmbuffver* = record
|
||||
midistrmbuffver* {.final.} = object
|
||||
dwVersion*: DWORD
|
||||
dwMid*: DWORD
|
||||
dwOEMVersion*: DWORD
|
||||
|
||||
TMIDISTRMBUFFVER* = MIDISTRMBUFFVER
|
||||
Tmidiproptimediv* = record
|
||||
Tmidiproptimediv* {.final.} = object
|
||||
cbStruct*: DWORD
|
||||
dwTimeDiv*: DWORD
|
||||
|
||||
LPMIDIPROPTIMEDIV* = ptr Tmidiproptimediv
|
||||
Tmidiproptempo* = record
|
||||
Tmidiproptempo* {.final.} = object
|
||||
cbStruct*: DWORD
|
||||
dwTempo*: DWORD
|
||||
|
||||
LPMIDIPROPTEMPO* = ptr Tmidiproptempo
|
||||
AUXCAPSA* = record
|
||||
AUXCAPSA* {.final.} = object
|
||||
wMid*: int16
|
||||
wPid*: int16
|
||||
vDriverVersion*: MMVERSION
|
||||
|
|
@ -1269,7 +1269,7 @@ type
|
|||
NPAUXCAPSA* = ptr AUXCAPSA
|
||||
LPAUXCAPSA* = ptr AUXCAPSA
|
||||
TAUXCAPSA* = AUXCAPSA
|
||||
AUXCAPSW* = record
|
||||
AUXCAPSW* {.final.} = object
|
||||
wMid*: int16
|
||||
wPid*: int16
|
||||
vDriverVersion*: MMVERSION
|
||||
|
|
@ -1305,7 +1305,7 @@ type
|
|||
proc mixerGetNumDevs*(): UINT{.stdcall, dynlib: "winmm.dll",
|
||||
importc: "mixerGetNumDevs".}
|
||||
type
|
||||
MIXERCAPSA* = record
|
||||
MIXERCAPSA* {.final.} = object
|
||||
wMid*: int16
|
||||
wPid*: int16
|
||||
vDriverVersion*: MMVERSION
|
||||
|
|
@ -1316,7 +1316,7 @@ type
|
|||
PMIXERCAPSA* = ptr MIXERCAPSA
|
||||
LPMIXERCAPSA* = ptr MIXERCAPSA
|
||||
TMIXERCAPSA* = MIXERCAPSA
|
||||
MIXERCAPSW* = record
|
||||
MIXERCAPSW* {.final.} = object
|
||||
wMid*: int16
|
||||
wPid*: int16
|
||||
vDriverVersion*: MMVERSION
|
||||
|
|
@ -1340,7 +1340,7 @@ else:
|
|||
LPMIXERCAPS* = LPMIXERCAPSA
|
||||
type
|
||||
TMIXERCAPS* = MIXERCAPS
|
||||
MIXERLINEA* = record
|
||||
MIXERLINEA* {.final.} = object
|
||||
cbStruct*: DWORD
|
||||
dwDestination*: DWORD
|
||||
dwSource*: DWORD
|
||||
|
|
@ -1361,7 +1361,7 @@ type
|
|||
PMIXERLINEA* = ptr MIXERLINEA
|
||||
LPMIXERLINEA* = ptr MIXERLINEA
|
||||
TMIXERLINEA* = MIXERLINEA
|
||||
MIXERLINEW* = record
|
||||
MIXERLINEW* {.final.} = object
|
||||
cbStruct*: DWORD
|
||||
dwDestination*: DWORD
|
||||
dwSource*: DWORD
|
||||
|
|
@ -1395,7 +1395,7 @@ else:
|
|||
LPMIXERLINE* = LPMIXERLINEA
|
||||
type
|
||||
TMIXERLINE* = MIXERLINE
|
||||
MIXERCONTROLA* = record
|
||||
MIXERCONTROLA* {.final.} = object
|
||||
cbStruct*: DWORD
|
||||
dwControlID*: DWORD
|
||||
dwControlType*: DWORD
|
||||
|
|
@ -1411,7 +1411,7 @@ type
|
|||
PMIXERCONTROLA* = ptr MIXERCONTROLA
|
||||
LPMIXERCONTROLA* = ptr MIXERCONTROLA
|
||||
TMIXERCONTROLA* = MIXERCONTROLA
|
||||
MIXERCONTROLW* = record
|
||||
MIXERCONTROLW* {.final.} = object
|
||||
cbStruct*: DWORD
|
||||
dwControlID*: DWORD
|
||||
dwControlType*: DWORD
|
||||
|
|
@ -1440,7 +1440,7 @@ else:
|
|||
LPMIXERCONTROL* = LPMIXERCONTROLA
|
||||
type
|
||||
TMIXERCONTROL* = MIXERCONTROL
|
||||
MIXERLINECONTROLSA* = record
|
||||
MIXERLINECONTROLSA* {.final.} = object
|
||||
cbStruct*: DWORD
|
||||
dwLineID*: DWORD
|
||||
dwControlType*, cControls*, cbmxctrl*: DWORD
|
||||
|
|
@ -1449,7 +1449,7 @@ type
|
|||
PMIXERLINECONTROLSA* = ptr MIXERLINECONTROLSA
|
||||
LPMIXERLINECONTROLSA* = ptr MIXERLINECONTROLSA
|
||||
TMIXERLINECONTROLSA* = MIXERLINECONTROLSA
|
||||
MIXERLINECONTROLSW* = record
|
||||
MIXERLINECONTROLSW* {.final.} = object
|
||||
cbStruct*: DWORD
|
||||
dwLineID*: DWORD
|
||||
dwControlType*, cControls*, cbmxctrl*: DWORD
|
||||
|
|
@ -1471,7 +1471,7 @@ else:
|
|||
LPMIXERLINECONTROLS* = LPMIXERLINECONTROLSA
|
||||
type
|
||||
TMIXERLINECONTROLS* = MIXERLINECONTROLS
|
||||
TMIXERCONTROLDETAILS* = record
|
||||
TMIXERCONTROLDETAILS* {.final.} = object
|
||||
cbStruct*: DWORD
|
||||
dwControlID*: DWORD
|
||||
cChannels*: DWORD
|
||||
|
|
@ -1481,7 +1481,7 @@ type
|
|||
MIXERCONTROLDETAILS* = tMIXERCONTROLDETAILS
|
||||
PMIXERCONTROLDETAILS* = ptr tMIXERCONTROLDETAILS
|
||||
LPMIXERCONTROLDETAILS* = ptr tMIXERCONTROLDETAILS
|
||||
MIXERCONTROLDETAILS_LISTTEXTA* = record
|
||||
MIXERCONTROLDETAILS_LISTTEXTA* {.final.} = object
|
||||
dwParam1*: DWORD
|
||||
dwParam2*: DWORD
|
||||
szName*: array[0..Pred(MIXER_LONG_NAME_CHARS), CHAR]
|
||||
|
|
@ -1489,7 +1489,7 @@ type
|
|||
PMIXERCONTROLDETAILS_LISTTEXTA* = ptr MIXERCONTROLDETAILS_LISTTEXTA
|
||||
LPMIXERCONTROLDETAILS_LISTTEXTA* = ptr MIXERCONTROLDETAILS_LISTTEXTA
|
||||
TMIXERCONTROLDETAILS_LISTTEXTA* = MIXERCONTROLDETAILS_LISTTEXTA
|
||||
MIXERCONTROLDETAILS_LISTTEXTW* = record
|
||||
MIXERCONTROLDETAILS_LISTTEXTW* {.final.} = object
|
||||
dwParam1*: DWORD
|
||||
dwParam2*: DWORD
|
||||
szName*: array[0..Pred(MIXER_LONG_NAME_CHARS), WCHAR]
|
||||
|
|
@ -1510,19 +1510,19 @@ else:
|
|||
LPMIXERCONTROLDETAILS_LISTTEXT* = LPMIXERCONTROLDETAILS_LISTTEXTA
|
||||
type
|
||||
TMIXERCONTROLDETAILS_LISTTEXT* = MIXERCONTROLDETAILS_LISTTEXT
|
||||
MIXERCONTROLDETAILS_BOOLEAN* = record
|
||||
MIXERCONTROLDETAILS_BOOLEAN* {.final.} = object
|
||||
fValue*: int32
|
||||
|
||||
PMIXERCONTROLDETAILS_BOOLEAN* = ptr MIXERCONTROLDETAILS_BOOLEAN
|
||||
LPMIXERCONTROLDETAILS_BOOLEAN* = ptr MIXERCONTROLDETAILS_BOOLEAN
|
||||
TMIXERCONTROLDETAILS_BOOLEAN* = MIXERCONTROLDETAILS_BOOLEAN
|
||||
MIXERCONTROLDETAILS_SIGNED* = record
|
||||
MIXERCONTROLDETAILS_SIGNED* {.final.} = object
|
||||
lValue*: int32
|
||||
|
||||
PMIXERCONTROLDETAILS_SIGNED* = ptr MIXERCONTROLDETAILS_SIGNED
|
||||
LPMIXERCONTROLDETAILS_SIGNED* = ptr MIXERCONTROLDETAILS_SIGNED
|
||||
TMIXERCONTROLDETAILS_SIGNED* = MIXERCONTROLDETAILS_SIGNED
|
||||
MIXERCONTROLDETAILS_UNSIGNED* = record
|
||||
MIXERCONTROLDETAILS_UNSIGNED* {.final.} = object
|
||||
dwValue*: DWORD
|
||||
|
||||
PMIXERCONTROLDETAILS_UNSIGNED* = ptr MIXERCONTROLDETAILS_UNSIGNED
|
||||
|
|
@ -1531,7 +1531,7 @@ type
|
|||
LPTIMECALLBACK* = proc (uTimerID, uMsg: UINT, dwUser, dw1, dw2: DWORD){.
|
||||
stdcall.}
|
||||
TTIMECALLBACK* = LPTIMECALLBACK
|
||||
timecaps* = record
|
||||
timecaps* {.final.} = object
|
||||
wPeriodMin*: UINT
|
||||
wPeriodMax*: UINT
|
||||
|
||||
|
|
@ -1539,7 +1539,7 @@ type
|
|||
NPTIMECAPS* = ptr timecaps
|
||||
LPTIMECAPS* = ptr timecaps
|
||||
TTIMECAS* = TIMECAPS
|
||||
JOYCAPSA* = record
|
||||
JOYCAPSA* {.final.} = object
|
||||
wMid*: int16
|
||||
wPid*: int16
|
||||
szPname*: array[0..Pred(MAXPNAMELEN), CHAR]
|
||||
|
|
@ -1569,7 +1569,7 @@ type
|
|||
NPJOYCAPSA* = ptr JOYCAPSA
|
||||
LPJOYCAPSA* = ptr JOYCAPSA
|
||||
TJOYCAPSA* = JOYCAPSA
|
||||
JOYCAPSW* = record
|
||||
JOYCAPSW* {.final.} = object
|
||||
wMid*: int16
|
||||
wPid*: int16
|
||||
szPname*: array[0..Pred(MAXPNAMELEN), WCHAR]
|
||||
|
|
@ -1614,7 +1614,7 @@ else:
|
|||
LPJOYCAPS* = LPJOYCAPSA
|
||||
type
|
||||
TJOYCAPS* = JOYCAPS
|
||||
joyinfo* = record
|
||||
joyinfo* {.final.} = object
|
||||
wXpos*: UINT
|
||||
wYpos*: UINT
|
||||
wZpos*: UINT
|
||||
|
|
@ -1624,7 +1624,7 @@ type
|
|||
NPJOYINFO* = ptr joyinfo
|
||||
LPJOYINFO* = ptr joyinfo
|
||||
TJOYINFO* = JOYINFO
|
||||
joyinfoex* = record
|
||||
joyinfoex* {.final.} = object
|
||||
dwSize*: DWORD
|
||||
dwFlags*: DWORD
|
||||
wXpos*: UINT
|
||||
|
|
@ -1648,7 +1648,7 @@ type
|
|||
HMMIO* = THandle
|
||||
LPMMIOPROC* = proc (x1: LPSTR, x2: UINT, x3, x4: LPARAM): LRESULT{.stdcall.}
|
||||
TMMIOPROC* = LPMMIOPROC
|
||||
MMIOINFO* = record
|
||||
MMIOINFO* {.final.} = object
|
||||
dwFlags*: DWORD
|
||||
fccIOProc*: FOURCC
|
||||
pIOProc*: LPMMIOPROC
|
||||
|
|
@ -1671,7 +1671,7 @@ type
|
|||
LPMMIOINFO* = ptr MMIOINFO
|
||||
LPCMMIOINFO* = ptr MMIOINFO
|
||||
TMMIOINFO* = MMIOINFO
|
||||
MMCKINFO* = record
|
||||
MMCKINFO* {.final.} = object
|
||||
ckid*: FOURCC
|
||||
cksize*: DWORD
|
||||
fccType*: FOURCC
|
||||
|
|
@ -1687,13 +1687,13 @@ type
|
|||
MCIDEVICEID* = UINT
|
||||
YIELDPROC* = proc (mciId: MCIDEVICEID, dwYieldData: DWORD): UINT{.stdcall.}
|
||||
TYIELDPROC* = YIELDPROC
|
||||
MCI_GENERIC_PARMS* = record
|
||||
MCI_GENERIC_PARMS* {.final.} = object
|
||||
dwCallback*: DWORD
|
||||
|
||||
PMCI_GENERIC_PARMS* = ptr MCI_GENERIC_PARMS
|
||||
LPMCI_GENERIC_PARMS* = ptr MCI_GENERIC_PARMS
|
||||
TMCI_GENERIC_PARMS* = MCI_GENERIC_PARMS
|
||||
MCI_OPEN_PARMSA* = record
|
||||
MCI_OPEN_PARMSA* {.final.} = object
|
||||
dwCallback*: DWORD
|
||||
wDeviceID*: MCIDEVICEID
|
||||
lpstrDeviceType*: LPCSTR
|
||||
|
|
@ -1703,7 +1703,7 @@ type
|
|||
PMCI_OPEN_PARMSA* = ptr MCI_OPEN_PARMSA
|
||||
LPMCI_OPEN_PARMSA* = ptr MCI_OPEN_PARMSA
|
||||
TMCI_OPEN_PARMSA* = MCI_OPEN_PARMSA
|
||||
MCI_OPEN_PARMSW* = record
|
||||
MCI_OPEN_PARMSW* {.final.} = object
|
||||
dwCallback*: DWORD
|
||||
wDeviceID*: MCIDEVICEID
|
||||
lpstrDeviceType*: LPCWSTR
|
||||
|
|
@ -1726,7 +1726,7 @@ else:
|
|||
LPMCI_OPEN_PARMS* = LPMCI_OPEN_PARMSA
|
||||
type
|
||||
TMCI_OPEN_PARMS* = MCI_OPEN_PARMS
|
||||
MCI_PLAY_PARMS* = record
|
||||
MCI_PLAY_PARMS* {.final.} = object
|
||||
dwCallback*: DWORD
|
||||
dwFrom*: DWORD
|
||||
dwTo*: DWORD
|
||||
|
|
@ -1734,14 +1734,14 @@ type
|
|||
PMCI_PLAY_PARMS* = ptr MCI_PLAY_PARMS
|
||||
LPMCI_PLAY_PARMS* = ptr MCI_PLAY_PARMS
|
||||
TMCI_PLAY_PARMS* = MCI_PLAY_PARMS
|
||||
MCI_SEEK_PARMS* = record
|
||||
MCI_SEEK_PARMS* {.final.} = object
|
||||
dwCallback*: DWORD
|
||||
dwTo*: DWORD
|
||||
|
||||
PMCI_SEEK_PARMS* = ptr MCI_SEEK_PARMS
|
||||
LPMCI_SEEK_PARMS* = ptr MCI_SEEK_PARMS
|
||||
TMCI_SEEK_PARMS* = MCI_SEEK_PARMS
|
||||
MCI_STATUS_PARMS* = record
|
||||
MCI_STATUS_PARMS* {.final.} = object
|
||||
dwCallback*: DWORD
|
||||
dwReturn*: DWORD
|
||||
dwItem*: DWORD
|
||||
|
|
@ -1750,14 +1750,14 @@ type
|
|||
PMCI_STATUS_PARMS* = ptr MCI_STATUS_PARMS
|
||||
LPMCI_STATUS_PARMS* = ptr MCI_STATUS_PARMS
|
||||
TMCI_STATUS_PARMS* = MCI_STATUS_PARMS
|
||||
MCI_INFO_PARMSA* = record
|
||||
MCI_INFO_PARMSA* {.final.} = object
|
||||
dwCallback*: DWORD
|
||||
lpstrReturn*: cstring
|
||||
dwRetSize*: DWORD
|
||||
|
||||
LPMCI_INFO_PARMSA* = ptr MCI_INFO_PARMSA
|
||||
TMCI_INFO_PARMSA* = MCI_INFO_PARMSA
|
||||
MCI_INFO_PARMSW* = record
|
||||
MCI_INFO_PARMSW* {.final.} = object
|
||||
dwCallback*: DWORD
|
||||
lpstrReturn*: LPWSTR
|
||||
dwRetSize*: DWORD
|
||||
|
|
@ -1775,7 +1775,7 @@ else:
|
|||
LPMCI_INFO_PARMS* = LPMCI_INFO_PARMSA
|
||||
type
|
||||
TMCI_INFO_PARMS* = MCI_INFO_PARMS
|
||||
MCI_GETDEVCAPS_PARMS* = record
|
||||
MCI_GETDEVCAPS_PARMS* {.final.} = object
|
||||
dwCallback*: DWORD
|
||||
dwReturn*: DWORD
|
||||
dwItem*: DWORD
|
||||
|
|
@ -1783,7 +1783,7 @@ type
|
|||
PMCI_GETDEVCAPS_PARMS* = ptr MCI_GETDEVCAPS_PARMS
|
||||
LPMCI_GETDEVCAPS_PARMS* = ptr MCI_GETDEVCAPS_PARMS
|
||||
TMCI_GETDEVCAPS_PARMS* = MCI_GETDEVCAPS_PARMS
|
||||
MCI_SYSINFO_PARMSA* = record
|
||||
MCI_SYSINFO_PARMSA* {.final.} = object
|
||||
dwCallback*: DWORD
|
||||
lpstrReturn*: cstring
|
||||
dwRetSize*: DWORD
|
||||
|
|
@ -1793,7 +1793,7 @@ type
|
|||
PMCI_SYSINFO_PARMSA* = ptr MCI_SYSINFO_PARMSA
|
||||
LPMCI_SYSINFO_PARMSA* = ptr MCI_SYSINFO_PARMSA
|
||||
TMCI_SYSINFO_PARMSA* = MCI_SYSINFO_PARMSA
|
||||
MCI_SYSINFO_PARMSW* = record
|
||||
MCI_SYSINFO_PARMSW* {.final.} = object
|
||||
dwCallback*: DWORD
|
||||
lpstrReturn*: LPWSTR
|
||||
dwRetSize*: DWORD
|
||||
|
|
@ -1816,7 +1816,7 @@ else:
|
|||
LPMCI_SYSINFO_PARMS* = LPMCI_SYSINFO_PARMSA
|
||||
type
|
||||
TMCI_SYSINFO_PARMS* = MCI_SYSINFO_PARMS
|
||||
MCI_SET_PARMS* = record
|
||||
MCI_SET_PARMS* {.final.} = object
|
||||
dwCallback*: DWORD
|
||||
dwTimeFormat*: DWORD
|
||||
dwAudio*: DWORD
|
||||
|
|
@ -1824,7 +1824,7 @@ type
|
|||
PMCI_SET_PARMS* = ptr MCI_SET_PARMS
|
||||
LPMCI_SET_PARMS* = ptr MCI_SET_PARMS
|
||||
TMCI_SET_PARMS* = MCI_SET_PARMS
|
||||
MCI_BREAK_PARMS* = record
|
||||
MCI_BREAK_PARMS* {.final.} = object
|
||||
dwCallback*: DWORD
|
||||
nVirtKey*: int32
|
||||
hwndBreak*: HWND
|
||||
|
|
@ -1832,14 +1832,14 @@ type
|
|||
PMCI_BREAK_PARMS* = ptr MCI_BREAK_PARMS
|
||||
LPMCI_BREAK_PARMS* = ptr MCI_BREAK_PARMS
|
||||
TMCI_BREAK_PARMS* = MCI_BREAK_PARMS
|
||||
MCI_SAVE_PARMSA* = record
|
||||
MCI_SAVE_PARMSA* {.final.} = object
|
||||
dwCallback*: DWORD
|
||||
lpfilename*: LPCSTR
|
||||
|
||||
PMCI_SAVE_PARMSA* = ptr MCI_SAVE_PARMSA
|
||||
LPMCI_SAVE_PARMSA* = ptr MCI_SAVE_PARMSA
|
||||
TMCI_SAVE_PARMSA* = MCI_SAVE_PARMSA
|
||||
MCI_SAVE_PARMSW* = record
|
||||
MCI_SAVE_PARMSW* {.final.} = object
|
||||
dwCallback*: DWORD
|
||||
lpfilename*: LPCWSTR
|
||||
|
||||
|
|
@ -1859,14 +1859,14 @@ else:
|
|||
LPMCI_SAVE_PARMS* = LPMCI_SAVE_PARMSA
|
||||
type
|
||||
TMCI_SAVE_PARMS* = MCI_SAVE_PARMS
|
||||
MCI_LOAD_PARMSA* = record
|
||||
MCI_LOAD_PARMSA* {.final.} = object
|
||||
dwCallback*: DWORD
|
||||
lpfilename*: LPCSTR
|
||||
|
||||
PMCI_LOAD_PARMSA* = ptr MCI_LOAD_PARMSA
|
||||
LPMCI_LOAD_PARMSA* = ptr MCI_LOAD_PARMSA
|
||||
TMCI_LOAD_PARMSA* = MCI_LOAD_PARMSA
|
||||
MCI_LOAD_PARMSW* = record
|
||||
MCI_LOAD_PARMSW* {.final.} = object
|
||||
dwCallback*: DWORD
|
||||
lpfilename*: LPCWSTR
|
||||
|
||||
|
|
@ -1886,14 +1886,14 @@ else:
|
|||
LPMCI_LOAD_PARMS* = LPMCI_LOAD_PARMSA
|
||||
type
|
||||
TMCI_LOAD_PARMS* = MCI_LOAD_PARMS
|
||||
MCI_RECORD_PARMS* = record
|
||||
MCI_RECORD_PARMS* {.final.} = object
|
||||
dwCallback*: DWORD
|
||||
dwFrom*: DWORD
|
||||
dwTo*: DWORD
|
||||
|
||||
LPMCI_RECORD_PARMS* = ptr MCI_RECORD_PARMS
|
||||
TMCI_RECORD_PARMS* = MCI_RECORD_PARMS
|
||||
MCI_VD_PLAY_PARMS* = record
|
||||
MCI_VD_PLAY_PARMS* {.final.} = object
|
||||
dwCallback*: DWORD
|
||||
dwFrom*: DWORD
|
||||
dwTo*: DWORD
|
||||
|
|
@ -1902,20 +1902,20 @@ type
|
|||
PMCI_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
|
||||
MCI_VD_STEP_PARMS* = record
|
||||
MCI_VD_STEP_PARMS* {.final.} = object
|
||||
dwCallback*: DWORD
|
||||
dwFrames*: DWORD
|
||||
|
||||
PMCI_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
|
||||
lpstrCommand*: LPCSTR
|
||||
|
||||
PMCI_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
|
||||
MCI_VD_ESCAPE_PARMSW* = record
|
||||
MCI_VD_ESCAPE_PARMSW* {.final.} = object
|
||||
dwCallback*: DWORD
|
||||
lpstrCommand*: LPCWSTR
|
||||
|
||||
|
|
@ -1935,7 +1935,7 @@ else:
|
|||
LPMCI_VD_ESCAPE_PARMS* = LPMCI_VD_ESCAPE_PARMSA
|
||||
type
|
||||
TMCI_VD_ESCAPE_PARMS* = MCI_VD_ESCAPE_PARMS
|
||||
MCI_WAVE_OPEN_PARMSA* = record
|
||||
MCI_WAVE_OPEN_PARMSA* {.final.} = object
|
||||
dwCallback*: DWORD
|
||||
wDeviceID*: MCIDEVICEID
|
||||
lpstrDeviceType*: LPCSTR
|
||||
|
|
@ -1946,7 +1946,7 @@ type
|
|||
PMCI_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
|
||||
MCI_WAVE_OPEN_PARMSW* = record
|
||||
MCI_WAVE_OPEN_PARMSW* {.final.} = object
|
||||
dwCallback*: DWORD
|
||||
wDeviceID*: MCIDEVICEID
|
||||
lpstrDeviceType*: LPCWSTR
|
||||
|
|
@ -1970,7 +1970,7 @@ else:
|
|||
LPMCI_WAVE_OPEN_PARMS* = LPMCI_WAVE_OPEN_PARMSA
|
||||
type
|
||||
TMCI_WAVE_OPEN_PARMS* = MCI_WAVE_OPEN_PARMS
|
||||
MCI_WAVE_DELETE_PARMS* = record
|
||||
MCI_WAVE_DELETE_PARMS* {.final.} = object
|
||||
dwCallback*: DWORD
|
||||
dwFrom*: DWORD
|
||||
dwTo*: DWORD
|
||||
|
|
@ -1978,7 +1978,7 @@ type
|
|||
PMCI_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
|
||||
MCI_WAVE_SET_PARMS* = record
|
||||
MCI_WAVE_SET_PARMS* {.final.} = object
|
||||
dwCallback*: DWORD
|
||||
dwTimeFormat*: DWORD
|
||||
dwAudio*: DWORD
|
||||
|
|
@ -1998,7 +1998,7 @@ type
|
|||
PMCI_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
|
||||
MCI_SEQ_SET_PARMS* = record
|
||||
MCI_SEQ_SET_PARMS* {.final.} = object
|
||||
dwCallback*: DWORD
|
||||
dwTimeFormat*: DWORD
|
||||
dwAudio*: DWORD
|
||||
|
|
@ -2011,7 +2011,7 @@ type
|
|||
PMCI_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
|
||||
MCI_ANIM_OPEN_PARMSA* = record
|
||||
MCI_ANIM_OPEN_PARMSA* {.final.} = object
|
||||
dwCallback*: DWORD
|
||||
wDeviceID*: MCIDEVICEID
|
||||
lpstrDeviceType*: LPCSTR
|
||||
|
|
@ -2023,7 +2023,7 @@ type
|
|||
PMCI_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
|
||||
MCI_ANIM_OPEN_PARMSW* = record
|
||||
MCI_ANIM_OPEN_PARMSW* {.final.} = object
|
||||
dwCallback*: DWORD
|
||||
wDeviceID*: MCIDEVICEID
|
||||
lpstrDeviceType*: LPCWSTR
|
||||
|
|
@ -2047,7 +2047,7 @@ else:
|
|||
LPMCI_ANIM_OPEN_PARMS* = LPMCI_ANIM_OPEN_PARMSA
|
||||
type
|
||||
TMCI_ANIM_OPEN_PARMS* = MCI_ANIM_OPEN_PARMS
|
||||
MCI_ANIM_WINDOW_PARMSW* = record
|
||||
MCI_ANIM_WINDOW_PARMSW* {.final.} = object
|
||||
dwCallback*: DWORD
|
||||
hWnd*: HWND
|
||||
nCmdShow*: UINT
|
||||
|
|
@ -2056,14 +2056,14 @@ type
|
|||
PMCI_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
|
||||
MCI_ANIM_STEP_PARMS* = record
|
||||
MCI_ANIM_STEP_PARMS* {.final.} = object
|
||||
dwCallback*: DWORD
|
||||
dwFrames*: DWORD
|
||||
|
||||
PMCI_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
|
||||
MCI_ANIM_WINDOW_PARMSA* = record
|
||||
MCI_ANIM_WINDOW_PARMSA* {.final.} = object
|
||||
dwCallback*: DWORD
|
||||
hWnd*: HWND
|
||||
nCmdShow*: UINT
|
||||
|
|
@ -2072,7 +2072,7 @@ type
|
|||
PMCI_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
|
||||
MCI_ANIM_PLAY_PARMS* = record
|
||||
MCI_ANIM_PLAY_PARMS* {.final.} = object
|
||||
dwCallback*: DWORD
|
||||
dwFrom*: DWORD
|
||||
dwTo*: DWORD
|
||||
|
|
@ -2092,14 +2092,14 @@ else:
|
|||
PMCI_ANIM_WINDOW_PARMS* = PMCI_ANIM_WINDOW_PARMSA
|
||||
LPMCI_ANIM_WINDOW_PARMS* = LPMCI_ANIM_WINDOW_PARMSA
|
||||
type
|
||||
MCI_ANIM_RECT_PARMS* = record
|
||||
MCI_ANIM_RECT_PARMS* {.final.} = object
|
||||
dwCallback*: DWORD
|
||||
rc*: TRECT
|
||||
|
||||
PMCI_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
|
||||
MCI_ANIM_UPDATE_PARMS* = record
|
||||
MCI_ANIM_UPDATE_PARMS* {.final.} = object
|
||||
dwCallback*: DWORD
|
||||
rc*: TRECT
|
||||
hDC*: HDC
|
||||
|
|
@ -2107,7 +2107,7 @@ type
|
|||
PMCI_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
|
||||
MCI_OVLY_OPEN_PARMSA* = record
|
||||
MCI_OVLY_OPEN_PARMSA* {.final.} = object
|
||||
dwCallback*: DWORD
|
||||
wDeviceID*: MCIDEVICEID
|
||||
lpstrDeviceType*: LPCSTR
|
||||
|
|
@ -2119,7 +2119,7 @@ type
|
|||
PMCI_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
|
||||
MCI_OVLY_OPEN_PARMSW* = record
|
||||
MCI_OVLY_OPEN_PARMSW* {.final.} = object
|
||||
dwCallback*: DWORD
|
||||
wDeviceID*: MCIDEVICEID
|
||||
lpstrDeviceType*: LPCWSTR
|
||||
|
|
@ -2144,7 +2144,7 @@ else:
|
|||
LPMCI_OVLY_OPEN_PARMS* = LPMCI_OVLY_OPEN_PARMSA
|
||||
type
|
||||
TMCI_OVLY_OPEN_PARMS* = MCI_OVLY_OPEN_PARMS
|
||||
MCI_OVLY_WINDOW_PARMSA* = record
|
||||
MCI_OVLY_WINDOW_PARMSA* {.final.} = object
|
||||
dwCallback*: DWORD
|
||||
hWnd*: HWND
|
||||
nCmdShow*: UINT
|
||||
|
|
@ -2153,7 +2153,7 @@ type
|
|||
PMCI_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
|
||||
MCI_OVLY_WINDOW_PARMSW* = record
|
||||
MCI_OVLY_WINDOW_PARMSW* {.final.} = object
|
||||
dwCallback*: DWORD
|
||||
hWnd*: HWND
|
||||
nCmdShow*: UINT
|
||||
|
|
@ -2175,14 +2175,14 @@ else:
|
|||
LPMCI_OVLY_WINDOW_PARMS* = LPMCI_OVLY_WINDOW_PARMSA
|
||||
type
|
||||
TMCI_OVLY_WINDOW_PARMS* = MCI_OVLY_WINDOW_PARMSW
|
||||
MCI_OVLY_RECT_PARMS* = record
|
||||
MCI_OVLY_RECT_PARMS* {.final.} = object
|
||||
dwCallback*: DWORD
|
||||
rc*: TRECT
|
||||
|
||||
PMCI_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
|
||||
MCI_OVLY_SAVE_PARMSA* = record
|
||||
MCI_OVLY_SAVE_PARMSA* {.final.} = object
|
||||
dwCallback*: DWORD
|
||||
lpfilename*: LPCSTR
|
||||
rc*: TRECT
|
||||
|
|
@ -2190,7 +2190,7 @@ type
|
|||
PMCI_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
|
||||
MCI_OVLY_SAVE_PARMSW* = record
|
||||
MCI_OVLY_SAVE_PARMSW* {.final.} = object
|
||||
dwCallback*: DWORD
|
||||
lpfilename*: LPCWSTR
|
||||
rc*: TRECT
|
||||
|
|
@ -2211,7 +2211,7 @@ else:
|
|||
LPMCI_OVLY_SAVE_PARMS* = LPMCI_OVLY_SAVE_PARMSA
|
||||
type
|
||||
TMCI_OVLY_SAVE_PARMS* = MCI_OVLY_SAVE_PARMS
|
||||
MCI_OVLY_LOAD_PARMSA* = record
|
||||
MCI_OVLY_LOAD_PARMSA* {.final.} = object
|
||||
dwCallback*: DWORD
|
||||
lpfilename*: LPCSTR
|
||||
rc*: TRECT
|
||||
|
|
@ -2219,7 +2219,7 @@ type
|
|||
PMCI_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
|
||||
MCI_OVLY_LOAD_PARMSW* = record
|
||||
MCI_OVLY_LOAD_PARMSW* {.final.} = object
|
||||
dwCallback*: DWORD
|
||||
lpfilename*: LPCWSTR
|
||||
rc*: TRECT
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
#
|
||||
# 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
|
||||
Windows
|
||||
|
|
@ -20,8 +20,8 @@ const
|
|||
type # Network Control Block
|
||||
PNCB* = ptr TNCB
|
||||
TNCBPostProc* = proc (P: PNCB)
|
||||
TNCB* = record # Structure returned to the NCB command NCBASTAT is ADAPTER_STATUS followed
|
||||
# by an array of NAME_BUFFER structures.
|
||||
TNCB* {.final.} = object # Structure returned to the NCB command NCBASTAT is ADAPTER_STATUS followed
|
||||
# by an array of NAME_BUFFER structures.
|
||||
ncb_command*: Char # command code
|
||||
ncb_retcode*: Char # return code
|
||||
ncb_lsn*: Char # local session number
|
||||
|
|
@ -42,7 +42,7 @@ type # Network Control Block
|
|||
# completes
|
||||
|
||||
PAdapterStatus* = ptr TAdapterStatus
|
||||
TAdapterStatus* = record
|
||||
TAdapterStatus* {.final.} = object
|
||||
adapter_address*: array[0..5, Char]
|
||||
rev_major*: Char
|
||||
reserved0*: Char
|
||||
|
|
@ -72,7 +72,7 @@ type # Network Control Block
|
|||
name_count*: int16
|
||||
|
||||
PNameBuffer* = ptr TNameBuffer
|
||||
TNameBuffer* = record
|
||||
TNameBuffer* {.final.} = object
|
||||
name*: array[0..NCBNAMSZ - 1, Char]
|
||||
name_num*: 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
|
||||
# status for all names.
|
||||
PSessionHeader* = ptr TSessionHeader
|
||||
TSessionHeader* = record
|
||||
TSessionHeader* {.final.} = object
|
||||
sess_name*: Char
|
||||
num_sess*: Char
|
||||
rcv_dg_outstanding*: Char
|
||||
rcv_any_outstanding*: Char
|
||||
|
||||
PSessionBuffer* = ptr TSessionBuffer
|
||||
TSessionBuffer* = record
|
||||
TSessionBuffer* {.final.} = object
|
||||
lsn*: Char
|
||||
state*: Char
|
||||
local_name*: array[0..NCBNAMSZ - 1, Char]
|
||||
|
|
@ -121,20 +121,20 @@ type # Structure returned to the NCB command NCBENUM.
|
|||
# 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.
|
||||
PLanaEnum* = ptr TLanaEnum
|
||||
TLanaEnum* = record # Structure returned to the NCB command NCBFINDNAME is FIND_NAME_HEADER followed
|
||||
# by an array of FIND_NAME_BUFFER structures.
|
||||
TLanaEnum* {.final.} = object # Structure returned to the NCB command NCBFINDNAME is FIND_NAME_HEADER followed
|
||||
# by an array of FIND_NAME_BUFFER structures.
|
||||
len*: Char # Number of valid entries in lana[]
|
||||
lana*: array[0..MAX_LANA, Char]
|
||||
|
||||
PFindNameHeader* = ptr TFindNameHeader
|
||||
TFindNameHeader* = record
|
||||
TFindNameHeader* {.final.} = object
|
||||
node_count*: int16
|
||||
reserved*: Char
|
||||
unique_group*: Char
|
||||
|
||||
PFindNameBuffer* = ptr TFindNameBuffer
|
||||
TFindNameBuffer* = record # Structure provided with NCBACTION. The purpose of NCBACTION is to provide
|
||||
# transport specific extensions to netbios.
|
||||
TFindNameBuffer* {.final.} = object # Structure provided with NCBACTION. The purpose of NCBACTION is to provide
|
||||
# transport specific extensions to netbios.
|
||||
len*: Char
|
||||
access_control*: Char
|
||||
frame_control*: Char
|
||||
|
|
@ -143,7 +143,7 @@ type # Structure returned to the NCB command NCBENUM.
|
|||
routing_info*: array[0..17, Char]
|
||||
|
||||
PActionHeader* = ptr TActionHeader
|
||||
TActionHeader* = record
|
||||
TActionHeader* {.final.} = object
|
||||
transport_id*: int32
|
||||
action_code*: int16
|
||||
reserved*: int16
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ type
|
|||
DWORD_PTR* = ptr DWORD
|
||||
pHICON* = ptr HICON
|
||||
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
|
||||
lpReserved*: LPTSTR
|
||||
lpDesktop*: LPTSTR
|
||||
|
|
@ -122,7 +122,7 @@ proc ExtractIcon*(hInst: HINST, lpszExeFileName: LPCWSTR, nIconIndex: UINT): HIC
|
|||
stdcall, dynlib: "shell32.dll", importc: "ExtractIconW".}
|
||||
# if(WINVER >= 0x0400)
|
||||
type # init with sizeof(DRAGINFO)
|
||||
DRAGINFOA* = record
|
||||
DRAGINFOA* {.final.} = object
|
||||
uSize*: UINT
|
||||
pt*: POINT
|
||||
fNC*: BOOL
|
||||
|
|
@ -131,7 +131,7 @@ type # init with sizeof(DRAGINFO)
|
|||
|
||||
TDRAGINFOA* = DRAGINFOA
|
||||
LPDRAGINFOA* = ptr DRAGINFOA # init with sizeof(DRAGINFO)
|
||||
DRAGINFOW* = record
|
||||
DRAGINFOW* {.final.} = object
|
||||
uSize*: UINT
|
||||
pt*: POINT
|
||||
fNC*: BOOL
|
||||
|
|
@ -178,7 +178,7 @@ const
|
|||
ABE_BOTTOM* = 3
|
||||
|
||||
type
|
||||
AppBarData* = record
|
||||
AppBarData* {.final.} = object
|
||||
cbSize*: DWORD
|
||||
hWnd*: HWND
|
||||
uCallbackMessage*: UINT
|
||||
|
|
@ -286,7 +286,7 @@ type
|
|||
# only used if FOF_SIMPLEPROGRESS
|
||||
|
||||
type
|
||||
SHFILEOPSTRUCTA* = record
|
||||
SHFILEOPSTRUCTA* {.final.} = object
|
||||
hwnd*: HWND
|
||||
wFunc*: UINT
|
||||
pFrom*: LPCSTR
|
||||
|
|
@ -298,7 +298,7 @@ type
|
|||
|
||||
TSHFILEOPSTRUCTA* = SHFILEOPSTRUCTA
|
||||
LPSHFILEOPSTRUCTA* = ptr SHFILEOPSTRUCTA
|
||||
SHFILEOPSTRUCTW* = record
|
||||
SHFILEOPSTRUCTW* {.final.} = object
|
||||
hwnd*: HWND
|
||||
wFunc*: UINT
|
||||
pFrom*: LPCWSTR
|
||||
|
|
@ -332,7 +332,7 @@ proc SHFileOperation*(lpFileOp: LPSHFILEOPSTRUCTW): int32{.stdcall,
|
|||
proc SHFreeNameMappings*(hNameMappings: THandle){.stdcall,
|
||||
dynlib: "shell32.dll", importc: "SHFreeNameMappings".}
|
||||
type
|
||||
SHNAMEMAPPINGA* = record
|
||||
SHNAMEMAPPINGA* {.final.} = object
|
||||
pszOldPath*: LPSTR
|
||||
pszNewPath*: LPSTR
|
||||
cchOldPath*: int32
|
||||
|
|
@ -340,7 +340,7 @@ type
|
|||
|
||||
TSHNAMEMAPPINGA* = SHNAMEMAPPINGA
|
||||
LPSHNAMEMAPPINGA* = ptr SHNAMEMAPPINGA
|
||||
SHNAMEMAPPINGW* = record
|
||||
SHNAMEMAPPINGW* {.final.} = object
|
||||
pszOldPath*: LPWSTR
|
||||
pszNewPath*: LPWSTR
|
||||
cchOldPath*: int32
|
||||
|
|
@ -404,7 +404,7 @@ const
|
|||
# (_WIN32_IE >= 0x560)
|
||||
|
||||
type
|
||||
SHELLEXECUTEINFOA* = record
|
||||
SHELLEXECUTEINFOA* {.final.} = object
|
||||
cbSize*: DWORD
|
||||
fMask*: ULONG
|
||||
hwnd*: HWND
|
||||
|
|
@ -423,7 +423,7 @@ type
|
|||
|
||||
TSHELLEXECUTEINFOA* = SHELLEXECUTEINFOA
|
||||
LPSHELLEXECUTEINFOA* = ptr SHELLEXECUTEINFOA
|
||||
SHELLEXECUTEINFOW* = record
|
||||
SHELLEXECUTEINFOW* {.final.} = object
|
||||
cbSize*: DWORD
|
||||
fMask*: ULONG
|
||||
hwnd*: HWND
|
||||
|
|
@ -474,7 +474,7 @@ proc WinExecError*(HWND: hwnd, error: int32, lpstrFileName: LPCWSTR,
|
|||
lpstrTitle: LPCWSTR){.stdcall, dynlib: "shell32.dll",
|
||||
importc: "WinExecErrorW".}
|
||||
type
|
||||
SHCREATEPROCESSINFOW* = record
|
||||
SHCREATEPROCESSINFOW* {.final.} = object
|
||||
cbSize*: DWORD
|
||||
fMask*: ULONG
|
||||
hwnd*: HWND
|
||||
|
|
@ -502,7 +502,7 @@ proc SHCreateProcessAsUserW*(pscpi: PSHCREATEPROCESSINFOW): Bool{.stdcall,
|
|||
#
|
||||
# struct for query recycle bin info
|
||||
type
|
||||
SHQUERYRBINFO* = record
|
||||
SHQUERYRBINFO* {.final.} = object
|
||||
cbSize*: DWORD
|
||||
i64Size*: int64
|
||||
i64NumItems*: int64
|
||||
|
|
@ -538,7 +538,7 @@ proc SHEmptyRecycleBin*(hwnd: HWND, pszRootPath: LPCWSTR, dwFlags: DWORD): HRESU
|
|||
# Tray notification definitions
|
||||
#
|
||||
type
|
||||
NOTIFYICONDATAA* = record
|
||||
NOTIFYICONDATAA* {.final.} = object
|
||||
cbSize*: DWORD
|
||||
hWnd*: HWND
|
||||
uID*: UINT
|
||||
|
|
@ -556,7 +556,7 @@ type
|
|||
|
||||
TNOTIFYICONDATAA* = NOTIFYICONDATAA
|
||||
PNOTIFYICONDATAA* = ptr NOTIFYICONDATAA
|
||||
NOTIFYICONDATAW* = record
|
||||
NOTIFYICONDATAW* {.final.} = object
|
||||
cbSize*: DWORD
|
||||
hWnd*: HWND
|
||||
uID*: UINT
|
||||
|
|
@ -645,7 +645,7 @@ proc Shell_NotifyIcon*(dwMessage: Dword, lpData: PNOTIFYICONDATAW): Bool{.
|
|||
# out: display name (or path)
|
||||
# out: type name
|
||||
type
|
||||
SHFILEINFOA* = record
|
||||
SHFILEINFOA* {.final.} = object
|
||||
hIcon*: HICON # out: icon
|
||||
iIcon*: int32 # out: icon index
|
||||
dwAttributes*: DWORD # out: SFGAO_ flags
|
||||
|
|
@ -654,7 +654,7 @@ type
|
|||
|
||||
TSHFILEINFOA* = SHFILEINFOA
|
||||
pSHFILEINFOA* = ptr SHFILEINFOA
|
||||
SHFILEINFOW* = record
|
||||
SHFILEINFOW* {.final.} = object
|
||||
hIcon*: HICON # out: icon
|
||||
iIcon*: int32 # out: icon index
|
||||
dwAttributes*: DWORD # out: SFGAO_ flags
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
412
nim/ast.pas
412
nim/ast.pas
|
|
@ -64,6 +64,135 @@ for key, val in enums.iteritems():
|
|||
cog.out(a)
|
||||
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
|
||||
TSymKind = (
|
||||
skUnknownSym, skConditional, skDynLib, skParam,
|
||||
|
|
@ -79,126 +208,6 @@ const
|
|||
'skVar', 'skProc', 'skIterator', 'skConverter',
|
||||
'skMacro', 'skTemplate', 'skField', 'skEnumField',
|
||||
'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]]]}
|
||||
|
||||
type
|
||||
|
|
@ -228,20 +237,28 @@ type
|
|||
mEqProc, mEqUntracedRef, mLePtr, mLtPtr, mEqCString, mXor,
|
||||
mUnaryMinusI, mUnaryMinusI64, mAbsI, mAbsI64, mNot, mUnaryPlusI,
|
||||
mBitnotI, mUnaryPlusI64, mBitnotI64, mUnaryPlusF64, mUnaryMinusF64, mAbsF64,
|
||||
mZe, mZe64, mToU8, mToU16, mToU32, mToFloat,
|
||||
mToBiggestFloat, mToInt, mToBiggestInt, mAnd, mOr, mEqStr,
|
||||
mLeStr, mLtStr, mEqSet, mLeSet, mLtSet, mMulSet,
|
||||
mPlusSet, mMinusSet, mSymDiffSet, mConStrStr, mConArrArr, mConArrT,
|
||||
mConTArr, mConTT, mSlice, mAppendStrCh, mAppendStrStr, mAppendSeqElem,
|
||||
mAppendSeqSeq, mInRange, mInSet, mIs, mAsgn, mRepr,
|
||||
mExit, mSetLengthStr, mSetLengthSeq, mAssert, mSwap, mArray,
|
||||
mOpenArray, mRange, mTuple, mSet, mSeq, mCompileDate,
|
||||
mCompileTime, mNimrodVersion, mNimrodMajor, mNimrodMinor, mNimrodPatch, mCpuEndian
|
||||
mZe8ToI, mZe8ToI64, mZe16ToI, mZe16ToI64, mZe32ToI64, mZeIToI64,
|
||||
mToU8, mToU16, mToU32, mToFloat, mToBiggestFloat, mToInt,
|
||||
mToBiggestInt, mCharToStr, mBoolToStr, mIntToStr, mInt64ToStr, mFloatToStr,
|
||||
mCStrToStr, mStrToStr, mAnd, mOr, mEqStr, mLeStr,
|
||||
mLtStr, mEqSet, mLeSet, mLtSet, mMulSet, mPlusSet,
|
||||
mMinusSet, mSymDiffSet, mConStrStr, mConArrArr, mConArrT, mConTArr,
|
||||
mConTT, mSlice, mAppendStrCh, mAppendStrStr, mAppendSeqElem, mAppendSeqSeq,
|
||||
mInRange, mInSet, mIs, mAsgn, mRepr, mExit,
|
||||
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]]]
|
||||
);
|
||||
|
||||
type
|
||||
PNode = ^TNode;
|
||||
PNodePtr = ^{@ptr}PNode;
|
||||
TNodeSeq = array of PNode;
|
||||
|
||||
PType = ^TType;
|
||||
|
|
@ -254,22 +271,22 @@ type
|
|||
comment: string;
|
||||
sons: TNodeSeq; // else!
|
||||
info: TLineInfo;
|
||||
base: TNumericalBase; // only valid for int or float literals
|
||||
flags: TNodeFlags;
|
||||
case Kind: TNodeKind of
|
||||
nkCharLit, nkRCharLit,
|
||||
nkIntLit, nkInt8Lit, nkInt16Lit, nkInt32Lit, nkInt64Lit:
|
||||
nkCharLit, nkIntLit, nkInt8Lit, nkInt16Lit, nkInt32Lit, nkInt64Lit:
|
||||
(intVal: biggestInt);
|
||||
nkFloatLit, nkFloat32Lit, nkFloat64Lit:
|
||||
(floatVal: biggestFloat);
|
||||
nkSym: (sym: PSym);
|
||||
nkIdent: (ident: PIdent);
|
||||
nkMetaNode: (nodePtr: PNodePtr);
|
||||
end;
|
||||
{@emit
|
||||
record // keep this below 32 bytes; otherwise the AST grows too much
|
||||
typ: PType;
|
||||
comment: string;
|
||||
info: TLineInfo;
|
||||
base: TNumericalBase; // only valid for int or float literals
|
||||
flags: TNodeFlags;
|
||||
case Kind: TNodeKind of
|
||||
nkCharLit..nkInt64Lit:
|
||||
(intVal: biggestInt);
|
||||
|
|
@ -279,6 +296,7 @@ type
|
|||
(strVal: string);
|
||||
nkSym: (sym: PSym);
|
||||
nkIdent: (ident: PIdent);
|
||||
nkMetaNode: (nodePtr: PNodePtr);
|
||||
else (sons: TNodeSeq);
|
||||
end; }
|
||||
|
||||
|
|
@ -307,27 +325,27 @@ type
|
|||
);
|
||||
|
||||
TLocFlag = (
|
||||
// lfIndirect, // location needs to be derefered
|
||||
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:
|
||||
lfIndirect, // backend introduced a pointer
|
||||
lfNoDeepCopy, // no need for a deep copy
|
||||
lfNoDecl, // do not declare it in C
|
||||
lfDynamicLib, // link symbol to dynamic library
|
||||
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;
|
||||
TLoc = record
|
||||
k: TLocKind; // kind of location
|
||||
t: PType; // type of location
|
||||
r: PRope; // rope value of location (C code generator)
|
||||
a: int; // location's "address", i.e. slot for temporaries
|
||||
s: TStorageLoc;
|
||||
flags: TLocFlags; // location's flags
|
||||
indirect: int; // count the number of dereferences needed to access the
|
||||
// location
|
||||
t: PType; // type of location
|
||||
r: PRope; // rope value of location (code generators)
|
||||
a: int; // location's "address", i.e. slot for temporaries
|
||||
end;
|
||||
|
||||
// ---------------- end of backend information ------------------------------
|
||||
|
|
@ -447,7 +465,7 @@ type
|
|||
PLib = ^TLib;
|
||||
|
||||
const
|
||||
OverloadableSyms = {@set}[skProc, skIterator, skEnumField];
|
||||
OverloadableSyms = {@set}[skProc, skIterator, skConverter];
|
||||
|
||||
const // "MagicToStr" array:
|
||||
MagicToStr: array [TMagic] of string = (
|
||||
|
|
@ -474,15 +492,22 @@ const // "MagicToStr" array:
|
|||
'EqProc', 'EqUntracedRef', 'LePtr', 'LtPtr', 'EqCString', 'Xor',
|
||||
'UnaryMinusI', 'UnaryMinusI64', 'AbsI', 'AbsI64', 'Not', 'UnaryPlusI',
|
||||
'BitnotI', 'UnaryPlusI64', 'BitnotI64', 'UnaryPlusF64', 'UnaryMinusF64', 'AbsF64',
|
||||
'Ze', 'Ze64', 'ToU8', 'ToU16', 'ToU32', 'ToFloat',
|
||||
'ToBiggestFloat', 'ToInt', 'ToBiggestInt', 'And', 'Or', 'EqStr',
|
||||
'LeStr', 'LtStr', 'EqSet', 'LeSet', 'LtSet', 'MulSet',
|
||||
'PlusSet', 'MinusSet', 'SymDiffSet', 'ConStrStr', 'ConArrArr', 'ConArrT',
|
||||
'ConTArr', 'ConTT', 'Slice', 'AppendStrCh', 'AppendStrStr', 'AppendSeqElem',
|
||||
'AppendSeqSeq', 'InRange', 'InSet', 'Is', 'Asgn', 'Repr',
|
||||
'Exit', 'SetLengthStr', 'SetLengthSeq', 'Assert', 'Swap', 'Array',
|
||||
'OpenArray', 'Range', 'Tuple', 'Set', 'Seq', 'CompileDate',
|
||||
'CompileTime', 'NimrodVersion', 'NimrodMajor', 'NimrodMinor', 'NimrodPatch', 'CpuEndian'
|
||||
'Ze8ToI', 'Ze8ToI64', 'Ze16ToI', 'Ze16ToI64', 'Ze32ToI64', 'ZeIToI64',
|
||||
'ToU8', 'ToU16', 'ToU32', 'ToFloat', 'ToBiggestFloat', 'ToInt',
|
||||
'ToBiggestInt', 'CharToStr', 'BoolToStr', 'IntToStr', 'Int64ToStr', 'FloatToStr',
|
||||
'CStrToStr', 'StrToStr', 'And', 'Or', 'EqStr', 'LeStr',
|
||||
'LtStr', 'EqSet', 'LeSet', 'LtSet', 'MulSet', 'PlusSet',
|
||||
'MinusSet', 'SymDiffSet', 'ConStrStr', 'ConArrArr', 'ConArrT', 'ConTArr',
|
||||
'ConTT', 'Slice', 'AppendStrCh', 'AppendStrStr', 'AppendSeqElem', 'AppendSeqSeq',
|
||||
'InRange', 'InSet', 'Is', 'Asgn', 'Repr', 'Exit',
|
||||
'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]]]
|
||||
);
|
||||
|
||||
|
|
@ -490,7 +515,7 @@ const
|
|||
GenericTypes: TTypeKinds = {@set}[tyGeneric, tyGenericParam];
|
||||
|
||||
StructuralEquivTypes: TTypeKinds = {@set}[
|
||||
tyEmptySet, tyArrayConstr, tyNil, tyRecordConstr, tyTuple,
|
||||
tyEmptySet, tyArrayConstr, tyNil, tyTuple,
|
||||
tyArray,
|
||||
tySet,
|
||||
tyRange,
|
||||
|
|
@ -503,16 +528,16 @@ const
|
|||
ConcreteTypes: TTypeKinds = {@set}[
|
||||
// types of the expr that may occur in::
|
||||
// var x = expr
|
||||
tyBool, tyChar, tyEnum, tyArray, tyRecord, tyObject, tySet, tyTuple,
|
||||
tyBool, tyChar, tyEnum, tyArray, tyObject, tySet, tyTuple,
|
||||
tyRange, tyPtr, tyRef, tyVar, tySequence, tyProc,
|
||||
tyPointer, tyOpenArray,
|
||||
tyString, tyCString,
|
||||
tyInt..tyInt64,
|
||||
tyFloat..tyFloat128
|
||||
];
|
||||
ConstantDataTypes: TTypeKinds = {@set}[tyArray, tyRecord, tySet, tyTuple];
|
||||
ExportableSymKinds = {@set}[skVar, skConst, skProc, skType, skEnumField,
|
||||
skIterator, skMacro, skTemplate];
|
||||
ConstantDataTypes: TTypeKinds = {@set}[tyArray, tySet, tyTuple];
|
||||
ExportableSymKinds = {@set}[skVar, skConst, skProc, skType,
|
||||
skIterator, skMacro, skTemplate, skConverter];
|
||||
namePos = 0;
|
||||
genericParamsPos = 1;
|
||||
paramsPos = 2;
|
||||
|
|
@ -534,7 +559,7 @@ function newIntTypeNode(kind: TNodeKind; const intVal: BiggestInt;
|
|||
typ: PType): PNode;
|
||||
function newFloatNode(kind: TNodeKind; const floatVal: BiggestFloat): 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 newNodeI(kind: TNodeKind; const info: TLineInfo): PNode;
|
||||
function newNodeIT(kind: TNodeKind; const info: TLineInfo; typ: PType): PNode;
|
||||
|
|
@ -548,7 +573,7 @@ procedure initNodeTable(out x: TNodeTable);
|
|||
|
||||
// copy procs:
|
||||
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 copyStrTable(out dest: TStrTable; const src: TStrTable);
|
||||
|
|
@ -620,7 +645,7 @@ begin
|
|||
if b.kind in [nkStrLit..nkTripleStrLit] then
|
||||
result := a.strVal <= b.strVal;
|
||||
end
|
||||
else assert(false);
|
||||
else InternalError(a.info, 'leValue');
|
||||
end
|
||||
end;
|
||||
|
||||
|
|
@ -638,7 +663,7 @@ begin
|
|||
if b.kind in [nkStrLit..nkTripleStrLit] then
|
||||
result := a.strVal = b.strVal;
|
||||
end
|
||||
else assert(false);
|
||||
else InternalError(a.info, 'SameValue');
|
||||
end
|
||||
end;
|
||||
|
||||
|
|
@ -652,7 +677,7 @@ begin
|
|||
nkStrLit..nkTripleStrLit:
|
||||
result := a.strVal;
|
||||
else begin
|
||||
assert(false);
|
||||
InternalError(a.info, 'valueToString');
|
||||
result := ''
|
||||
end
|
||||
end
|
||||
|
|
@ -663,6 +688,9 @@ var
|
|||
i: int;
|
||||
begin
|
||||
dest.counter := src.counter;
|
||||
{@emit
|
||||
if isNil(src.data) then exit;
|
||||
}
|
||||
setLength(dest.data, length(src.data));
|
||||
for i := 0 to high(src.data) do
|
||||
dest.data[i] := src.data[i];
|
||||
|
|
@ -673,6 +701,9 @@ var
|
|||
i: int;
|
||||
begin
|
||||
dest.counter := src.counter;
|
||||
{@emit
|
||||
if isNil(src.data) then exit;
|
||||
}
|
||||
setLength(dest.data, length(src.data));
|
||||
for i := 0 to high(src.data) do
|
||||
dest.data[i] := src.data[i];
|
||||
|
|
@ -683,6 +714,9 @@ var
|
|||
i: int;
|
||||
begin
|
||||
dest.counter := src.counter;
|
||||
{@emit
|
||||
if isNil(src.data) then exit;
|
||||
}
|
||||
setLength(dest.data, length(src.data));
|
||||
for i := 0 to high(src.data) do
|
||||
dest.data[i] := src.data[i];
|
||||
|
|
@ -700,7 +734,7 @@ begin
|
|||
FillChar(result^, sizeof(result^), 0);
|
||||
{@emit}
|
||||
result.kind := kind;
|
||||
result.info := UnknownLineInfo;
|
||||
result.info := UnknownLineInfo();
|
||||
end;
|
||||
|
||||
function newIntNode(kind: TNodeKind; const intVal: BiggestInt): PNode;
|
||||
|
|
@ -728,10 +762,11 @@ begin
|
|||
result.strVal := strVal
|
||||
end;
|
||||
|
||||
function newIdentNode(ident: PIdent): PNode;
|
||||
function newIdentNode(ident: PIdent; const info: TLineInfo): PNode;
|
||||
begin
|
||||
result := newNode(nkIdent);
|
||||
result.ident := ident
|
||||
result.ident := ident;
|
||||
result.info := info;
|
||||
end;
|
||||
|
||||
function newSymNode(sym: PSym): PNode;
|
||||
|
|
@ -778,6 +813,7 @@ begin
|
|||
dest.n := src.n;
|
||||
dest.size := src.size;
|
||||
dest.align := src.align;
|
||||
dest.containerID := src.containerID;
|
||||
newSons(dest, sonsLen(src));
|
||||
for i := 0 to sonsLen(src)-1 do
|
||||
dest.sons[i] := src.sons[i];
|
||||
|
|
@ -793,14 +829,13 @@ begin
|
|||
// backend-info should not be copied
|
||||
end;
|
||||
|
||||
function copySym(s: PSym; owner: PSym): PSym;
|
||||
function copySym(s: PSym; keepId: bool = false): PSym;
|
||||
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.info := s.info;
|
||||
result.typ := s.typ;
|
||||
if owner = s.owner then result.id := s.id
|
||||
else result.id := getID();
|
||||
if keepId then result.id := s.id else result.id := getID();
|
||||
result.flags := s.flags;
|
||||
result.magic := s.magic;
|
||||
copyStrTable(result.tab, s.tab);
|
||||
|
|
@ -820,7 +855,7 @@ begin
|
|||
result.Name := Name;
|
||||
result.Kind := symKind;
|
||||
result.flags := {@set}[];
|
||||
result.info := UnknownLineInfo;
|
||||
result.info := UnknownLineInfo();
|
||||
result.options := gOptions;
|
||||
result.owner := owner;
|
||||
result.offset := -1;
|
||||
|
|
@ -972,7 +1007,7 @@ begin
|
|||
result := newNode(src.kind);
|
||||
result.info := src.info;
|
||||
result.typ := src.typ;
|
||||
result.base := src.base;
|
||||
result.flags := src.flags;
|
||||
case src.Kind of
|
||||
nkCharLit..nkInt64Lit:
|
||||
result.intVal := src.intVal;
|
||||
|
|
@ -984,6 +1019,8 @@ begin
|
|||
result.ident := src.ident;
|
||||
nkStrLit..nkTripleStrLit:
|
||||
result.strVal := src.strVal;
|
||||
nkMetaNode:
|
||||
result.nodePtr := src.nodePtr;
|
||||
else begin end;
|
||||
end;
|
||||
end;
|
||||
|
|
@ -994,11 +1031,30 @@ var
|
|||
i: int;
|
||||
begin
|
||||
if src = nil then begin result := nil; exit end;
|
||||
result := copyNode(src);
|
||||
result.sons := nil; // BUGFIX
|
||||
newSons(result, sonsLen(src));
|
||||
for i := 0 to sonsLen(src)-1 do
|
||||
result.sons[i] := copyTree(src.sons[i]);
|
||||
result := newNode(src.kind);
|
||||
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));
|
||||
for i := 0 to sonsLen(src)-1 do
|
||||
result.sons[i] := copyTree(src.sons[i]);
|
||||
end;
|
||||
end
|
||||
end;
|
||||
|
||||
function lastSon(n: PNode): PNode;
|
||||
|
|
|
|||
146
nim/astalgo.pas
146
nim/astalgo.pas
|
|
@ -136,6 +136,10 @@ procedure debug(n: PNode); overload;
|
|||
function IdTableGet(const t: TIdTable; key: PIdObj): 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;
|
||||
procedure IdNodeTablePut(var t: TIdNodeTable; key: PIdObj; val: PNode);
|
||||
|
||||
|
|
@ -180,8 +184,6 @@ function nextTry(h, maxHash: THash): THash;
|
|||
implementation
|
||||
|
||||
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
|
||||
i: int;
|
||||
begin
|
||||
|
|
@ -194,7 +196,7 @@ begin
|
|||
end
|
||||
end;
|
||||
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);
|
||||
if result <> nil then exit;
|
||||
for i := 1 to sonsLen(n)-1 do begin
|
||||
|
|
@ -203,7 +205,7 @@ begin
|
|||
result := lookupInRecord(lastSon(n.sons[i]), field);
|
||||
if result <> nil then exit;
|
||||
end;
|
||||
else internalError('lookupInRecord(record case branch)');
|
||||
else internalError(n.info, 'lookupInRecord(record case branch)');
|
||||
end
|
||||
end
|
||||
end;
|
||||
|
|
@ -226,7 +228,8 @@ var
|
|||
i: int;
|
||||
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;
|
||||
if result.name.id = ident.id then exit
|
||||
end;
|
||||
|
|
@ -342,7 +345,7 @@ end;
|
|||
|
||||
function lineInfoToStr(const info: TLineInfo): PRope;
|
||||
begin
|
||||
result := ropeFormat('[$1, $2, $3]', [makeYamlString(toFilename(info)),
|
||||
result := ropef('[$1, $2, $3]', [makeYamlString(toFilename(info)),
|
||||
toRope(toLinenumber(info)), toRope(toColumn(info))]);
|
||||
end;
|
||||
|
||||
|
|
@ -367,11 +370,11 @@ begin
|
|||
for i := 0 to high(n.data) do
|
||||
if n.data[i] <> nil then begin
|
||||
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)]);
|
||||
inc(mycount)
|
||||
end;
|
||||
if mycount > 0 then appRopeFormat(result, '$n$1', [spaces(indent)]);
|
||||
if mycount > 0 then appf(result, '$n$1', [spaces(indent)]);
|
||||
app(result, ']'+'');
|
||||
assert(mycount = n.counter);
|
||||
end;
|
||||
|
|
@ -387,10 +390,10 @@ begin
|
|||
i := 0;
|
||||
while i <= high(c) do begin
|
||||
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)
|
||||
end;
|
||||
appRopeFormat(result, '$n$1}', [spaces(indent)]);
|
||||
appf(result, '$n$1}', [spaces(indent)]);
|
||||
end;
|
||||
|
||||
function symToYamlAux(n: PSym; var marker: TObjectSet;
|
||||
|
|
@ -401,7 +404,7 @@ begin
|
|||
if n = nil then
|
||||
result := toRope('null')
|
||||
else if ObjectSetContainsOrIncl(marker, n) then
|
||||
result := ropeFormat('"$1 @$2"', [
|
||||
result := ropef('"$1 @$2"', [
|
||||
toRope(n.name.s),
|
||||
toRope(strutils.toHex({@cast}TAddress(n), sizeof(n)*2))])
|
||||
else begin
|
||||
|
|
@ -427,7 +430,7 @@ begin
|
|||
if n = nil then
|
||||
result := toRope('null')
|
||||
else if objectSetContainsOrIncl(marker, n) then
|
||||
result := ropeFormat('"$1 @$2"', [
|
||||
result := ropef('"$1 @$2"', [
|
||||
toRope(typeKindToStr[n.kind]),
|
||||
toRope(strutils.toHex({@cast}TAddress(n), sizeof(n)*2))])
|
||||
else begin
|
||||
|
|
@ -453,48 +456,48 @@ begin
|
|||
result := toRope('null')
|
||||
else begin
|
||||
istr := spaces(indent+2);
|
||||
result := ropeFormat('{$n$1"kind": $2',
|
||||
result := ropef('{$n$1"kind": $2',
|
||||
[istr, makeYamlString(nodeKindToStr[n.kind])]);
|
||||
if maxRecDepth <> 0 then begin
|
||||
appRopeFormat(result, ',$n$1"typ": $2',
|
||||
[istr, typeToYamlAux(n.typ, marker, indent+2, maxRecDepth)]);
|
||||
appRopeFormat(result, ',$n$1"info": $2',
|
||||
appf(result, ',$n$1"info": $2',
|
||||
[istr, lineInfoToStr(n.info)]);
|
||||
case n.kind of
|
||||
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:
|
||||
appRopeFormat(result, '$n$1"floatVal": $2',
|
||||
appf(result, '$n$1"floatVal": $2',
|
||||
[istr, toRopeF(n.floatVal)]);
|
||||
nkStrLit..nkTripleStrLit:
|
||||
appRopeFormat(result, '$n$1"strVal": $2',
|
||||
appf(result, '$n$1"strVal": $2',
|
||||
[istr, makeYamlString(n.strVal)]);
|
||||
nkSym:
|
||||
appRopeFormat(result, ',$n$1"sym": $2',
|
||||
appf(result, ',$n$1"sym": $2',
|
||||
[istr, symToYamlAux(n.sym, marker, indent+2, maxRecDepth)]);
|
||||
|
||||
nkIdent: begin
|
||||
if n.ident <> nil then
|
||||
appRopeFormat(result, '$n$1"ident": $2',
|
||||
appf(result, '$n$1"ident": $2',
|
||||
[istr, makeYamlString(n.ident.s)])
|
||||
else
|
||||
appRopeFormat(result, '$n$1"ident": null', [istr])
|
||||
appf(result, '$n$1"ident": null', [istr])
|
||||
end
|
||||
else 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
|
||||
if i > 0 then app(result, ','+'');
|
||||
appRopeFormat(result, '$n$1$2',
|
||||
appf(result, '$n$1$2',
|
||||
[spaces(indent+4),
|
||||
treeToYamlAux(n.sons[i], marker, indent + 4, maxRecDepth-1)]);
|
||||
end;
|
||||
appRopeFormat(result, '$n$1]', [istr]);
|
||||
appf(result, '$n$1]', [istr]);
|
||||
end
|
||||
end
|
||||
end
|
||||
end;
|
||||
appf(result, ',$n$1"typ": $2',
|
||||
[istr, typeToYamlAux(n.typ, marker, indent+2, maxRecDepth)]);
|
||||
end;
|
||||
appRopeFormat(result, '$n$1}', [spaces(indent)]);
|
||||
appf(result, '$n$1}', [spaces(indent)]);
|
||||
end
|
||||
end;
|
||||
|
||||
|
|
@ -523,19 +526,88 @@ begin
|
|||
end;
|
||||
|
||||
// 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;
|
||||
begin
|
||||
writeln(output, ropeToStr(symToYaml(n, 0, 3)));
|
||||
writeln(output, ropeToStr(ropef('$1_$2', [toRope(n.name.s), toRope(n.id)])));
|
||||
end;
|
||||
|
||||
procedure debug(n: PType); overload;
|
||||
begin
|
||||
writeln(output, ropeToStr(typeToYaml(n, 0, 3)));
|
||||
writeln(output, ropeToStr(debugType(n)));
|
||||
end;
|
||||
|
||||
procedure debug(n: PNode); overload;
|
||||
begin
|
||||
writeln(output, ropeToStr(treeToYaml(n, 0, -1)));
|
||||
writeln(output, ropeToStr(debugTree(n, 0, 100)));
|
||||
end;
|
||||
|
||||
// -------------------- node sets --------------------------------------------
|
||||
|
|
@ -748,7 +820,8 @@ var
|
|||
begin
|
||||
h := n.name.h and high(data);
|
||||
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))
|
||||
end;
|
||||
assert(data[h] = nil);
|
||||
|
|
@ -963,6 +1036,15 @@ begin
|
|||
result := -1
|
||||
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;
|
||||
var
|
||||
index: int;
|
||||
|
|
@ -999,6 +1081,7 @@ begin
|
|||
end
|
||||
else begin
|
||||
if mustRehash(length(t.data), t.counter) then begin
|
||||
{@emit n := [];}
|
||||
setLength(n, length(t.data) * growthFactor);
|
||||
{@ignore}
|
||||
fillChar(n[0], length(n)*sizeof(n[0]), 0);
|
||||
|
|
@ -1083,6 +1166,7 @@ begin
|
|||
end
|
||||
else begin
|
||||
if mustRehash(length(t.data), t.counter) then begin
|
||||
{@emit n := [];}
|
||||
setLength(n, length(t.data) * growthFactor);
|
||||
{@ignore}
|
||||
fillChar(n[0], length(n)*sizeof(n[0]), 0);
|
||||
|
|
|
|||
|
|
@ -49,17 +49,20 @@ end;
|
|||
|
||||
procedure BitSetIncl(var x: TBitSet; const elem: BiggestInt);
|
||||
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;
|
||||
|
||||
procedure BitSetExcl(var x: TBitSet; const elem: BiggestInt);
|
||||
begin
|
||||
x[int(elem div ElemSize)] := x[int(elem div ElemSize)] and
|
||||
not (1 shl (elem mod ElemSize))
|
||||
x[int(elem div ElemSize)] := toU8(x[int(elem div ElemSize)] and
|
||||
not int(1 shl (elem mod ElemSize)))
|
||||
end;
|
||||
|
||||
procedure BitSetInit(out b: TBitSet; len: int);
|
||||
begin
|
||||
{@emit b := [];}
|
||||
setLength(b, len);
|
||||
{@ignore}
|
||||
fillChar(b[0], length(b)*sizeof(b[0]), 0);
|
||||
|
|
@ -70,28 +73,28 @@ procedure BitSetUnion(var x: TBitSet; const y: TBitSet);
|
|||
var
|
||||
i: int;
|
||||
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;
|
||||
|
||||
procedure BitSetDiff(var x: TBitSet; const y: TBitSet);
|
||||
var
|
||||
i: int;
|
||||
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;
|
||||
|
||||
procedure BitSetSymDiff(var x: TBitSet; const y: TBitSet);
|
||||
var
|
||||
i: int;
|
||||
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;
|
||||
|
||||
procedure BitSetIntersect(var x: TBitSet; const y: TBitSet);
|
||||
var
|
||||
i: int;
|
||||
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;
|
||||
|
||||
function BitSetEquals(const x, y: TBitSet): Boolean;
|
||||
|
|
|
|||
1344
nim/ccgexprs.pas
1344
nim/ccgexprs.pas
File diff suppressed because it is too large
Load diff
207
nim/ccgstmts.pas
207
nim/ccgstmts.pas
|
|
@ -18,17 +18,25 @@ begin
|
|||
line := toLinenumber(t.info); // BUGFIX
|
||||
if line < 0 then line := 0; // negative numbers are not allowed in #line
|
||||
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)]);
|
||||
if ([optStackTrace, optEndb] * p.Options = [optStackTrace, optEndb]) and
|
||||
((p.prc = nil) or not (sfPure in p.prc.flags)) then begin
|
||||
useMagic('endb'); // new: endb support
|
||||
appRopeFormat(p.s[cpsStmts], 'endb($1);$n', [toRope(line)])
|
||||
useMagic(p.module, 'endb'); // new: endb support
|
||||
appf(p.s[cpsStmts], 'endb($1);$n', [toRope(line)])
|
||||
end
|
||||
else if ([optLineTrace, optStackTrace] * p.Options =
|
||||
[optLineTrace, optStackTrace]) and ((p.prc = nil) or
|
||||
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;
|
||||
|
||||
procedure genReturnStmt(p: BProc; t: PNode);
|
||||
|
|
@ -36,15 +44,16 @@ begin
|
|||
p.beforeRetNeeded := true;
|
||||
genLineDir(p, t);
|
||||
if (t.sons[0] <> nil) then genStmts(p, t.sons[0]);
|
||||
finishTryStmt(p, p.nestedTryStmts);
|
||||
app(p.s[cpsStmts], 'goto BeforeRet;' + tnl)
|
||||
end;
|
||||
|
||||
procedure genObjectInit(p: BProc; sym: PSym);
|
||||
begin
|
||||
if containsObject(sym.typ) then begin
|
||||
useMagic('objectInit');
|
||||
appRopeFormat(p.s[cpsInit], 'objectInit($1, $2);$n',
|
||||
[addrLoc(sym.loc), genTypeInfo(currMod, sym.typ)])
|
||||
useMagic(p.module, 'objectInit');
|
||||
appf(p.s[cpsInit], 'objectInit($1, $2);$n',
|
||||
[addrLoc(sym.loc), genTypeInfo(p.module, sym.typ)])
|
||||
end
|
||||
end;
|
||||
|
||||
|
|
@ -52,11 +61,11 @@ procedure initVariable(p: BProc; v: PSym);
|
|||
begin
|
||||
if containsGarbageCollectedRef(v.typ) or (v.ast = nil) then
|
||||
// Language change: always initialize variables if v.ast == nil!
|
||||
if not (skipAbstract(v.typ).Kind in [tyArray, tyArrayConstr, tySet,
|
||||
tyRecord, tyTuple, tyObject]) then
|
||||
appRopeFormat(p.s[cpsInit], '$1 = 0;$n', [v.loc.r])
|
||||
if not (skipVarGenericRange(v.typ).Kind in [tyArray, tyArrayConstr, tySet,
|
||||
tyTuple, tyObject]) then
|
||||
appf(p.s[cpsStmts], '$1 = 0;$n', [v.loc.r])
|
||||
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])
|
||||
end;
|
||||
|
||||
|
|
@ -73,7 +82,7 @@ begin
|
|||
assert(a.sons[0].kind = nkSym);
|
||||
v := a.sons[0].sym;
|
||||
if sfGlobal in v.flags then
|
||||
assignGlobalVar(v)
|
||||
assignGlobalVar(p.module, v)
|
||||
else begin
|
||||
assignLocalVar(p, v);
|
||||
initVariable(p, v) // XXX: this is not required if a.sons[2] != nil,
|
||||
|
|
@ -95,19 +104,20 @@ var
|
|||
begin
|
||||
for i := 0 to sonsLen(t)-1 do begin
|
||||
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;
|
||||
// This can happen for forward consts:
|
||||
if (c.ast <> nil) and (c.typ.kind in ConstantDataTypes) and
|
||||
not (lfNoDecl in c.loc.flags) then begin
|
||||
// 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
|
||||
appRopeFormat(currMod.s[cfsData], 'extern $1$2 $3;$n',
|
||||
[constTok, getTypeDesc(c.typ), c.loc.r])
|
||||
appf(p.module.s[cfsData], 'extern NIM_CONST $1 $2;$n',
|
||||
[getTypeDesc(p.module, c.typ), c.loc.r])
|
||||
else
|
||||
appRopeFormat(currMod.s[cfsData], '$1$2 $3 = $4;$n',
|
||||
[constTok, getTypeDesc(c.typ), c.loc.r, genConstExpr(p, c.ast)])
|
||||
appf(p.module.s[cfsData], 'NIM_CONST $1 $2 = $3;$n',
|
||||
[getTypeDesc(p.module, c.typ), c.loc.r,
|
||||
genConstExpr(p, c.ast)])
|
||||
end
|
||||
end
|
||||
end;
|
||||
|
|
@ -139,11 +149,11 @@ begin
|
|||
nkElifBranch: begin
|
||||
a := initLocExpr(p, it.sons[0]);
|
||||
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);
|
||||
genStmts(p, it.sons[1]);
|
||||
if sonsLen(n) > 1 then
|
||||
appRopeFormat(p.s[cpsStmts], 'goto $1;$n', [Lend]);
|
||||
appf(p.s[cpsStmts], 'goto $1;$n', [Lend]);
|
||||
fixLabel(p, Lelse);
|
||||
end;
|
||||
nkElse: begin
|
||||
|
|
@ -166,17 +176,18 @@ var
|
|||
begin
|
||||
genLineDir(p, t);
|
||||
assert(sonsLen(t) = 2);
|
||||
inc(p.unique);
|
||||
Labl := con('L'+'', toRope(p.unique));
|
||||
inc(p.labels);
|
||||
Labl := con('L'+'', toRope(p.labels));
|
||||
len := length(p.blocks);
|
||||
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);
|
||||
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);
|
||||
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)
|
||||
end;
|
||||
|
||||
|
|
@ -185,7 +196,7 @@ var
|
|||
idx: int;
|
||||
sym: PSym;
|
||||
begin
|
||||
inc(p.unique);
|
||||
inc(p.labels);
|
||||
idx := length(p.blocks);
|
||||
if t.sons[0] <> nil then begin // named block?
|
||||
assert(t.sons[0].kind = nkSym);
|
||||
|
|
@ -194,14 +205,22 @@ begin
|
|||
sym.loc.a := idx
|
||||
end;
|
||||
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)
|
||||
else genStmts(p, t.sons[1]);
|
||||
if p.blocks[idx] > 0 then // label has been used:
|
||||
appRopeFormat(p.s[cpsStmts], 'L$1: ;$n', [toRope(p.blocks[idx])]);
|
||||
if p.blocks[idx].id > 0 then // label has been used:
|
||||
appf(p.s[cpsStmts], 'L$1: ;$n', [toRope(p.blocks[idx].id)]);
|
||||
setLength(p.blocks, idx)
|
||||
end;
|
||||
|
||||
// try:
|
||||
// while:
|
||||
// try:
|
||||
// if ...:
|
||||
// break # we need to finish only one try statement here!
|
||||
// finally:
|
||||
|
||||
procedure genBreakStmt(p: BProc; t: PNode);
|
||||
var
|
||||
idx: int;
|
||||
|
|
@ -215,8 +234,9 @@ begin
|
|||
assert(sym.loc.k = locOther);
|
||||
idx := sym.loc.a
|
||||
end;
|
||||
p.blocks[idx] := abs(p.blocks[idx]); // label is used
|
||||
appRopeFormat(p.s[cpsStmts], 'goto L$1;$n', [toRope(p.blocks[idx])])
|
||||
p.blocks[idx].id := abs(p.blocks[idx].id); // label is used
|
||||
finishTryStmt(p, p.nestedTryStmts - p.blocks[idx].nestedTryStmts);
|
||||
appf(p.s[cpsStmts], 'goto L$1;$n', [toRope(p.blocks[idx].id)])
|
||||
end;
|
||||
|
||||
procedure genAsmStmt(p: BProc; t: PNode);
|
||||
|
|
@ -245,15 +265,15 @@ begin
|
|||
InternalError(t.sons[i].info, 'genAsmStmt()')
|
||||
end
|
||||
end;
|
||||
appRopeFormat(p.s[cpsStmts], CC[ccompiler].asmStmtFrmt, [s]);
|
||||
appf(p.s[cpsStmts], CC[ccompiler].asmStmtFrmt, [s]);
|
||||
end;
|
||||
|
||||
function getRaiseFrmt(): string;
|
||||
function getRaiseFrmt(p: BProc): string;
|
||||
begin
|
||||
if gCmd = cmdCompileToCpp then
|
||||
result := 'throw nimException($1, $2);$n'
|
||||
else begin
|
||||
useMagic('E_Base');
|
||||
useMagic(p.module, 'E_Base');
|
||||
result := 'raiseException((E_Base*)$1, $2);$n'
|
||||
end
|
||||
end;
|
||||
|
|
@ -266,14 +286,13 @@ var
|
|||
begin
|
||||
genLineDir(p, t);
|
||||
if t.sons[0] <> nil then begin
|
||||
if gCmd <> cmdCompileToCpp then
|
||||
useMagic('raiseException');
|
||||
if gCmd <> cmdCompileToCpp then useMagic(p.module, 'raiseException');
|
||||
a := InitLocExpr(p, t.sons[0]);
|
||||
e := rdLoc(a);
|
||||
freeTemp(p, a);
|
||||
typ := t.sons[0].typ;
|
||||
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)])
|
||||
end
|
||||
else begin
|
||||
|
|
@ -281,7 +300,7 @@ begin
|
|||
if gCmd = cmdCompileToCpp then
|
||||
app(p.s[cpsStmts], 'throw;' + tnl)
|
||||
else begin
|
||||
useMagic('reraiseException');
|
||||
useMagic(p.module, 'reraiseException');
|
||||
app(p.s[cpsStmts], 'reraiseException();' + tnl)
|
||||
end
|
||||
end
|
||||
|
|
@ -309,13 +328,13 @@ begin
|
|||
y := initLocExpr(p, b.sons[i].sons[1]);
|
||||
freeTemp(p, x);
|
||||
freeTemp(p, y);
|
||||
appRopeFormat(p.s[cpsStmts], rangeFormat,
|
||||
appf(p.s[cpsStmts], rangeFormat,
|
||||
[rdCharLoc(e), rdCharLoc(x), rdCharLoc(y), labl])
|
||||
end
|
||||
else begin
|
||||
x := initLocExpr(p, b.sons[i]);
|
||||
freeTemp(p, x);
|
||||
appRopeFormat(p.s[cpsStmts], eqFormat,
|
||||
appf(p.s[cpsStmts], eqFormat,
|
||||
[rdCharLoc(e), rdCharLoc(x), labl])
|
||||
end
|
||||
end
|
||||
|
|
@ -328,11 +347,11 @@ var
|
|||
begin
|
||||
Lend := getLabel(p);
|
||||
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
|
||||
len := sonsLen(t.sons[i]);
|
||||
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
|
||||
else // else statement
|
||||
genStmts(p, t.sons[i].sons[0])
|
||||
|
|
@ -349,15 +368,15 @@ var
|
|||
begin
|
||||
a := initLocExpr(p, t.sons[0]);
|
||||
// fist pass: gnerate ifs+goto:
|
||||
labId := p.unique;
|
||||
labId := p.labels;
|
||||
for i := 1 to sonsLen(t) - 1 do begin
|
||||
inc(p.unique);
|
||||
inc(p.labels);
|
||||
if t.sons[i].kind = nkOfBranch then
|
||||
genCaseGenericBranch(p, t.sons[i], a, rangeFormat, eqFormat,
|
||||
con('L'+'', toRope(p.unique)))
|
||||
con('L'+'', toRope(p.labels)))
|
||||
else
|
||||
// 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;
|
||||
// second pass: generate statements
|
||||
genCaseSecondPass(p, t, labId);
|
||||
|
|
@ -435,7 +454,7 @@ begin
|
|||
freeTemp(p, x);
|
||||
assert(b.sons[i].kind in [nkStrLit..nkTripleStrLit]);
|
||||
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])
|
||||
end
|
||||
end;
|
||||
|
|
@ -446,38 +465,39 @@ var
|
|||
a: TLoc;
|
||||
branches: TRopeSeq;
|
||||
begin
|
||||
useMagic('eqStrings');
|
||||
useMagic(p.module, 'eqStrings');
|
||||
// count how many constant strings there are in the case:
|
||||
strings := 0;
|
||||
for i := 1 to sonsLen(t)-1 do
|
||||
if t.sons[i].kind = nkOfBranch then inc(strings, sonsLen(t.sons[i])-1);
|
||||
if strings > stringCaseThreshold then begin
|
||||
useMagic('hashString');
|
||||
useMagic(p.module, 'hashString');
|
||||
bitMask := nmath.nextPowerOfTwo(strings)-1;
|
||||
setLength(branches, bitMask+1);
|
||||
a := initLocExpr(p, t.sons[0]);
|
||||
// fist pass: gnerate ifs+goto:
|
||||
labId := p.unique;
|
||||
labId := p.labels;
|
||||
for i := 1 to sonsLen(t) - 1 do begin
|
||||
inc(p.unique);
|
||||
inc(p.labels);
|
||||
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)
|
||||
else begin end
|
||||
else begin
|
||||
// else statement: nothing to do yet
|
||||
// but we reserved a label, which we use later
|
||||
end
|
||||
end;
|
||||
// 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)]);
|
||||
for j := 0 to high(branches) do
|
||||
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]]);
|
||||
app(p.s[cpsStmts], '}' + tnl);
|
||||
// else statement:
|
||||
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
|
||||
genCaseSecondPass(p, t, labId);
|
||||
freeTemp(p, a);
|
||||
|
|
@ -521,7 +541,7 @@ begin
|
|||
end;
|
||||
if canGenerateSwitch then begin
|
||||
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);
|
||||
for i := 1 to sonsLen(t)-1 do begin
|
||||
if t.sons[i].kind = nkOfBranch then begin
|
||||
|
|
@ -529,19 +549,19 @@ begin
|
|||
for j := 0 to len-2 do begin
|
||||
if t.sons[i].sons[j].kind = nkRange then begin // a range
|
||||
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[1])])
|
||||
else begin
|
||||
v := copyNode(t.sons[i].sons[j].sons[0]);
|
||||
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)
|
||||
end
|
||||
end;
|
||||
end
|
||||
else
|
||||
appRopeFormat(p.s[cpsStmts], 'case $1:$n',
|
||||
appf(p.s[cpsStmts], 'case $1:$n',
|
||||
[genLiteral(p, t.sons[i].sons[j])]);
|
||||
end;
|
||||
genStmts(p, t.sons[i].sons[len-1])
|
||||
|
|
@ -563,7 +583,7 @@ end;
|
|||
procedure genCaseStmt(p: BProc; t: PNode);
|
||||
begin
|
||||
genLineDir(p, t);
|
||||
case skipAbstract(t.sons[0].typ).kind of
|
||||
case skipVarGenericRange(t.sons[0].typ).kind of
|
||||
tyString: genStringCase(p, t);
|
||||
tyFloat..tyFloat128:
|
||||
genCaseGeneric(p, t, 'if ($1 >= $2 && $1 <= $3) goto $4;$n',
|
||||
|
|
@ -622,21 +642,20 @@ begin
|
|||
exc := getTempName();
|
||||
if not hasGeneralExceptSection(t) then begin
|
||||
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])
|
||||
end;
|
||||
if optStackTrace in p.Options then
|
||||
app(p.s[cpsStmts], 'framePtr = (TFrame*)&F;' + tnl);
|
||||
app(p.s[cpsStmts], 'try {' + tnl);
|
||||
inc(p.inTryStmt);
|
||||
inc(p.nestedTryStmts);
|
||||
genStmts(p, t.sons[0]);
|
||||
dec(p.inTryStmt);
|
||||
len := sonsLen(t);
|
||||
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
|
||||
appRopeFormat(p.s[cpsStmts], '$1 = NIM_TRUE;$n', [rethrowFlag]);
|
||||
appRopeFormat(p.s[cpsStmts], 'if ($1.sp.exc) {$n', [exc])
|
||||
appf(p.s[cpsStmts], '$1 = NIM_TRUE;$n', [rethrowFlag]);
|
||||
appf(p.s[cpsStmts], 'if ($1.sp.exc) {$n', [exc])
|
||||
end; // XXX: this is not correct!
|
||||
i := 1;
|
||||
while (i < len) and (t.sons[i].kind = nkExceptBranch) do begin
|
||||
|
|
@ -648,24 +667,25 @@ begin
|
|||
else begin
|
||||
for j := 0 to blen - 2 do begin
|
||||
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)])
|
||||
end;
|
||||
genStmts(p, t.sons[i].sons[blen - 1])
|
||||
end;
|
||||
// code to clear the exception:
|
||||
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);
|
||||
inc(i);
|
||||
end;
|
||||
if t.sons[1].kind = nkExceptBranch then // BUGFIX
|
||||
app(p.s[cpsStmts], '}}' + tnl); // end of catch-switch statement
|
||||
dec(p.nestedTryStmts);
|
||||
app(p.s[cpsStmts], 'excHandler = excHandler->prev;' + tnl);
|
||||
if (i < len) and (t.sons[i].kind = nkFinally) then begin
|
||||
genStmts(p, t.sons[i].sons[0]);
|
||||
if rethrowFlag <> nil then
|
||||
appRopeFormat(p.s[cpsStmts], 'if ($1) { throw; }$n', [rethrowFlag])
|
||||
appf(p.s[cpsStmts], 'if ($1) { throw; }$n', [rethrowFlag])
|
||||
end
|
||||
end;
|
||||
|
||||
|
|
@ -698,21 +718,21 @@ begin
|
|||
genLineDir(p, t);
|
||||
|
||||
safePoint := getTempName();
|
||||
useMagic('TSafePoint');
|
||||
useMagic('E_Base');
|
||||
useMagic('excHandler');
|
||||
appRopeFormat(p.s[cpsLocals], 'volatile TSafePoint $1;$n', [safePoint]);
|
||||
appRopeFormat(p.s[cpsStmts], '$1.prev = excHandler;$n' +
|
||||
'excHandler = &$1;$n' +
|
||||
'$1.status = setjmp($1.context);$n' +
|
||||
'if ($1.status == 0) {$n', [safePoint]);
|
||||
useMagic(p.module, 'TSafePoint');
|
||||
useMagic(p.module, 'E_Base');
|
||||
useMagic(p.module, 'excHandler');
|
||||
appf(p.s[cpsLocals], 'TSafePoint $1;$n', [safePoint]);
|
||||
appf(p.s[cpsStmts], '$1.prev = excHandler;$n' +
|
||||
'excHandler = &$1;$n' +
|
||||
'$1.status = setjmp($1.context);$n',
|
||||
[safePoint]);
|
||||
if optStackTrace in p.Options then
|
||||
app(p.s[cpsStmts], 'framePtr = (TFrame*)&F;' + tnl);
|
||||
appf(p.s[cpsStmts], 'if ($1.status == 0) {$n', [safePoint]);
|
||||
len := sonsLen(t);
|
||||
inc(p.inTryStmt);
|
||||
inc(p.nestedTryStmts);
|
||||
genStmts(p, t.sons[0]);
|
||||
app(p.s[cpsStmts], '} else {' + tnl);
|
||||
dec(p.inTryStmt);
|
||||
i := 1;
|
||||
while (i < len) and (t.sons[i].kind = nkExceptBranch) do begin
|
||||
blen := sonsLen(t.sons[i]);
|
||||
|
|
@ -720,7 +740,7 @@ begin
|
|||
// general except section:
|
||||
if i > 1 then app(p.s[cpsStmts], 'else {' + tnl);
|
||||
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);
|
||||
end
|
||||
else begin
|
||||
|
|
@ -728,24 +748,25 @@ begin
|
|||
for j := 0 to blen - 2 do begin
|
||||
assert(t.sons[i].sons[j].kind = nkType);
|
||||
if orExpr <> nil then app(orExpr, '||');
|
||||
appRopeFormat(orExpr, '($1.exc->Sup.m_type == $2)',
|
||||
[safePoint, genTypeInfo(currMod, t.sons[i].sons[j].typ)])
|
||||
appf(orExpr, '($1.exc->Sup.m_type == $2)',
|
||||
[safePoint, genTypeInfo(p.module, t.sons[i].sons[j].typ)])
|
||||
end;
|
||||
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]);
|
||||
// code to clear the exception:
|
||||
appRopeFormat(p.s[cpsStmts], '$1.status = 0;}$n', [safePoint]);
|
||||
appf(p.s[cpsStmts], '$1.status = 0;}$n', [safePoint]);
|
||||
end;
|
||||
inc(i)
|
||||
end;
|
||||
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
|
||||
genStmts(p, t.sons[i].sons[0]);
|
||||
useMagic('raiseException');
|
||||
appRopeFormat(p.s[cpsStmts], 'if ($1.status != 0) { ' +
|
||||
'raiseException($1.exc, $1.exc->Name); }$n', [safePoint])
|
||||
useMagic(p.module, 'raiseException');
|
||||
appf(p.s[cpsStmts], 'if ($1.status != 0) { ' +
|
||||
'raiseException($1.exc, $1.exc->name); }$n', [safePoint])
|
||||
end
|
||||
end;
|
||||
|
||||
|
|
@ -767,7 +788,7 @@ begin
|
|||
name := 'bp' + toString(breakPointId)
|
||||
end;
|
||||
genLineDir(p, t); // BUGFIX
|
||||
appRopeFormat(gBreakpoints,
|
||||
appf(gBreakpoints,
|
||||
'dbgRegisterBreakpoint($1, (NCSTRING)$2, (NCSTRING)$3);$n',
|
||||
[toRope(toLinenumber(t.info)), makeCString(toFilename(t.info)),
|
||||
makeCString(name)])
|
||||
|
|
@ -852,15 +873,15 @@ begin
|
|||
nkCommentStmt, nkNilLit, nkIteratorDef, nkIncludeStmt, nkImportStmt,
|
||||
nkFromStmt, nkTemplateDef, nkMacroDef: begin end;
|
||||
nkPragma: genPragma(p, t);
|
||||
nkProcDef: begin
|
||||
nkProcDef, nkConverterDef: begin
|
||||
if (t.sons[genericParamsPos] = nil) then begin
|
||||
prc := t.sons[namePos].sym;
|
||||
if (t.sons[codePos] <> nil)
|
||||
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!
|
||||
end;
|
||||
genProc(prc)
|
||||
genProc(p.module, prc)
|
||||
end
|
||||
//else if sfCompilerProc in prc.flags then genProcPrototype(prc);
|
||||
end
|
||||
|
|
|
|||
597
nim/ccgtypes.pas
597
nim/ccgtypes.pas
|
|
@ -9,12 +9,6 @@
|
|||
|
||||
// ------------------------- Name Mangling --------------------------------
|
||||
|
||||
function getUnique(p: BProc): PRope;
|
||||
begin
|
||||
inc(p.unique);
|
||||
result := toRope(p.unique)
|
||||
end;
|
||||
|
||||
function mangle(const name: string): string;
|
||||
var
|
||||
i: int;
|
||||
|
|
@ -23,7 +17,7 @@ begin
|
|||
result := toUpper(name[strStart])+''
|
||||
else
|
||||
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
|
||||
'A'..'Z': addChar(result, chr(ord(name[i]) - ord('A') + ord('a')));
|
||||
'_': begin end;
|
||||
|
|
@ -35,22 +29,68 @@ end;
|
|||
|
||||
function mangleName(s: PSym): PRope;
|
||||
begin
|
||||
if s.owner <> nil then
|
||||
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)]);
|
||||
result := ropef('$1_$2', [toRope(mangle(s.name.s)), toRope(s.id)]);
|
||||
if optGenMapping in gGlobalOptions 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])
|
||||
end;
|
||||
|
||||
// ------------------------------ 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;
|
||||
begin
|
||||
|
|
@ -58,8 +98,6 @@ begin
|
|||
end;
|
||||
|
||||
function isInvalidReturnType(rettype: PType): bool;
|
||||
var
|
||||
t: PType;
|
||||
begin
|
||||
// Arrays and sets cannot be returned by a C procedure, because C is
|
||||
// such a poor programming language.
|
||||
|
|
@ -68,16 +106,9 @@ begin
|
|||
if rettype = nil then
|
||||
result := true
|
||||
else begin
|
||||
t := skipAbstract(rettype);
|
||||
case t.kind of
|
||||
tyArray, tyArrayConstr: result := true;
|
||||
tyObject, tyRecord: result := needsComplexAssignment(t);
|
||||
tySet: begin
|
||||
case int(getSize(t)) of
|
||||
1, 2, 4, 8: result := false;
|
||||
else result := true
|
||||
end
|
||||
end
|
||||
case mapType(rettype) of
|
||||
ctArray: result := true;
|
||||
ctStruct: result := needsComplexAssignment(skipGeneric(rettype));
|
||||
else result := false;
|
||||
end
|
||||
end
|
||||
|
|
@ -96,65 +127,46 @@ begin
|
|||
result := PRope(TableGetType(tab, key))
|
||||
end;
|
||||
|
||||
var
|
||||
gUnique: int;
|
||||
|
||||
function getTempName(): PRope;
|
||||
begin
|
||||
inc(gUnique);
|
||||
result := con('T'+'', toRope(gUnique))
|
||||
end;
|
||||
|
||||
function isCArray(typ: PType): 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 ...
|
||||
function ccgIntroducedPtr(s: PSym): bool;
|
||||
var
|
||||
pt: PType;
|
||||
begin
|
||||
pt := param.typ;
|
||||
if (sfResult in param.flags) and not isInvalidReturnType(pt) then
|
||||
result := false // BUGFIX
|
||||
else if pt.Kind = tyObject then begin
|
||||
// objects are always passed by reference,
|
||||
// otherwise implicit casting doesn't work
|
||||
result := true;
|
||||
pt := s.typ;
|
||||
assert(not (sfResult in s.flags));
|
||||
case pt.Kind of
|
||||
tyObject: begin
|
||||
if (optByRef in s.options) or (getSize(pt) > platform.floatSize) then
|
||||
result := true // requested anyway
|
||||
else if (tfFinal in pt.flags) and (pt.sons[0] = nil) then
|
||||
result := false // no need, because no subtyping possible
|
||||
else
|
||||
result := true; // ordinary objects are always passed by reference,
|
||||
// otherwise casting doesn't work
|
||||
end;
|
||||
tyTuple:
|
||||
result := (getSize(pt) > platform.floatSize) or (optByRef in s.options);
|
||||
else
|
||||
result := false
|
||||
end
|
||||
else if (pt.kind in [tyRecordConstr, tyRecord]) and
|
||||
((getSize(pt) > platform.floatSize) or
|
||||
(optByRef in param.options)) then begin
|
||||
result := true;
|
||||
end
|
||||
else if isCArray(pt) then
|
||||
result := false
|
||||
else if (pt.kind = tyVar) or (getSize(pt) > platform.floatSize) then begin
|
||||
result := true;
|
||||
end
|
||||
else
|
||||
result := false
|
||||
end;
|
||||
|
||||
const
|
||||
PointerTypes = {@set}[tySequence, tyString, tyRef, tyPtr, tyPointer];
|
||||
|
||||
procedure fillResult(param: PSym);
|
||||
begin
|
||||
fillLoc(param.loc, locParam, param.typ,
|
||||
toRope('Result'), {@set}[lfOnUnknown]);
|
||||
if UsePtrPassing(param) then param.loc.indirect := 1
|
||||
fillLoc(param.loc, locParam, param.typ, toRope('Result'), OnStack);
|
||||
if (mapType(param.typ) <> ctArray) and IsInvalidReturnType(param.typ) then
|
||||
begin
|
||||
include(param.loc.flags, lfIndirect);
|
||||
param.loc.s := OnUnknown
|
||||
end
|
||||
end;
|
||||
|
||||
procedure genProcParams(t: PType; out rettype, params: PRope);
|
||||
procedure genProcParams(m: BModule; t: PType; out rettype, params: PRope);
|
||||
var
|
||||
i, j: int;
|
||||
param: PSym;
|
||||
|
|
@ -165,31 +177,25 @@ begin
|
|||
// C cannot return arrays (what a poor language...)
|
||||
rettype := toRope('void')
|
||||
else
|
||||
rettype := getTypeDesc(t.sons[0]);
|
||||
rettype := getTypeDesc(m, t.sons[0]);
|
||||
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;
|
||||
fillLoc(param.loc, locParam, param.typ,
|
||||
con(toRope('Par'), toRope(i)), {@set}[lfOnStack]);
|
||||
if param.typ.kind = tyVar 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
|
||||
fillLoc(param.loc, locParam, param.typ, mangleName(param), OnStack);
|
||||
app(params, getTypeDesc(m, param.typ));
|
||||
if ccgIntroducedPtr(param) then begin
|
||||
app(params, '*'+'');
|
||||
param.loc.indirect := 1
|
||||
include(param.loc.flags, lfIndirect);
|
||||
param.loc.s := OnUnknown;
|
||||
end;
|
||||
app(params, ' '+'');
|
||||
|
||||
app(params, param.loc.r);
|
||||
// declare the len field for open arrays:
|
||||
arr := param.typ;
|
||||
if arr.kind = tyVar then arr := arr.sons[0];
|
||||
j := 0;
|
||||
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);
|
||||
arr := arr.sons[0]
|
||||
end;
|
||||
|
|
@ -197,8 +203,8 @@ begin
|
|||
end;
|
||||
if (t.sons[0] <> nil) and isInvalidReturnType(t.sons[0]) then begin
|
||||
if params <> nil then app(params, ', ');
|
||||
app(params, getTypeDesc(t.sons[0]));
|
||||
if not isCArray(t.sons[0]) then app(params, '*'+'');
|
||||
app(params, getTypeDesc(m, t.sons[0]));
|
||||
if mapType(t.sons[0]) <> ctArray then app(params, '*'+'');
|
||||
app(params, ' Result');
|
||||
end;
|
||||
if t.callConv = ccClosure then begin
|
||||
|
|
@ -216,11 +222,6 @@ begin
|
|||
params := con('('+'', params);
|
||||
end;
|
||||
|
||||
function getLengthOfSet(s: PNode): int;
|
||||
begin
|
||||
result := int(getSize(s.typ))
|
||||
end;
|
||||
|
||||
function isImportedType(t: PType): bool;
|
||||
begin
|
||||
result := (t.sym <> nil) and (sfImportc in t.sym.flags)
|
||||
|
|
@ -228,25 +229,10 @@ end;
|
|||
|
||||
function getTypeName(typ: PType): PRope;
|
||||
begin
|
||||
if typ.sym <> nil then begin
|
||||
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
|
||||
if (typ.sym <> nil) and ([sfImportc, sfExportc] * typ.sym.flags <> []) then
|
||||
result := typ.sym.loc.r
|
||||
else begin
|
||||
// we must use a unique type id here because we don't store
|
||||
// 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;
|
||||
if typ.loc.r = nil then typ.loc.r := con('Ty', toRope(typ.id));
|
||||
result := typ.loc.r
|
||||
end
|
||||
end;
|
||||
|
|
@ -262,18 +248,18 @@ end;
|
|||
function getSimpleTypeDesc(typ: PType): PRope;
|
||||
const
|
||||
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
|
||||
case typ.Kind of
|
||||
tyPointer: result := typeNameOrLiteral(typ, 'void*');
|
||||
tyEnum: begin
|
||||
if firstOrd(typ) < 0 then
|
||||
result := typeNameOrLiteral(typ, 'NS32')
|
||||
result := typeNameOrLiteral(typ, 'NI32')
|
||||
else begin
|
||||
case int(getSize(typ)) of
|
||||
1: result := typeNameOrLiteral(typ, 'NU8');
|
||||
2: result := typeNameOrLiteral(typ, 'NU16');
|
||||
4: result := typeNameOrLiteral(typ, 'NS32');
|
||||
4: result := typeNameOrLiteral(typ, 'NI32');
|
||||
else begin
|
||||
internalError('getSimpleTypeDesc()');
|
||||
result := nil
|
||||
|
|
@ -293,14 +279,14 @@ begin
|
|||
end
|
||||
end;
|
||||
|
||||
function getTypePre(typ: PType): PRope;
|
||||
function getTypePre(m: BModule; typ: PType): PRope;
|
||||
begin
|
||||
if typ = nil then
|
||||
result := toRope('void')
|
||||
else begin
|
||||
result := getSimpleTypeDesc(typ);
|
||||
if result = nil then
|
||||
result := CacheGetType(currMod.typeCache, typ)
|
||||
result := CacheGetType(m.typeCache, typ)
|
||||
end
|
||||
end;
|
||||
|
||||
|
|
@ -310,19 +296,18 @@ begin
|
|||
else result := 'typedef struct $1 $1;$n'
|
||||
end;
|
||||
|
||||
function getTypeForward(typ: PType): PRope;
|
||||
function getTypeForward(m: BModule; typ: PType): PRope;
|
||||
begin
|
||||
result := CacheGetType(currMod.forwTypeCache, typ);
|
||||
result := CacheGetType(m.forwTypeCache, typ);
|
||||
if result <> nil then exit;
|
||||
result := getTypePre(typ);
|
||||
result := getTypePre(m, typ);
|
||||
if result <> nil then exit;
|
||||
case typ.kind of
|
||||
tySequence, tyRecord, tyObject: begin
|
||||
tySequence, tyTuple, tyObject: begin
|
||||
result := getTypeName(typ);
|
||||
if not isImportedType(typ) then
|
||||
appRopeFormat(currMod.s[cfsForwardTypes],
|
||||
getForwardStructFormat(), [result]);
|
||||
IdTablePut(currMod.forwTypeCache, typ, result)
|
||||
appf(m.s[cfsForwardTypes], getForwardStructFormat(), [result]);
|
||||
IdTablePut(m.forwTypeCache, typ, result)
|
||||
end
|
||||
else
|
||||
InternalError('getTypeForward(' + typeKindToStr[typ.kind] + ')')
|
||||
|
|
@ -333,205 +318,254 @@ function mangleRecFieldName(field: PSym; rectype: PType): PRope;
|
|||
begin
|
||||
if (rectype.sym <> nil)
|
||||
and ([sfImportc, sfExportc] * rectype.sym.flags <> []) then
|
||||
result := toRope(field.name.s)
|
||||
result := field.loc.r
|
||||
else
|
||||
result := toRope(mangle(field.name.s))
|
||||
result := toRope(mangle(field.name.s));
|
||||
if result = nil then InternalError(field.info, 'mangleRecFieldName');
|
||||
end;
|
||||
|
||||
function genRecordFieldsAux(n: PNode; accessExpr: PRope; rectype: PType): PRope;
|
||||
function genRecordFieldsAux(m: BModule; n: PNode; accessExpr: PRope;
|
||||
rectype: PType): PRope;
|
||||
var
|
||||
i: int;
|
||||
ae, uname, sname, a: PRope;
|
||||
m: PNode;
|
||||
k: PNode;
|
||||
field: PSym;
|
||||
begin
|
||||
result := nil;
|
||||
case n.kind of
|
||||
nkRecList: 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;
|
||||
nkRecCase: begin
|
||||
assert(n.sons[0].kind = nkSym);
|
||||
app(result, genRecordFieldsAux(n.sons[0], accessExpr, rectype));
|
||||
if (n.sons[0].kind <> nkSym) then
|
||||
InternalError(n.info, 'genRecordFieldsAux');
|
||||
app(result, genRecordFieldsAux(m, n.sons[0], accessExpr, rectype));
|
||||
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;
|
||||
app(result, 'union {'+tnl);
|
||||
for i := 1 to sonsLen(n)-1 do begin
|
||||
case n.sons[i].kind of
|
||||
nkOfBranch, nkElse: begin
|
||||
m := lastSon(n.sons[i]);
|
||||
if m.kind <> nkSym then begin
|
||||
k := lastSon(n.sons[i]);
|
||||
if k.kind <> nkSym then begin
|
||||
sname := con('S'+'', toRope(i));
|
||||
a := genRecordFieldsAux(m, ropeFormat('$1.$2', [ae, sname]),
|
||||
a := genRecordFieldsAux(m, k, ropef('$1.$2', [ae, sname]),
|
||||
rectype);
|
||||
if a <> nil then begin
|
||||
app(result, 'struct {');
|
||||
app(result, a);
|
||||
appRopeFormat(result, '} $1;$n', [sname]);
|
||||
appf(result, '} $1;$n', [sname]);
|
||||
end
|
||||
end
|
||||
else app(result, genRecordFieldsAux(m, ae, rectype));
|
||||
else app(result, genRecordFieldsAux(m, k, ae, rectype));
|
||||
end;
|
||||
else internalError('genRecordFieldsAux(record case branch)');
|
||||
end;
|
||||
end;
|
||||
appRopeFormat(result, '} $1;$n', [uname])
|
||||
appf(result, '} $1;$n', [uname])
|
||||
end;
|
||||
nkSym: begin
|
||||
field := n.sym;
|
||||
assert(field.ast = nil);
|
||||
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;
|
||||
fillLoc(field.loc, locField, field.typ, ae, {@set}[]);
|
||||
appRopeFormat(result, '$1 $2;$n', [getTypeDesc(field.loc.t), sname])
|
||||
fillLoc(field.loc, locField, field.typ, ae, OnUnknown);
|
||||
appf(result, '$1 $2;$n', [getTypeDesc(m, field.loc.t), sname])
|
||||
end;
|
||||
else internalError(n.info, 'genRecordFieldsAux()');
|
||||
end
|
||||
end;
|
||||
|
||||
function getRecordFields(typ: PType): PRope;
|
||||
function getRecordFields(m: BModule; typ: PType): PRope;
|
||||
begin
|
||||
result := genRecordFieldsAux(typ.n, nil, typ);
|
||||
result := genRecordFieldsAux(m, typ.n, nil, typ);
|
||||
end;
|
||||
|
||||
function getRecordDesc(typ: PType; name: PRope): PRope;
|
||||
function getRecordDesc(m: BModule; typ: PType; name: PRope): PRope;
|
||||
var
|
||||
desc: PRope;
|
||||
hasField: bool;
|
||||
begin
|
||||
// declare the record:
|
||||
hasField := false;
|
||||
if typ.kind = tyObject then begin
|
||||
useMagic('TNimType');
|
||||
useMagic(m, 'TNimType');
|
||||
if typ.sons[0] = nil then begin
|
||||
if (typ.sym <> nil) and (sfPure in typ.sym.flags) then
|
||||
result := ropeFormat('struct $1 {$n', [name])
|
||||
else
|
||||
result := ropeFormat('struct $1 {$nTNimType* m_type;$n', [name])
|
||||
if (typ.sym <> nil) and (sfPure in typ.sym.flags)
|
||||
or (tfFinal in typ.flags) then
|
||||
result := ropef('struct $1 {$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
|
||||
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
|
||||
else
|
||||
result := ropeFormat('struct $1 {$n', [name]);
|
||||
desc := getRecordFields(typ);
|
||||
if (typ.kind <> tyObject) and (desc = nil) and (gCmd <> cmdCompileToCpp) then
|
||||
result := ropef('struct $1 {$n', [name]);
|
||||
desc := getRecordFields(m, typ);
|
||||
if (desc = nil) and not hasField then
|
||||
// no fields in struct are not valid in C, so generate a dummy:
|
||||
appRopeFormat(result, 'char dummy;$n', [])
|
||||
appf(result, 'char dummy;$n', [])
|
||||
else
|
||||
app(result, desc);
|
||||
app(result, '};' + tnl);
|
||||
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
|
||||
var
|
||||
name, rettype, desc, recdesc: PRope;
|
||||
n: biggestInt;
|
||||
t, et: PType;
|
||||
begin
|
||||
if typ.sym <> nil then useHeader(typ.sym);
|
||||
result := getTypePre(typ);
|
||||
t := getUniqueType(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;
|
||||
case typ.Kind of
|
||||
case t.Kind of
|
||||
tyRef, tyPtr, tyVar, tyOpenArray: begin
|
||||
case typ.sons[0].Kind of
|
||||
tyRecord, tyObject, tySequence: begin
|
||||
// no restriction!
|
||||
// We have a forward declaration for structs
|
||||
name := getTypeForward(typ.sons[0]);
|
||||
et := getUniqueType(t.sons[0]);
|
||||
if et.kind in [tyArrayConstr, tyArray, tyOpenArray] then
|
||||
et := getUniqueType(elemType(et));
|
||||
case et.Kind of
|
||||
tyObject, tyTuple: begin
|
||||
// no restriction! We have a forward declaration for structs
|
||||
name := getTypeForward(m, et);
|
||||
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;
|
||||
else begin
|
||||
// else we have a strong dependency :-(
|
||||
result := con(getTypeDesc(typ.sons[0]), '*'+'');
|
||||
IdTablePut(currMod.typeCache, typ, result)
|
||||
result := con(getTypeDesc(m, et), '*'+'');
|
||||
IdTablePut(m.typeCache, t, result)
|
||||
end
|
||||
end
|
||||
end;
|
||||
tyProc: begin
|
||||
result := getTypeName(typ);
|
||||
IdTablePut(currMod.typeCache, typ, result);
|
||||
genProcParams(typ, rettype, desc);
|
||||
if not isImportedType(typ) then begin
|
||||
if typ.callConv <> ccClosure then
|
||||
appRopeFormat(currMod.s[cfsTypes], 'typedef $1_PTR($2, $3) $4;$n',
|
||||
[toRope(CallingConvToStr[typ.callConv]), rettype, result, desc])
|
||||
result := getTypeName(t);
|
||||
IdTablePut(m.typeCache, t, result);
|
||||
genProcParams(m, t, rettype, desc);
|
||||
if not isImportedType(t) then begin
|
||||
if t.callConv <> ccClosure then
|
||||
appf(m.s[cfsTypes], 'typedef $1_PTR($2, $3) $4;$n',
|
||||
[toRope(CallingConvToStr[t.callConv]), rettype, result, desc])
|
||||
else // procedure vars may need a closure!
|
||||
appRopeFormat(currMod.s[cfsTypes], 'typedef struct $1 {$n' +
|
||||
'N_CDECL_PTR($2, PrcPart) $3;$n' +
|
||||
'void* ClPart;$n};$n',
|
||||
appf(m.s[cfsTypes], 'typedef struct $1 {$n' +
|
||||
'N_CDECL_PTR($2, PrcPart) $3;$n' +
|
||||
'void* ClPart;$n};$n',
|
||||
[result, rettype, desc]);
|
||||
end
|
||||
end;
|
||||
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:
|
||||
result := getTypeName(typ);
|
||||
IdTablePut(currMod.typeCache, typ, con(result, '*'+''));
|
||||
if not isImportedType(typ) then begin
|
||||
appRopeFormat(currMod.s[cfsForwardTypes],
|
||||
getForwardStructFormat(), [result]);
|
||||
appRopeFormat(currMod.s[cfsSeqTypes],
|
||||
// BUGFIX: needed to introduce cfsSeqTypes
|
||||
'struct $2 {$n' +
|
||||
' NS len, space;$n' +
|
||||
' $1 data[SEQ_DECL_SIZE];$n' +
|
||||
'};$n', [getTypeDesc(typ.sons[0]), result]);
|
||||
result := CacheGetType(m.forwTypeCache, t);
|
||||
if result = nil then begin
|
||||
result := getTypeName(t);
|
||||
if not isImportedType(t) then
|
||||
appf(m.s[cfsForwardTypes], getForwardStructFormat(), [result]);
|
||||
IdTablePut(m.forwTypeCache, t, result);
|
||||
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, '*'+'');
|
||||
end;
|
||||
tyArrayConstr, tyArray: begin
|
||||
n := lengthOrd(typ);
|
||||
n := lengthOrd(t);
|
||||
if n <= 0 then n := 1; // make an array of at least one element
|
||||
result := getTypeName(typ);
|
||||
IdTablePut(currMod.typeCache, typ, result);
|
||||
if not isImportedType(typ) then
|
||||
appRopeFormat(currMod.s[cfsTypes], 'typedef $1 $2[$3];$n',
|
||||
[getTypeDesc(typ.sons[1]), result, ToRope(n)])
|
||||
result := getTypeName(t);
|
||||
IdTablePut(m.typeCache, t, result);
|
||||
if not isImportedType(t) then
|
||||
appf(m.s[cfsTypes], 'typedef $1 $2[$3];$n',
|
||||
[getTypeDesc(m, t.sons[1]), result, ToRope(n)])
|
||||
end;
|
||||
tyObject, tyRecord, tyRecordConstr: begin
|
||||
result := getTypeName(typ);
|
||||
IdTablePut(currMod.typeCache, typ, result);
|
||||
recdesc := getRecordDesc(typ, result); // always compute for sideeffects
|
||||
if not isImportedType(typ) then
|
||||
app(currMod.s[cfsTypes], recdesc);
|
||||
if CacheGetType(currMod.forwTypeCache, typ) = nil then begin
|
||||
if not isImportedType(typ) then
|
||||
appRopeFormat(currMod.s[cfsForwardTypes],
|
||||
tyObject, tyTuple: begin
|
||||
result := CacheGetType(m.forwTypeCache, t);
|
||||
if result = nil then begin
|
||||
result := getTypeName(t);
|
||||
if not isImportedType(t) then
|
||||
appf(m.s[cfsForwardTypes],
|
||||
getForwardStructFormat(), [result]);
|
||||
IdTablePut(currMod.forwTypeCache, typ, result)
|
||||
end
|
||||
IdTablePut(m.forwTypeCache, t, result)
|
||||
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;
|
||||
tySet: begin
|
||||
case int(getSize(typ)) of
|
||||
1: result := toRope('NS8');
|
||||
2: result := toRope('NS16');
|
||||
4: result := toRope('NS32');
|
||||
8: result := toRope('NS64');
|
||||
case int(getSize(t)) of
|
||||
1: result := toRope('NU8');
|
||||
2: result := toRope('NU16');
|
||||
4: result := toRope('NU32');
|
||||
8: result := toRope('NU64');
|
||||
else begin
|
||||
result := getTypeName(typ);
|
||||
IdTablePut(currMod.typeCache, typ, result);
|
||||
if not isImportedType(typ) then
|
||||
appRopeFormat(currMod.s[cfsTypes], 'typedef NS8 $1[$2];$n',
|
||||
[result, toRope(getSize(typ))])
|
||||
result := getTypeName(t);
|
||||
IdTablePut(m.typeCache, t, result);
|
||||
if not isImportedType(t) then
|
||||
appf(m.s[cfsTypes], 'typedef NU8 $1[$2];$n',
|
||||
[result, toRope(getSize(t))])
|
||||
end
|
||||
end
|
||||
end
|
||||
end;
|
||||
tyGenericInst: result := getTypeDesc(m, lastSon(t));
|
||||
else begin
|
||||
InternalError('getTypeDesc(' + typeKindToStr[typ.kind] + ')');
|
||||
InternalError('getTypeDesc(' + typeKindToStr[t.kind] + ')');
|
||||
result := nil
|
||||
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
|
||||
rettype, params: PRope;
|
||||
begin
|
||||
|
|
@ -540,9 +574,9 @@ begin
|
|||
result := toRope('static ')
|
||||
else
|
||||
result := nil;
|
||||
fillLoc(prc.loc, locProc, prc.typ, mangleName(prc), {@set}[]);
|
||||
genProcParams(prc.typ, rettype, params);
|
||||
appRopeFormat(result, '$1($2, $3)$4',
|
||||
fillLoc(prc.loc, locProc, prc.typ, mangleName(prc), OnUnknown);
|
||||
genProcParams(m, prc.typ, rettype, params);
|
||||
appf(result, '$1($2, $3)$4',
|
||||
[toRope(CallingConvToStr[prc.typ.callConv]),
|
||||
rettype, prc.loc.r, params])
|
||||
end;
|
||||
|
|
@ -559,19 +593,26 @@ var
|
|||
tmp: PRope;
|
||||
begin
|
||||
tmp := getTempName();
|
||||
appRopeFormat(m.s[cfsTypeInit1], 'static TNimType $1;$n', [tmp]);
|
||||
appRopeFormat(m.s[cfsTypeInit2], '$2 = &$1;$n', [tmp, name]);
|
||||
appf(m.s[cfsTypeInit1], 'static TNimType $1;$n', [tmp]);
|
||||
appf(m.s[cfsTypeInit2], '$2 = &$1;$n', [tmp, name]);
|
||||
end;
|
||||
|
||||
procedure genTypeInfoAuxBase(m: BModule; typ: PType; name, base: PRope);
|
||||
var
|
||||
nimtypeKind: int;
|
||||
begin
|
||||
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->kind = $3;$n' +
|
||||
'$1->base = $4;$n', [
|
||||
name, getTypeDesc(typ), toRope(ord(typ.kind)), base]);
|
||||
appRopeFormat(m.s[cfsVars], 'TNimType* $1;$n', [name]);
|
||||
name, getTypeDesc(m, typ), toRope(nimtypeKind), base]);
|
||||
appf(m.s[cfsVars], 'TNimType* $1;$n', [name]);
|
||||
end;
|
||||
|
||||
procedure genTypeInfoAux(m: BModule; typ: PType; name: PRope);
|
||||
|
|
@ -599,21 +640,21 @@ begin
|
|||
genObjectFields(m, typ, n.sons[0], expr)
|
||||
else if len > 0 then begin
|
||||
tmp := getTempName();
|
||||
appRopeFormat(m.s[cfsTypeInit1], 'static TNimNode* $1[$2];$n',
|
||||
[tmp, toRope(len)]);
|
||||
appf(m.s[cfsTypeInit1], 'static TNimNode* $1[$2];$n',
|
||||
[tmp, toRope(len)]);
|
||||
for i := 0 to len-1 do begin
|
||||
tmp2 := getTempName();
|
||||
appRopeFormat(m.s[cfsTypeInit1], 'static TNimNode $1;$n', [tmp2]);
|
||||
appRopeFormat(m.s[cfsTypeInit3], '$1[$2] = &$3;$n',
|
||||
appf(m.s[cfsTypeInit1], 'static TNimNode $1;$n', [tmp2]);
|
||||
appf(m.s[cfsTypeInit3], '$1[$2] = &$3;$n',
|
||||
[tmp, toRope(i), tmp2]);
|
||||
genObjectFields(m, typ, n.sons[i], tmp2);
|
||||
end;
|
||||
appRopeFormat(m.s[cfsTypeInit3],
|
||||
'$1.len = $2; $1.kind = 2; $1.sons = &$3;$n', [
|
||||
appf(m.s[cfsTypeInit3],
|
||||
'$1.len = $2; $1.kind = 2; $1.sons = &$3[0];$n', [
|
||||
expr, toRope(len), tmp]);
|
||||
end
|
||||
else
|
||||
appRopeFormat(m.s[cfsTypeInit3],
|
||||
appf(m.s[cfsTypeInit3],
|
||||
'$1.len = $2; $1.kind = 2;$n', [expr, toRope(len)]);
|
||||
end;
|
||||
nkRecCase: begin
|
||||
|
|
@ -621,22 +662,22 @@ begin
|
|||
assert(n.sons[0].kind = nkSym);
|
||||
field := n.sons[0].sym;
|
||||
tmp := getTempName();
|
||||
appRopeFormat(m.s[cfsTypeInit3], '$1.kind = 3;$n' +
|
||||
'$1.offset = offsetof($2, $3);$n' +
|
||||
'$1.typ = $4;$n' +
|
||||
'$1.name = $5;$n' +
|
||||
'$1.sons = &$6;$n' +
|
||||
'$1.len = $7;$n',
|
||||
[expr, getTypeDesc(typ), field.loc.r,
|
||||
appf(m.s[cfsTypeInit3], '$1.kind = 3;$n' +
|
||||
'$1.offset = offsetof($2, $3);$n' +
|
||||
'$1.typ = $4;$n' +
|
||||
'$1.name = $5;$n' +
|
||||
'$1.sons = &$6[0];$n' +
|
||||
'$1.len = $7;$n',
|
||||
[expr, getTypeDesc(m, typ), field.loc.r,
|
||||
genTypeInfo(m, field.typ),
|
||||
makeCString(field.name.s), tmp,
|
||||
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)]);
|
||||
for i := 1 to len-1 do begin
|
||||
b := n.sons[i]; // branch
|
||||
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);
|
||||
//writeln(output, renderTree(b.sons[j]));
|
||||
case b.kind of
|
||||
|
|
@ -648,18 +689,18 @@ begin
|
|||
x := int(getOrdValue(b.sons[j].sons[0]));
|
||||
y := int(getOrdValue(b.sons[j].sons[1]));
|
||||
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]);
|
||||
inc(x);
|
||||
end;
|
||||
end
|
||||
else
|
||||
appRopeFormat(m.s[cfsTypeInit3], '$1[$2] = &$3;$n',
|
||||
appf(m.s[cfsTypeInit3], '$1[$2] = &$3;$n',
|
||||
[tmp, toRope(getOrdValue(b.sons[j])), tmp2])
|
||||
end
|
||||
end;
|
||||
nkElse: begin
|
||||
appRopeFormat(m.s[cfsTypeInit3], '$1[$2] = &$3;$n',
|
||||
appf(m.s[cfsTypeInit3], '$1[$2] = &$3;$n',
|
||||
[tmp, toRope(lengthOrd(field.typ)), tmp2]);
|
||||
end
|
||||
else
|
||||
|
|
@ -669,13 +710,13 @@ begin
|
|||
end;
|
||||
nkSym: begin
|
||||
field := n.sym;
|
||||
appRopeFormat(m.s[cfsTypeInit3], '$1.kind = 1;$n' +
|
||||
'$1.offset = offsetof($2, $3);$n' +
|
||||
'$1.typ = $4;$n' +
|
||||
'$1.name = $5;$n',
|
||||
[expr, getTypeDesc(typ), field.loc.r,
|
||||
genTypeInfo(m, field.typ),
|
||||
makeCString(field.name.s)]);
|
||||
appf(m.s[cfsTypeInit3], '$1.kind = 1;$n' +
|
||||
'$1.offset = offsetof($2, $3);$n' +
|
||||
'$1.typ = $4;$n' +
|
||||
'$1.name = $5;$n',
|
||||
[expr, getTypeDesc(m, typ), field.loc.r,
|
||||
genTypeInfo(m, field.typ),
|
||||
makeCString(field.name.s)]);
|
||||
end;
|
||||
else internalError(n.info, 'genObjectFields');
|
||||
end
|
||||
|
|
@ -685,11 +726,12 @@ procedure genObjectInfo(m: BModule; typ: PType; name: PRope);
|
|||
var
|
||||
tmp: PRope;
|
||||
begin
|
||||
genTypeInfoAux(m, typ, name);
|
||||
if typ.kind = tyObject then genTypeInfoAux(m, typ, name)
|
||||
else genTypeInfoAuxBase(m, typ, name, toRope('0'+''));
|
||||
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);
|
||||
appRopeFormat(m.s[cfsTypeInit3], '$1->node = &$2;$n', [name, tmp]);
|
||||
appf(m.s[cfsTypeInit3], '$1->node = &$2;$n', [name, tmp]);
|
||||
end;
|
||||
|
||||
procedure genEnumInfo(m: BModule; typ: PType; name: PRope);
|
||||
|
|
@ -702,25 +744,25 @@ begin
|
|||
tmp := getTempName();
|
||||
tmp2 := getTempName();
|
||||
len := sonsLen(typ.n);
|
||||
appRopeFormat(m.s[cfsTypeInit1], 'static TNimNode* $1[$2];$n' +
|
||||
'static TNimNode $3;$n',
|
||||
[tmp, toRope(len), tmp2]);
|
||||
appf(m.s[cfsTypeInit1], 'static TNimNode* $1[$2];$n' +
|
||||
'static TNimNode $3;$n',
|
||||
[tmp, toRope(len), tmp2]);
|
||||
for i := 0 to len-1 do begin
|
||||
assert(typ.n.sons[i].kind = nkSym);
|
||||
field := typ.n.sons[i].sym;
|
||||
tmp3 := getTempName();
|
||||
appRopeFormat(m.s[cfsTypeInit1], 'static TNimNode $1;$n', [tmp3]);
|
||||
appRopeFormat(m.s[cfsTypeInit3], '$1[$2] = &$3;$n' +
|
||||
'$3.kind = 1;$n' +
|
||||
'$3.offset = $4;$n' +
|
||||
'$3.typ = $5;$n' +
|
||||
'$3.name = $6;$n',
|
||||
appf(m.s[cfsTypeInit1], 'static TNimNode $1;$n', [tmp3]);
|
||||
appf(m.s[cfsTypeInit3], '$1[$2] = &$3;$n' +
|
||||
'$3.kind = 1;$n' +
|
||||
'$3.offset = $4;$n' +
|
||||
'$3.typ = $5;$n' +
|
||||
'$3.name = $6;$n',
|
||||
[tmp, toRope(i), tmp3,
|
||||
toRope(field.position),
|
||||
name, makeCString(field.name.s)]);
|
||||
end;
|
||||
appRopeFormat(m.s[cfsTypeInit3],
|
||||
'$1.len = $2; $1.kind = 2; $1.sons = &$3;$n$4->node = &$1;$n', [
|
||||
appf(m.s[cfsTypeInit3],
|
||||
'$1.len = $2; $1.kind = 2; $1.sons = &$3[0];$n$4->node = &$1;$n', [
|
||||
tmp2, toRope(len), tmp, name]);
|
||||
end;
|
||||
|
||||
|
|
@ -731,8 +773,8 @@ begin
|
|||
assert(typ.sons[0] <> nil);
|
||||
genTypeInfoAux(m, typ, name);
|
||||
tmp := getTempName();
|
||||
appRopeFormat(m.s[cfsTypeInit1], 'static TNimNode $1;$n', [tmp]);
|
||||
appRopeFormat(m.s[cfsTypeInit3],
|
||||
appf(m.s[cfsTypeInit1], 'static TNimNode $1;$n', [tmp]);
|
||||
appf(m.s[cfsTypeInit3],
|
||||
'$1.len = $2; $1.kind = 0;$n' +
|
||||
'$3->node = &$1;$n', [tmp, toRope(firstOrd(typ)), name]);
|
||||
end;
|
||||
|
|
@ -746,14 +788,13 @@ function genTypeInfo(m: BModule; typ: PType): PRope;
|
|||
var
|
||||
t: PType;
|
||||
begin
|
||||
t := typ;
|
||||
if t.kind = tyGenericInst then t := lastSon(t);
|
||||
result := ropeFormat('NTI$1', [toRope(t.id)]);
|
||||
t := getUniqueType(typ);
|
||||
result := ropef('NTI$1', [toRope(t.id)]);
|
||||
if not IntSetContainsOrIncl(m.typeInfoMarker, t.id) then begin
|
||||
// declare type information structures:
|
||||
useMagic('TNimType');
|
||||
useMagic('TNimNode');
|
||||
appRopeFormat(m.s[cfsVars], 'extern TNimType* $1;$n', [result]);
|
||||
useMagic(m, 'TNimType');
|
||||
useMagic(m, 'TNimNode');
|
||||
appf(m.s[cfsVars], 'extern TNimType* $1;$n', [result]);
|
||||
end;
|
||||
if IntSetContainsOrIncl(gTypeInfoGenerated, t.id) then exit;
|
||||
case t.kind of
|
||||
|
|
@ -763,7 +804,7 @@ begin
|
|||
tyArrayConstr, tyArray: genArrayInfo(m, t, result);
|
||||
tySet: genSetInfo(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]);
|
||||
else InternalError('genTypeInfo(' + typekindToStr[t.kind] + ')');
|
||||
end
|
||||
|
|
|
|||
|
|
@ -17,15 +17,41 @@ interface
|
|||
|
||||
uses
|
||||
charsets, nsystem,
|
||||
ast, astalgo, ropes, lists, hashes, strutils, types;
|
||||
ast, astalgo, ropes, lists, hashes, strutils, types, msgs;
|
||||
|
||||
function toCChar(c: Char): string;
|
||||
function makeCString(const s: string): PRope;
|
||||
|
||||
function TableGetType(const tab: TIdTable; key: PType): PObject;
|
||||
function GetUniqueType(key: PType): PType;
|
||||
|
||||
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;
|
||||
var
|
||||
t: PType;
|
||||
|
|
@ -69,7 +95,7 @@ begin
|
|||
result := nil;
|
||||
res := '"'+'';
|
||||
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;
|
||||
app(result, toRope(res));
|
||||
res := '"'+''; // reset
|
||||
|
|
@ -80,4 +106,6 @@ begin
|
|||
app(result, toRope(res));
|
||||
end;
|
||||
|
||||
initialization
|
||||
InitIdTable(gTypeTable);
|
||||
end.
|
||||
|
|
|
|||
370
nim/cgen.pas
370
nim/cgen.pas
|
|
@ -43,13 +43,28 @@ type
|
|||
cfsProcHeaders, // section for C procs prototypes
|
||||
cfsProcs, // section for C procs that are not inline
|
||||
cfsTypeInit1, // section 1 for declarations of type information
|
||||
cfsTypeInit2, // section A for initialization of type information
|
||||
cfsTypeInit3, // section B for init of type information
|
||||
cfsTypeInit2, // section 2 for initialization of type information
|
||||
cfsTypeInit3, // section 3 for init of type information
|
||||
cfsDebugInit, // section for initialization of debug information
|
||||
cfsDynLibInit, // section for initialization of dynamic library binding
|
||||
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 represents a generated C file
|
||||
|
|
@ -66,15 +81,20 @@ type
|
|||
BModule = ^TCGen;
|
||||
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
|
||||
s: TCProcSections; // the procs sections; short name for readability
|
||||
prc: PSym; // the Nimrod proc that this C proc belongs to
|
||||
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)
|
||||
unique: Natural; // for generating unique names in the C proc
|
||||
blocks: array of int; // the ID of the label; positive means that it
|
||||
// has been used (i.e. the label should be emitted)
|
||||
labels: Natural; // for generating unique labels in the C proc
|
||||
blocks: array of TBlock; // nested blocks
|
||||
locals: array of TLoc; // locNone means slot is free again
|
||||
options: TOptions; // options that should be used for code
|
||||
// generation; this is the same as prc.options
|
||||
|
|
@ -82,8 +102,9 @@ type
|
|||
frameLen: int; // current length of frame descriptor
|
||||
sendClosure: PType; // closure record type that we pass
|
||||
receiveClosure: PType; // closure record type that we get
|
||||
module: BModule; // used to prevent excessive parameter passing
|
||||
end;
|
||||
|
||||
TTypeSeq = array of PType;
|
||||
TCGen = object(TBackend) // represents a C source file
|
||||
s: TCFileSections; // sections of the C file
|
||||
cfilename: string; // filename of the module (including path,
|
||||
|
|
@ -93,55 +114,48 @@ type
|
|||
declaredThings: TIntSet; // things we have declared in this .c file
|
||||
debugDeclared: TIntSet; // for debugging purposes
|
||||
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
|
||||
initProc: BProc; // code for init procedure
|
||||
typeStack: TTypeSeq; // used for type generation
|
||||
end;
|
||||
|
||||
var
|
||||
currMod: BModule; // currently compiled module
|
||||
// a global so that this needs not to be
|
||||
// passed to every proc
|
||||
gUnique: Natural;
|
||||
mainModProcs, mainModInit: PRope; // parts of the main module
|
||||
gMapping: PRope; // the generated mapping file (if requested)
|
||||
|
||||
constTok: PRope; // either 'const ' or nil depending on gCmd
|
||||
|
||||
function initLoc(k: TLocKind; typ: PType): TLoc;
|
||||
function initLoc(k: TLocKind; typ: PType; s: TStorageLoc): TLoc;
|
||||
begin
|
||||
result.k := k;
|
||||
result.t := typ;
|
||||
result.s := s;
|
||||
result.t := GetUniqueType(typ);
|
||||
result.r := nil;
|
||||
result.a := -1;
|
||||
result.indirect := 0;
|
||||
result.flags := {@set}[]
|
||||
end;
|
||||
|
||||
procedure fillLoc(var a: TLoc; k: TLocKind; typ: PType; r: PRope;
|
||||
flags: TLocFlags);
|
||||
s: TStorageLoc);
|
||||
begin
|
||||
// fills the loc if it is not already initialized
|
||||
if a.k = locNone then begin
|
||||
a.k := k;
|
||||
if typ.kind = tyGenericInst then a.t := lastSon(typ) else a.t := typ;
|
||||
a.t := getUniqueType(typ);
|
||||
a.a := -1;
|
||||
a.s := s;
|
||||
if a.r = nil then a.r := r;
|
||||
a.flags := a.flags + flags
|
||||
end
|
||||
end;
|
||||
|
||||
procedure inheritStorage(var dest: TLoc; const src: TLoc);
|
||||
begin
|
||||
dest.flags := src.flags * [lfOnStack, lfOnHeap, lfOnData, lfOnUnknown]
|
||||
end;
|
||||
|
||||
function newProc(prc: PSym): BProc;
|
||||
function newProc(prc: PSym; module: BModule): BProc;
|
||||
begin
|
||||
new(result);
|
||||
{@ignore}
|
||||
fillChar(result^, sizeof(result^), 0);
|
||||
{@emit}
|
||||
result.prc := prc;
|
||||
result.module := module;
|
||||
if prc <> nil then
|
||||
result.options := prc.options
|
||||
else
|
||||
|
|
@ -157,20 +171,19 @@ end;
|
|||
|
||||
function isSimpleConst(typ: PType): bool;
|
||||
begin
|
||||
result := not (skipAbstract(typ).kind in [tyRecord, tyRecordConstr,
|
||||
tyObject, tyArray,
|
||||
result := not (skipVarGeneric(typ).kind in [tyTuple, tyObject, tyArray,
|
||||
tyArrayConstr, tySet, tySequence])
|
||||
end;
|
||||
|
||||
procedure useHeader(sym: PSym);
|
||||
procedure useHeader(m: BModule; sym: PSym);
|
||||
begin
|
||||
if lfHeader in sym.loc.Flags then begin
|
||||
assert(sym.annex <> nil);
|
||||
{@discard} lists.IncludeStr(currMod.headerFiles, PLib(sym.annex).path)
|
||||
{@discard} lists.IncludeStr(m.headerFiles, PLib(sym.annex).path)
|
||||
end
|
||||
end;
|
||||
|
||||
procedure UseMagic(const name: string); forward;
|
||||
procedure UseMagic(m: BModule; const name: string); forward;
|
||||
|
||||
// ----------------------------- name mangling
|
||||
// +++++++++++++++++++++++++++++ type generation
|
||||
|
|
@ -182,14 +195,14 @@ procedure UseMagic(const name: string); forward;
|
|||
function beEqualTypes(a, b: PType): bool;
|
||||
begin
|
||||
// returns whether two type are equal for the backend
|
||||
result := sameType(skipAbstract(a), skipAbstract(b))
|
||||
result := sameType(skipGenericRange(a), skipGenericRange(b))
|
||||
end;
|
||||
|
||||
function getTemp(p: BProc; t: PType): TLoc;
|
||||
var
|
||||
i, index: int;
|
||||
name: PRope;
|
||||
begin
|
||||
begin (*
|
||||
for i := 0 to high(p.locals) do begin
|
||||
assert(i = p.locals[i].a);
|
||||
if (p.locals[i].k = locNone) and beEqualTypes(p.locals[i].t, t) then begin
|
||||
|
|
@ -198,41 +211,41 @@ begin
|
|||
result := p.locals[i];
|
||||
exit
|
||||
end
|
||||
end;
|
||||
end; *)
|
||||
// not found:
|
||||
index := length(p.locals);
|
||||
setLength(p.locals, index+1);
|
||||
// declare the new temporary:
|
||||
name := con('Loc', toRope(index));
|
||||
appRopeFormat(p.s[cpsLocals], '$1 $2; /* temporary */$n',
|
||||
[getTypeDesc(t), name]);
|
||||
appf(p.s[cpsLocals], '$1 $2; /* temporary */$n',
|
||||
[getTypeDesc(p.module, t), name]);
|
||||
p.locals[index].k := locTemp;
|
||||
p.locals[index].a := index;
|
||||
p.locals[index].r := name;
|
||||
p.locals[index].t := t;
|
||||
p.locals[index].flags := {@set}[lfOnStack];
|
||||
p.locals[index].t := getUniqueType(t);
|
||||
p.locals[index].s := OnStack;
|
||||
p.locals[index].flags := {@set}[];
|
||||
result := p.locals[index] // BUGFIX!
|
||||
end;
|
||||
|
||||
procedure freeTemp(p: BProc; const temp: TLoc);
|
||||
begin
|
||||
begin (*
|
||||
if (temp.a >= 0) and (temp.a < length(p.locals)) and
|
||||
(p.locals[temp.a].k = locTemp) then
|
||||
p.locals[temp.a].k := locNone
|
||||
p.locals[temp.a].k := locNone *)
|
||||
end;
|
||||
|
||||
// -------------------------- Variable manager ----------------------------
|
||||
|
||||
procedure declareGlobalVar(s: PSym);
|
||||
procedure declareGlobalVar(m: BModule; s: PSym);
|
||||
begin
|
||||
if not IntSetContainsOrIncl(currMod.declaredThings, s.id) then begin
|
||||
app(currMod.s[cfsVars], getTypeDesc(s.loc.t));
|
||||
if not IntSetContainsOrIncl(m.declaredThings, s.id) then begin
|
||||
app(m.s[cfsVars], getTypeDesc(m, s.loc.t));
|
||||
if sfRegister in s.flags then
|
||||
app(currMod.s[cfsVars], ' register');
|
||||
app(m.s[cfsVars], ' register');
|
||||
if sfVolatile in s.flags then
|
||||
app(currMod.s[cfsVars], ' volatile');
|
||||
appRopeFormat(currMod.s[cfsVars], ' $1; /* $2 */$n',
|
||||
[s.loc.r, toRope(s.name.s)])
|
||||
app(m.s[cfsVars], ' volatile');
|
||||
appf(m.s[cfsVars], ' $1;$n', [s.loc.r])
|
||||
end
|
||||
end;
|
||||
|
||||
|
|
@ -241,39 +254,38 @@ begin
|
|||
//assert(s.loc.k == locNone) // not yet assigned
|
||||
// this need not be fullfilled for inline procs; they are regenerated
|
||||
// for each module that uses them!
|
||||
fillLoc(s.loc, locLocalVar, s.typ, mangleName(s), {@set}[lfOnStack]);
|
||||
app(p.s[cpsLocals], getTypeDesc(s.loc.t));
|
||||
fillLoc(s.loc, locLocalVar, s.typ, mangleName(s), OnStack);
|
||||
app(p.s[cpsLocals], getTypeDesc(p.module, s.loc.t));
|
||||
if sfRegister in s.flags then
|
||||
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');
|
||||
|
||||
appRopeFormat(p.s[cpsLocals], ' $1; /* $2 */$n',
|
||||
[s.loc.r, toRope(s.name.s)]);
|
||||
appf(p.s[cpsLocals], ' $1;$n', [s.loc.r]);
|
||||
// if debugging we need a new slot for the local variable:
|
||||
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',
|
||||
[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);
|
||||
end
|
||||
end;
|
||||
|
||||
procedure assignGlobalVar(s: PSym);
|
||||
procedure assignGlobalVar(m: BModule; s: PSym);
|
||||
begin
|
||||
fillLoc(s.loc, locGlobalVar, s.typ, mangleName(s), {@set}[lfOnData]);
|
||||
useHeader(s);
|
||||
fillLoc(s.loc, locGlobalVar, s.typ, mangleName(s), OnHeap);
|
||||
useHeader(m, s);
|
||||
if lfNoDecl in s.loc.flags then exit;
|
||||
if sfImportc in s.flags then app(currMod.s[cfsVars], 'extern ');
|
||||
declareGlobalVar(s);
|
||||
if [optStackTrace, optEndb] * currMod.module.options =
|
||||
if sfImportc in s.flags then app(m.s[cfsVars], 'extern ');
|
||||
declareGlobalVar(m, s);
|
||||
if [optStackTrace, optEndb] * m.module.options =
|
||||
[optStackTrace, optEndb] then begin
|
||||
useMagic('dbgRegisterGlobal');
|
||||
appRopeFormat(currMod.s[cfsDebugInit],
|
||||
useMagic(m, 'dbgRegisterGlobal');
|
||||
appf(m.s[cfsDebugInit],
|
||||
'dbgRegisterGlobal($1, &$2, $3);$n',
|
||||
[makeCString(normalize(s.owner.name.s + '.' +{&} s.name.s)), s.loc.r,
|
||||
genTypeInfo(currMod, s.typ)])
|
||||
genTypeInfo(m, s.typ)])
|
||||
end;
|
||||
end;
|
||||
|
||||
|
|
@ -286,12 +298,12 @@ procedure assignParam(p: BProc; s: PSym);
|
|||
begin
|
||||
assert(s.loc.r <> nil);
|
||||
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',
|
||||
[toRope(p.frameLen), makeCString(normalize(s.name.s)),
|
||||
iff(usePtrPassing(s), s.loc.r, con('&'+'', s.loc.r)),
|
||||
genTypeInfo(currMod, s.loc.t)]);
|
||||
iff(ccgIntroducedPtr(s), s.loc.r, con('&'+'', s.loc.r)),
|
||||
genTypeInfo(p.module, s.loc.t)]);
|
||||
inc(p.frameLen)
|
||||
end
|
||||
end;
|
||||
|
|
@ -301,19 +313,19 @@ end;
|
|||
// note that a label is a location too
|
||||
function getLabel(p: BProc): TLabel;
|
||||
begin
|
||||
inc(p.unique);
|
||||
result := con('L'+'', toRope(p.unique))
|
||||
inc(p.labels);
|
||||
result := con('L'+'', toRope(p.labels))
|
||||
end;
|
||||
|
||||
procedure fixLabel(p: BProc; labl: TLabel);
|
||||
begin
|
||||
appRopeFormat(p.s[cpsStmts], '$1: ;$n', [labl])
|
||||
appf(p.s[cpsStmts], '$1: ;$n', [labl])
|
||||
end;
|
||||
|
||||
procedure genProcPrototype(sym: PSym); forward;
|
||||
procedure genVarPrototype(sym: PSym); forward;
|
||||
procedure genConstPrototype(sym: PSym); forward;
|
||||
procedure genProc(prc: PSym); forward;
|
||||
procedure genProcPrototype(m: BModule; sym: PSym); forward;
|
||||
procedure genVarPrototype(m: BModule; sym: PSym); forward;
|
||||
procedure genConstPrototype(m: BModule; sym: PSym); forward;
|
||||
procedure genProc(m: BModule; prc: PSym); forward;
|
||||
procedure genStmts(p: BProc; t: PNode); forward;
|
||||
|
||||
{$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.
|
||||
|
||||
procedure loadDynamicLib(lib: PLib);
|
||||
procedure loadDynamicLib(m: BModule; lib: PLib);
|
||||
var
|
||||
tmp: PRope;
|
||||
begin
|
||||
assert(lib <> nil);
|
||||
if lib.kind = libDynamic then begin
|
||||
lib.kind := libDynamicGenerated;
|
||||
useMagic('nimLoadLibrary');
|
||||
useMagic('nimUnloadLibrary');
|
||||
useMagic(m, 'nimLoadLibrary');
|
||||
useMagic(m, 'nimUnloadLibrary');
|
||||
tmp := getTempName();
|
||||
appRopeFormat(currMod.s[cfsVars], 'static void* $1;$n', [tmp]);
|
||||
appRopeFormat(currMod.s[cfsDynLibInit],
|
||||
appf(m.s[cfsVars], 'static void* $1;$n', [tmp]);
|
||||
appf(m.s[cfsDynLibInit],
|
||||
'$1 = nimLoadLibrary((string) &$2);$n',
|
||||
[tmp, getStrLit(lib.path)]);
|
||||
appRopeFormat(currMod.s[cfsDynLibDeinit],
|
||||
[tmp, getStrLit(m, lib.path)]);
|
||||
appf(m.s[cfsDynLibDeinit],
|
||||
'if ($1 != NIM_NIL) nimUnloadLibrary($1);$n', [tmp]);
|
||||
assert(lib.name = nil);
|
||||
lib.name := tmp
|
||||
end
|
||||
end;
|
||||
|
||||
procedure SymInDynamicLib(sym: PSym);
|
||||
procedure SymInDynamicLib(m: BModule; sym: PSym);
|
||||
var
|
||||
lib: PLib;
|
||||
extname, tmp: PRope;
|
||||
begin
|
||||
lib := PLib(sym.annex);
|
||||
extname := sym.loc.r;
|
||||
loadDynamicLib(lib);
|
||||
useMagic('nimGetProcAddr');
|
||||
tmp := ropeFormat('Dl_$1', [toRope(sym.id)]);
|
||||
loadDynamicLib(m, lib);
|
||||
useMagic(m, 'nimGetProcAddr');
|
||||
tmp := ropef('Dl_$1', [toRope(sym.id)]);
|
||||
sym.loc.r := tmp; // from now on we only need the internal name
|
||||
sym.typ.sym := nil; // generate a new name
|
||||
appRopeFormat(currMod.s[cfsDynLibInit],
|
||||
appf(m.s[cfsDynLibInit],
|
||||
'$1 = ($2) nimGetProcAddr($3, $4);$n',
|
||||
[tmp, getTypeDesc(sym.typ), lib.name,
|
||||
[tmp, getTypeDesc(m, sym.typ), lib.name,
|
||||
makeCString(ropeToStr(extname))]);
|
||||
declareGlobalVar(sym)
|
||||
declareGlobalVar(m, sym)
|
||||
end;
|
||||
|
||||
// ----------------------------- sections ---------------------------------
|
||||
|
||||
procedure UseMagic(const name: string);
|
||||
procedure UseMagic(m: BModule; const name: string);
|
||||
var
|
||||
sym: PSym;
|
||||
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
|
||||
// there anyway, because that is the way the code generator works
|
||||
sym := magicsys.getCompilerProc(name);
|
||||
case sym.kind of
|
||||
skProc: genProcPrototype(sym);
|
||||
skVar: genVarPrototype(sym);
|
||||
skType: {@discard} getTypeDesc(sym.typ);
|
||||
skProc, skConverter: genProcPrototype(m, sym);
|
||||
skVar: genVarPrototype(m, sym);
|
||||
skType: {@discard} getTypeDesc(m, sym.typ);
|
||||
else InternalError('useMagic: ' + name)
|
||||
end
|
||||
end;
|
||||
|
||||
procedure generateHeaders();
|
||||
procedure generateHeaders(m: BModule);
|
||||
var
|
||||
it: PStrEntry;
|
||||
begin
|
||||
app(currMod.s[cfsHeaders], '#include "nimbase.h"' +{&} tnl +{&} tnl);
|
||||
it := PStrEntry(currMod.headerFiles.head);
|
||||
app(m.s[cfsHeaders], '#include "nimbase.h"' +{&} tnl +{&} tnl);
|
||||
it := PStrEntry(m.headerFiles.head);
|
||||
while it <> nil do begin
|
||||
if not (it.data[strStart] in ['"', '<']) then
|
||||
appRopeFormat(currMod.s[cfsHeaders],
|
||||
appf(m.s[cfsHeaders],
|
||||
'#include "$1"$n', [toRope(it.data)])
|
||||
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)
|
||||
end
|
||||
end;
|
||||
|
|
@ -402,15 +414,15 @@ var
|
|||
slots: PRope;
|
||||
begin
|
||||
if p.frameLen > 0 then begin
|
||||
useMagic('TVarSlot');
|
||||
slots := ropeFormat(' TVarSlot s[$1];$n', [toRope(p.frameLen)])
|
||||
useMagic(p.module, 'TVarSlot');
|
||||
slots := ropef(' TVarSlot s[$1];$n', [toRope(p.frameLen)])
|
||||
end
|
||||
else
|
||||
slots := nil;
|
||||
appRopeFormat(p.s[cpsLocals], 'volatile struct {TFrame* prev;' +
|
||||
'NCSTRING procname;NS line;NCSTRING filename;' +
|
||||
'NS len;$n$1} F;$n', [slots]);
|
||||
prepend(p.s[cpsInit], ropeFormat('F.len = $1;$n', [toRope(p.frameLen)]))
|
||||
appf(p.s[cpsLocals], 'volatile struct {TFrame* prev;' +
|
||||
'NCSTRING procname;NI line;NCSTRING filename;' +
|
||||
'NI len;$n$1} F;$n', [slots]);
|
||||
prepend(p.s[cpsInit], ropef('F.len = $1;$n', [toRope(p.frameLen)]))
|
||||
end;
|
||||
|
||||
function retIsNotVoid(s: PSym): bool;
|
||||
|
|
@ -418,27 +430,27 @@ begin
|
|||
result := (s.typ.sons[0] <> nil) and not isInvalidReturnType(s.typ.sons[0])
|
||||
end;
|
||||
|
||||
procedure genProc(prc: PSym);
|
||||
procedure genProc(m: BModule; prc: PSym);
|
||||
var
|
||||
p: BProc;
|
||||
generatedProc, header, returnStmt: PRope;
|
||||
i: int;
|
||||
res, param: PSym;
|
||||
begin
|
||||
useHeader(prc);
|
||||
fillLoc(prc.loc, locProc, prc.typ, mangleName(prc), {@set}[lfOnData]);
|
||||
useHeader(m, prc);
|
||||
fillLoc(prc.loc, locProc, prc.typ, mangleName(prc), OnStack);
|
||||
if (lfNoDecl in prc.loc.Flags) then exit;
|
||||
if lfDynamicLib in prc.loc.flags then
|
||||
SymInDynamicLib(prc)
|
||||
SymInDynamicLib(m, prc)
|
||||
else if not (sfImportc in prc.flags) then begin
|
||||
// we have a real proc here:
|
||||
p := newProc(prc);
|
||||
header := genProcHeader(prc);
|
||||
p := newProc(prc, m);
|
||||
header := genProcHeader(m, prc);
|
||||
if (sfCompilerProc in prc.flags)
|
||||
and (sfSystemModule in currMod.module.flags)
|
||||
and not IntSetContains(currMod.declaredThings, prc.id) then
|
||||
appRopeFormat(currMod.s[cfsProcHeaders], '$1;$n', [header]);
|
||||
intSetIncl(currMod.declaredThings, prc.id);
|
||||
and (sfSystemModule in m.module.flags)
|
||||
and not IntSetContains(m.declaredThings, prc.id) then
|
||||
appf(m.s[cfsProcHeaders], '$1;$n', [header]);
|
||||
intSetIncl(m.declaredThings, prc.id);
|
||||
returnStmt := nil;
|
||||
assert(prc.ast <> nil);
|
||||
|
||||
|
|
@ -450,7 +462,7 @@ begin
|
|||
assert(res.loc.r <> nil);
|
||||
initVariable(p, res);
|
||||
genObjectInit(p, res);
|
||||
returnStmt := ropeFormat('return $1;$n', [rdLoc(res.loc)]);
|
||||
returnStmt := ropef('return $1;$n', [rdLoc(res.loc)]);
|
||||
end
|
||||
else if (prc.typ.sons[0] <> nil) then begin
|
||||
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.
|
||||
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]])
|
||||
else begin
|
||||
generatedProc := con(header, '{' + tnl);
|
||||
if optStackTrace in prc.options then begin
|
||||
getFrameDecl(p);
|
||||
prepend(p.s[cpsInit], ropeFormat(
|
||||
prepend(p.s[cpsInit], ropef(
|
||||
'F.procname = $1;$n' +
|
||||
'F.prev = framePtr;$n' +
|
||||
'F.filename = $2;$n' +
|
||||
|
|
@ -491,86 +503,93 @@ begin
|
|||
//if prc.typ.callConv <> ccInline then
|
||||
// prc.ast.sons[codePos] := nil;
|
||||
end;
|
||||
app(currMod.s[cfsProcs], generatedProc);
|
||||
app(m.s[cfsProcs], generatedProc);
|
||||
end
|
||||
end;
|
||||
|
||||
procedure genVarPrototype(sym: PSym);
|
||||
procedure genVarPrototype(m: BModule; sym: PSym);
|
||||
begin
|
||||
assert(sfGlobal in sym.flags);
|
||||
useHeader(sym);
|
||||
fillLoc(sym.loc, locGlobalVar, sym.typ, mangleName(sym), {@set}[lfOnData]);
|
||||
useHeader(m, sym);
|
||||
fillLoc(sym.loc, locGlobalVar, sym.typ, mangleName(sym), OnHeap);
|
||||
if (lfNoDecl in sym.loc.Flags) or
|
||||
intSetContainsOrIncl(currMod.declaredThings, sym.id) then
|
||||
intSetContainsOrIncl(m.declaredThings, sym.id) then
|
||||
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!
|
||||
assert(sym.loc.r <> nil);
|
||||
app(currMod.s[cfsVars], 'extern ');
|
||||
app(currMod.s[cfsVars], getTypeDesc(sym.loc.t));
|
||||
app(m.s[cfsVars], 'extern ');
|
||||
app(m.s[cfsVars], getTypeDesc(m, sym.loc.t));
|
||||
if sfRegister in sym.flags then
|
||||
app(currMod.s[cfsVars], ' register');
|
||||
app(m.s[cfsVars], ' register');
|
||||
if sfVolatile in sym.flags then
|
||||
app(currMod.s[cfsVars], ' volatile');
|
||||
appRopeFormat(currMod.s[cfsVars], ' $1; /* $2 */$n',
|
||||
[sym.loc.r, toRope(sym.name.s)])
|
||||
app(m.s[cfsVars], ' volatile');
|
||||
appf(m.s[cfsVars], ' $1;$n', [sym.loc.r])
|
||||
end
|
||||
end;
|
||||
|
||||
procedure genConstPrototype(sym: PSym);
|
||||
procedure genConstPrototype(m: BModule; sym: PSym);
|
||||
begin
|
||||
useHeader(sym);
|
||||
fillLoc(sym.loc, locData, sym.typ, mangleName(sym), {@set}[lfOnData]);
|
||||
useHeader(m, sym);
|
||||
fillLoc(sym.loc, locData, sym.typ, mangleName(sym), OnUnknown);
|
||||
if (lfNoDecl in sym.loc.Flags) or
|
||||
intSetContainsOrIncl(currMod.declaredThings, sym.id) then
|
||||
intSetContainsOrIncl(m.declaredThings, sym.id) then
|
||||
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!
|
||||
assert(sym.loc.r <> nil);
|
||||
app(currMod.s[cfsData], 'extern ');
|
||||
appRopeFormat(currMod.s[cfsData], '$1$2 $3; /* $4 */$n',
|
||||
[constTok, getTypeDesc(sym.loc.t), sym.loc.r, toRope(sym.name.s)])
|
||||
app(m.s[cfsData], 'extern ');
|
||||
appf(m.s[cfsData], 'NIM_CONST $1 $2;$n',
|
||||
[getTypeDesc(m, sym.loc.t), sym.loc.r])
|
||||
end
|
||||
end;
|
||||
|
||||
procedure genProcPrototype(sym: PSym);
|
||||
procedure genProcPrototype(m: BModule; sym: PSym);
|
||||
begin
|
||||
useHeader(sym);
|
||||
fillLoc(sym.loc, locProc, sym.typ, mangleName(sym), {@set}[lfOnData]);
|
||||
useHeader(m, sym);
|
||||
fillLoc(sym.loc, locProc, sym.typ, mangleName(sym), OnStack);
|
||||
if lfDynamicLib in sym.loc.Flags then begin
|
||||
// it is a proc variable!
|
||||
if (sym.owner.id <> currMod.module.id) and
|
||||
not intSetContainsOrIncl(currMod.declaredThings, sym.id) then begin
|
||||
app(currMod.s[cfsVars], 'extern ');
|
||||
if (sym.owner.id <> m.module.id) and
|
||||
not intSetContainsOrIncl(m.declaredThings, sym.id) then begin
|
||||
app(m.s[cfsVars], 'extern ');
|
||||
// BUGFIX: declareGlobalVar() inlined, because of intSetContainsOrIncl
|
||||
// check
|
||||
app(currMod.s[cfsVars], getTypeDesc(sym.loc.t));
|
||||
appRopeFormat(currMod.s[cfsVars], ' $1; /* $2 */$n',
|
||||
[sym.loc.r, toRope(sym.name.s)])
|
||||
app(m.s[cfsVars], getTypeDesc(m, sym.loc.t));
|
||||
appf(m.s[cfsVars], ' $1;$n', [sym.loc.r])
|
||||
end
|
||||
end
|
||||
else begin
|
||||
// it is a proc:
|
||||
if (lfNoDecl in sym.loc.Flags) then exit;
|
||||
if intSetContainsOrIncl(currMod.declaredThings, sym.id) then exit;
|
||||
appRopeFormat(currMod.s[cfsProcHeaders], '$1;$n', [genProcHeader(sym)]);
|
||||
if intSetContainsOrIncl(m.declaredThings, sym.id) then exit;
|
||||
appf(m.s[cfsProcHeaders], '$1;$n', [genProcHeader(m, sym)]);
|
||||
if (sym.typ.callConv = ccInline)
|
||||
and (sym.owner.id <> currMod.module.id) then
|
||||
genProc(sym) // generate the code again!
|
||||
// else
|
||||
// IntSetIncl(currMod.declaredThings, sym.id)
|
||||
and (sym.owner.id <> m.module.id) then
|
||||
genProc(m, sym) // generate the code again!
|
||||
end
|
||||
end;
|
||||
|
||||
function getFileHeader: PRope;
|
||||
function getFileHeader(const cfilenoext: string): PRope;
|
||||
begin
|
||||
result := ropeFormat(
|
||||
result := ropef(
|
||||
'/* Generated by the Nimrod Compiler v$1 */$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(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;
|
||||
|
||||
procedure genMainProc(m: BModule);
|
||||
|
|
@ -581,13 +600,13 @@ const
|
|||
'$1' +
|
||||
'$2';
|
||||
PosixMain =
|
||||
'NS cmdCount;$n' +
|
||||
'NI cmdCount;$n' +
|
||||
'char** cmdLine;$n' +
|
||||
'char** gEnv;$n' +
|
||||
'int main(int argc, char** args, char** env) {$n' +
|
||||
' int dummy[8];$n' +
|
||||
' cmdLine = args;$n' +
|
||||
' cmdCount = (NS)argc;$n' +
|
||||
' cmdCount = (NI)argc;$n' +
|
||||
' gEnv = env;$n' +{&}
|
||||
CommonMainBody +{&}
|
||||
' return 0;$n' +
|
||||
|
|
@ -610,7 +629,7 @@ const
|
|||
var
|
||||
frmt: TFormatStr;
|
||||
begin
|
||||
useMagic('setStackBottom');
|
||||
useMagic(m, 'setStackBottom');
|
||||
if (platform.targetOS = osWindows) and
|
||||
(gGlobalOptions * [optGenGuiApp, optGenDynLib] <> []) then begin
|
||||
if optGenGuiApp in gGlobalOptions then
|
||||
|
|
@ -622,8 +641,8 @@ begin
|
|||
else
|
||||
frmt := PosixMain;
|
||||
if gBreakpoints <> nil then
|
||||
useMagic('dbgRegisterBreakpoint');
|
||||
appRopeFormat(m.s[cfsProcs], frmt, [gBreakpoints, mainModInit])
|
||||
useMagic(m, 'dbgRegisterBreakpoint');
|
||||
appf(m.s[cfsProcs], frmt, [gBreakpoints, mainModInit])
|
||||
end;
|
||||
|
||||
procedure genInitCode(m: BModule);
|
||||
|
|
@ -631,16 +650,16 @@ var
|
|||
initname, prc: PRope;
|
||||
begin
|
||||
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]);
|
||||
if not (sfSystemModule in m.module.flags) then
|
||||
appRopeFormat(mainModInit, '$1();$n', [initname]);
|
||||
prc := ropeFormat('N_NIMCALL(void, $1)(void) {$n', [initname]);
|
||||
appf(mainModInit, '$1();$n', [initname]);
|
||||
prc := ropef('N_NIMCALL(void, $1)(void) {$n', [initname]);
|
||||
if optStackTrace in m.initProc.options then begin
|
||||
prepend(m.initProc.s[cpsLocals], toRope('volatile TFrame F;' + tnl));
|
||||
app(prc, m.initProc.s[cpsLocals]);
|
||||
app(prc, m.s[cfsTypeInit1]);
|
||||
appRopeFormat(prc,
|
||||
appf(prc,
|
||||
'F.len = 0;$n' + // IMPORTANT: else the debugger crashes!
|
||||
'F.procname = $1;$n' +
|
||||
'F.prev = framePtr;$n' +
|
||||
|
|
@ -666,12 +685,12 @@ begin
|
|||
app(m.s[cfsProcs], prc)
|
||||
end;
|
||||
|
||||
function genModule(m: BModule): PRope;
|
||||
function genModule(m: BModule; const cfilenoext: string): PRope;
|
||||
var
|
||||
i: TCFileSection;
|
||||
begin
|
||||
result := getFileHeader();
|
||||
generateHeaders();
|
||||
result := getFileHeader(cfilenoext);
|
||||
generateHeaders(m);
|
||||
for i := low(TCFileSection) to cfsProcs do app(result, m.s[i])
|
||||
end;
|
||||
|
||||
|
|
@ -688,11 +707,10 @@ begin
|
|||
initIdTable(result.typeCache);
|
||||
initIdTable(result.forwTypeCache);
|
||||
result.module := module;
|
||||
if gCmd <> cmdCompileToCpp then
|
||||
constTok := toRope('const ');
|
||||
intSetInit(result.typeInfoMarker);
|
||||
result.initProc := newProc(nil);
|
||||
result.initProc := newProc(nil, result);
|
||||
result.initProc.options := gOptions;
|
||||
{@emit result.typeStack := [];}
|
||||
end;
|
||||
|
||||
function shouldRecompile(code: PRope; const cfile, cfilenoext: string): bool;
|
||||
|
|
@ -717,28 +735,27 @@ var
|
|||
code: PRope;
|
||||
begin
|
||||
m := BModule(b);
|
||||
currMod := m;
|
||||
currMod.initProc.options := gOptions;
|
||||
genStmts(currMod.initProc, n);
|
||||
m.initProc.options := gOptions;
|
||||
genStmts(m.initProc, n);
|
||||
// generate code for the init statements of the module:
|
||||
genInitCode(m);
|
||||
finishTypeDescriptions(m);
|
||||
if sfMainModule in m.module.flags then begin
|
||||
// generate mapping file (if requested):
|
||||
if gMapping <> nil then
|
||||
WriteRope(gMapping, ChangeFileExt(cfile + '_map', 'txt'));
|
||||
|
||||
// generate main file:
|
||||
app(currMod.s[cfsProcHeaders], mainModProcs);
|
||||
genMainProc(currMod);
|
||||
app(m.s[cfsProcHeaders], mainModProcs);
|
||||
genMainProc(m);
|
||||
end;
|
||||
cfile := completeCFilePath(m.cfilename);
|
||||
cfilenoext := changeFileExt(cfile, '');
|
||||
code := genModule(m);
|
||||
code := genModule(m, cfilenoext);
|
||||
if shouldRecompile(code, changeFileExt(cfile, cExt), cfilenoext) then begin
|
||||
addFileToCompile(cfilenoext); // is to compile
|
||||
end;
|
||||
addFileToLink(cfilenoext);
|
||||
currMod := nil // free the memory
|
||||
end;
|
||||
|
||||
function CBackend(b: PBackend; module: PSym; const filename: string): PBackend;
|
||||
|
|
@ -749,7 +766,6 @@ begin
|
|||
g.backendCreator := CBackend;
|
||||
g.eventMask := {@set}[eAfterModule];
|
||||
g.afterModuleEvent := finishModule;
|
||||
currMod := g;
|
||||
result := g;
|
||||
end;
|
||||
|
||||
|
|
|
|||
|
|
@ -7,10 +7,10 @@
|
|||
// distribution, for details about the copyright.
|
||||
//
|
||||
|
||||
// This module handles the parsing of command line arguments.
|
||||
|
||||
unit commands;
|
||||
|
||||
// This module handles the parsing of command line arguments.
|
||||
|
||||
interface
|
||||
|
||||
{$include 'config.inc'}
|
||||
|
|
@ -41,16 +41,14 @@ uses
|
|||
const
|
||||
{$ifdef fpc}
|
||||
compileDate = {$I %date%};
|
||||
compileTime = {$I %time%};
|
||||
{$else}
|
||||
compileDate = '2008-0-0';
|
||||
compileTime = '00:00:00';
|
||||
{$endif}
|
||||
{@emit}
|
||||
|
||||
const
|
||||
HelpMessage = 'Nimrod Compiler Version $1 (' +{&}
|
||||
compileDate +{&} ' ' +{&} compileTime +{&} ') [$2: $3]' +{&} nl +{&}
|
||||
compileDate +{&} ') [$2: $3]' +{&} nl +{&}
|
||||
'Copyright (c) 2004-2008 by Andreas Rumpf' +{&} nl;
|
||||
|
||||
const
|
||||
|
|
@ -66,7 +64,8 @@ const
|
|||
+{&} ' compile compile project with default code generator (C)' +{&} nl
|
||||
+{&} ' compile_to_c compile project with C code generator' +{&} nl
|
||||
+{&} ' compile_to_cpp compile project with C++ code generator' +{&} nl
|
||||
+{&} ' doc generate the documentation for inputfile; ' +{&} nl
|
||||
+{&} ' compile_to_ecmascript compile project to ECMAScript code (experimental)' +{&} nl
|
||||
+{&} ' doc generate the documentation for inputfile;' +{&} nl
|
||||
+{&} ' with --run switch opens it with $BROWSER' +{&} nl
|
||||
+{&} 'Arguments:' +{&} nl
|
||||
+{&} ' arguments are passed to the program being run (if --run option is selected)' +{&} nl
|
||||
|
|
@ -80,6 +79,8 @@ const
|
|||
+{&} ' --line_trace:on|off code generation for line trace 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
|
||||
+{&} ' --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
|
||||
+{&} ' --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
|
||||
|
|
@ -174,17 +175,8 @@ const
|
|||
;
|
||||
|
||||
function getCommandLineDesc: string;
|
||||
var
|
||||
v: string;
|
||||
begin
|
||||
// the Pascal version number gets a little star ('*'), the Nimrod version
|
||||
// does not! This helps distinguishing the different builds.
|
||||
{@ignore}
|
||||
v := VersionAsString +{&} '*';
|
||||
{@emit
|
||||
v := VersionAsString
|
||||
}
|
||||
result := format(HelpMessage, [v, platform.os[hostOS].name,
|
||||
result := format(HelpMessage, [VersionAsString, platform.os[hostOS].name,
|
||||
cpu[hostCPU].name]) +{&} Usage
|
||||
end;
|
||||
|
||||
|
|
@ -210,6 +202,7 @@ begin
|
|||
cpu[hostCPU].name]) +{&} AdvancedUsage);
|
||||
advHelpWritten := true;
|
||||
helpWritten := true;
|
||||
halt(0);
|
||||
end
|
||||
end;
|
||||
|
||||
|
|
@ -423,7 +416,7 @@ begin
|
|||
ProcessOnOffSwitch({@set}[optHints], arg, pass, info);
|
||||
wCheckpoints:
|
||||
ProcessOnOffSwitch({@set}[optCheckpoints], arg, pass, info);
|
||||
wStackTrace, wS:
|
||||
wStackTrace:
|
||||
ProcessOnOffSwitch({@set}[optStackTrace], arg, pass, info);
|
||||
wLineTrace:
|
||||
ProcessOnOffSwitch({@set}[optLineTrace], arg, pass, info);
|
||||
|
|
@ -436,6 +429,10 @@ begin
|
|||
end;
|
||||
wChecks, wX:
|
||||
ProcessOnOffSwitch(checksOptions, arg, pass, info);
|
||||
wObjChecks:
|
||||
ProcessOnOffSwitch({@set}[optObjCheck], arg, pass, info);
|
||||
wFieldChecks:
|
||||
ProcessOnOffSwitch({@set}[optFieldCheck], arg, pass, info);
|
||||
wRangeChecks:
|
||||
ProcessOnOffSwitch({@set}[optRangeCheck], arg, pass, info);
|
||||
wBoundChecks:
|
||||
|
|
@ -485,6 +482,10 @@ begin
|
|||
liMessage(info, errGuiConsoleOrLibExpectedButXFound, arg)
|
||||
end
|
||||
end;
|
||||
wListDef: begin
|
||||
if pass in {@set}[passCmd2, passPP] then
|
||||
condsyms.listSymbols();
|
||||
end;
|
||||
wPassC, wT: begin
|
||||
expectArg(switch, arg, pass, info);
|
||||
if pass in {@set}[passCmd2, passPP] then
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ type
|
|||
TCrc32 = int32;
|
||||
|
||||
const
|
||||
InitCrc32 = TCrc32($ffffffff);
|
||||
InitCrc32 = TCrc32(-1);
|
||||
|
||||
function updateCrc32(val: Byte; crc: TCrc32): TCrc32; overload;
|
||||
function updateCrc32(val: Char; crc: TCrc32): TCrc32; overload;
|
||||
|
|
|
|||
193
nim/docgen.pas
193
nim/docgen.pas
|
|
@ -40,6 +40,7 @@ type
|
|||
modDesc: PRope; // module description
|
||||
dependsOn: PRope; // dependencies
|
||||
id: int; // for generating IDs
|
||||
splitAfter: int; // split to long entries in the TOC
|
||||
tocPart: array of TTocEntry;
|
||||
hasToc: bool;
|
||||
toc, section: TSections;
|
||||
|
|
@ -106,6 +107,8 @@ begin
|
|||
end;
|
||||
|
||||
function newDocumentor(const filename: string): PDoc;
|
||||
var
|
||||
s: string;
|
||||
begin
|
||||
new(result);
|
||||
{@ignore}
|
||||
|
|
@ -115,6 +118,10 @@ begin
|
|||
}
|
||||
result.filename := filename;
|
||||
result.id := 100;
|
||||
result.splitAfter := 25;
|
||||
s := getConfigVar('split.item.toc');
|
||||
if s <> '' then
|
||||
result.splitAfter := parseInt(s);
|
||||
end;
|
||||
|
||||
function getVarIdx(const varnames: array of string; const id: string): int;
|
||||
|
|
@ -209,12 +216,16 @@ begin
|
|||
end
|
||||
end;
|
||||
|
||||
function toXml(const s: string): string;
|
||||
function toXml(const s: string; splitAfter: int = -1): string;
|
||||
var
|
||||
i: int;
|
||||
begin
|
||||
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;
|
||||
|
||||
function renderRstToHtml(d: PDoc; n: PRstNode): PRope; forward;
|
||||
|
|
@ -226,8 +237,8 @@ var
|
|||
begin
|
||||
result := nil;
|
||||
for i := 0 to rsonsLen(n)-1 do
|
||||
appRopeFormat(result, inner, [renderRstToHtml(d, n.sons[i])]);
|
||||
result := ropeFormat(outer, [result]);
|
||||
appf(result, inner, [renderRstToHtml(d, n.sons[i])]);
|
||||
result := ropef(outer, [result]);
|
||||
end;
|
||||
|
||||
procedure setIndexForSourceTerm(d: PDoc; name: PRstNode; id: int);
|
||||
|
|
@ -249,7 +260,7 @@ var
|
|||
a, h: PRstNode;
|
||||
begin
|
||||
inc(d.id);
|
||||
result := ropeFormat('<em id="$1">$2</em>',
|
||||
result := ropef('<em id="$1">$2</em>',
|
||||
[toRope(d.id), renderAux(d, n)]);
|
||||
h := newRstNode(rnHyperlink);
|
||||
a := newRstNode(rnLeaf, d.indexValFilename +{&} '#' +{&} toString(d.id));
|
||||
|
|
@ -277,11 +288,13 @@ var
|
|||
begin
|
||||
if n = nil then begin result := nil; exit end;
|
||||
result := genComment(d, n);
|
||||
if result = nil then
|
||||
for i := 0 to sonsLen(n)-1 do begin
|
||||
result := genRecComment(d, n.sons[i]);
|
||||
if result <> nil then exit
|
||||
end
|
||||
if result = nil then begin
|
||||
if not (n.kind in [nkEmpty..nkNilLit]) then
|
||||
for i := 0 to sonsLen(n)-1 do begin
|
||||
result := genRecComment(d, n.sons[i]);
|
||||
if result <> nil then exit
|
||||
end
|
||||
end
|
||||
else
|
||||
n.comment := snil
|
||||
end;
|
||||
|
|
@ -303,14 +316,14 @@ begin
|
|||
result := isVisible(n.sons[0]);
|
||||
end;
|
||||
|
||||
function getName(n: PNode): string;
|
||||
function getName(n: PNode; splitAfter: int = -1): string;
|
||||
begin
|
||||
case n.kind of
|
||||
nkPostfix: result := getName(n.sons[1]);
|
||||
nkPragmaExpr: result := getName(n.sons[0]);
|
||||
nkSym: result := toXML(n.sym.name.s);
|
||||
nkIdent: result := toXML(n.ident.s);
|
||||
nkAccQuoted: result := '`' +{&} getName(n.sons[0]) +{&} '`';
|
||||
nkPostfix: result := getName(n.sons[1], splitAfter);
|
||||
nkPragmaExpr: result := getName(n.sons[0], splitAfter);
|
||||
nkSym: result := toXML(n.sym.name.s, splitAfter);
|
||||
nkIdent: result := toXML(n.ident.s, splitAfter);
|
||||
nkAccQuoted: result := '`' +{&} getName(n.sons[0], splitAfter) +{&} '`';
|
||||
else begin
|
||||
internalError(n.info, 'getName()');
|
||||
result := ''
|
||||
|
|
@ -355,49 +368,49 @@ begin
|
|||
case kind of
|
||||
tkEof: break;
|
||||
tkComment:
|
||||
appRopeFormat(result, '<span class="Comment">$1</span>',
|
||||
appf(result, '<span class="Comment">$1</span>',
|
||||
[toRope(toXml(literal))]);
|
||||
tokKeywordLow..tokKeywordHigh:
|
||||
appRopeFormat(result, '<span class="Keyword">$1</span>',
|
||||
appf(result, '<span class="Keyword">$1</span>',
|
||||
[toRope(literal)]);
|
||||
tkOpr, tkHat:
|
||||
appRopeFormat(result, '<span class="Operator">$1</span>',
|
||||
appf(result, '<span class="Operator">$1</span>',
|
||||
[toRope(toXml(literal))]);
|
||||
tkStrLit..tkTripleStrLit:
|
||||
appRopeFormat(result, '<span class="StringLit">$1</span>',
|
||||
appf(result, '<span class="StringLit">$1</span>',
|
||||
[toRope(toXml(literal))]);
|
||||
tkCharLit, tkRCharLit:
|
||||
appRopeFormat(result, '<span class="CharLit">$1</span>',
|
||||
tkCharLit:
|
||||
appf(result, '<span class="CharLit">$1</span>',
|
||||
[toRope(toXml(literal))]);
|
||||
tkIntLit..tkInt64Lit:
|
||||
appRopeFormat(result, '<span class="DecNumber">$1</span>',
|
||||
appf(result, '<span class="DecNumber">$1</span>',
|
||||
[toRope(literal)]);
|
||||
tkFloatLit..tkFloat64Lit:
|
||||
appRopeFormat(result, '<span class="FloatNumber">$1</span>',
|
||||
appf(result, '<span class="FloatNumber">$1</span>',
|
||||
[toRope(literal)]);
|
||||
tkSymbol:
|
||||
appRopeFormat(result, '<span class="Identifier">$1</span>',
|
||||
appf(result, '<span class="Identifier">$1</span>',
|
||||
[toRope(literal)]);
|
||||
tkInd, tkSad, tkDed, tkSpaces:
|
||||
app(result, literal);
|
||||
//appRopeFormat(result, '<span class="Whitespace">$1</span>',
|
||||
//appf(result, '<span class="Whitespace">$1</span>',
|
||||
// [toRope(literal)]);
|
||||
tkParLe, tkParRi, tkBracketLe, tkBracketRi, tkCurlyLe, tkCurlyRi,
|
||||
tkBracketDotLe, tkBracketDotRi, tkCurlyDotLe, tkCurlyDotRi,
|
||||
tkParDotLe, tkParDotRi, tkComma, tkSemiColon, tkColon,
|
||||
tkEquals, tkDot, tkDotDot, tkAccent:
|
||||
appRopeFormat(result, '<span class="Other">$1</span>',
|
||||
appf(result, '<span class="Other">$1</span>',
|
||||
[toRope(literal)]);
|
||||
else InternalError(n.info, 'docgen.genThing(' + toktypeToStr[kind] + ')');
|
||||
end
|
||||
end;
|
||||
inc(d.id);
|
||||
app(d.section[k], ropeFormatNamedVars(getConfigVar('doc.item'),
|
||||
['name', 'header', 'desc', 'itemID'],
|
||||
[name, result, comm, toRope(d.id)]));
|
||||
['name', 'header', 'desc', 'itemID'],
|
||||
[name, result, comm, toRope(d.id)]));
|
||||
app(d.toc[k], ropeFormatNamedVars(getConfigVar('doc.item.toc'),
|
||||
['name', 'header', 'desc', 'itemID'],
|
||||
[name, result, comm, toRope(d.id)]));
|
||||
['name', 'header', 'desc', 'itemID'],
|
||||
[toRope(getName(nameNode, d.splitAfter)), result, comm, toRope(d.id)]));
|
||||
setIndexForSourceTerm(d, getRstName(nameNode), d.id);
|
||||
end;
|
||||
|
||||
|
|
@ -416,12 +429,12 @@ begin
|
|||
d.tocPart[len].refname := refname;
|
||||
d.tocPart[len].n := n;
|
||||
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>',
|
||||
[toRope(n.level), d.tocPart[len].refname, result]);
|
||||
end
|
||||
else
|
||||
result := ropeFormat('<h$1 id="$2">$3</h$1>',
|
||||
result := ropef('<h$1 id="$2">$3</h$1>',
|
||||
[toRope(n.level), refname, result]);
|
||||
end;
|
||||
|
||||
|
|
@ -437,7 +450,7 @@ begin
|
|||
if d.meta[metaTitle] = nil then d.meta[metaTitle] := t
|
||||
else if d.meta[metaSubtitle] = nil then d.meta[metaSubtitle] := t
|
||||
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]);
|
||||
end;
|
||||
|
||||
|
|
@ -469,32 +482,32 @@ begin
|
|||
rnHeadline: begin
|
||||
result := renderRstSons(d, n);
|
||||
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]))]);
|
||||
end;
|
||||
rnOverline: begin
|
||||
result := renderRstSons(d, n);
|
||||
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]))]);
|
||||
end;
|
||||
rnTransition:
|
||||
result := ropeFormat('$n$n$1$2$n$n',
|
||||
result := ropef('$n$n$1$2$n$n',
|
||||
[ind, toRope(repeatChar(78-d.indent, '-'))]);
|
||||
rnParagraph: begin
|
||||
result := renderRstSons(d, n);
|
||||
result := ropeFormat('$n$n$1$2', [ind, result]);
|
||||
result := ropef('$n$n$1$2', [ind, result]);
|
||||
end;
|
||||
rnBulletItem: begin
|
||||
inc(d.indent, 2);
|
||||
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);
|
||||
end;
|
||||
rnEnumItem: begin
|
||||
inc(d.indent, 4);
|
||||
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);
|
||||
end;
|
||||
rnOptionList, rnFieldList, rnDefList, rnDefItem, rnLineBlock, rnFieldName,
|
||||
|
|
@ -502,27 +515,27 @@ begin
|
|||
result := renderRstSons(d, n);
|
||||
rnDefName: begin
|
||||
result := renderRstSons(d, n);
|
||||
result := ropeFormat('$n$n$1$2', [ind, result]);
|
||||
result := ropef('$n$n$1$2', [ind, result]);
|
||||
end;
|
||||
rnDefBody: begin
|
||||
inc(d.indent, 2);
|
||||
result := renderRstSons(d, n);
|
||||
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);
|
||||
end;
|
||||
rnField: begin
|
||||
result := renderRstToRst(d, n.sons[0]);
|
||||
L := max(ropeLen(result)+3, 30);
|
||||
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)),
|
||||
renderRstToRst(d, n.sons[1])]);
|
||||
dec(d.indent, L);
|
||||
end;
|
||||
rnLineBlockItem: begin
|
||||
result := renderRstSons(d, n);
|
||||
result := ropeFormat('$n$1| $2', [ind, result]);
|
||||
result := ropef('$n$1| $2', [ind, result]);
|
||||
end;
|
||||
rnBlockQuote: begin
|
||||
inc(d.indent, 2);
|
||||
|
|
@ -531,44 +544,44 @@ begin
|
|||
end;
|
||||
rnRef: begin
|
||||
result := renderRstSons(d, n);
|
||||
result := ropeFormat('`$1`_', [result]);
|
||||
result := ropef('`$1`_', [result]);
|
||||
end;
|
||||
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])]);
|
||||
end;
|
||||
rnGeneralRole: begin
|
||||
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;
|
||||
rnSub: begin
|
||||
result := renderRstSons(d, n);
|
||||
result := ropeFormat('`$1`:sub:', [result]);
|
||||
result := ropef('`$1`:sub:', [result]);
|
||||
end;
|
||||
rnSup: begin
|
||||
result := renderRstSons(d, n);
|
||||
result := ropeFormat('`$1`:sup:', [result]);
|
||||
result := ropef('`$1`:sup:', [result]);
|
||||
end;
|
||||
rnIdx: begin
|
||||
result := renderRstSons(d, n);
|
||||
result := ropeFormat('`$1`:idx:', [result]);
|
||||
result := ropef('`$1`:idx:', [result]);
|
||||
end;
|
||||
rnEmphasis: begin
|
||||
result := renderRstSons(d, n);
|
||||
result := ropeFormat('*$1*', [result]);
|
||||
result := ropef('*$1*', [result]);
|
||||
end;
|
||||
rnStrongEmphasis: begin
|
||||
result := renderRstSons(d, n);
|
||||
result := ropeFormat('**$1**', [result]);
|
||||
result := ropef('**$1**', [result]);
|
||||
end;
|
||||
rnInterpretedText: begin
|
||||
result := renderRstSons(d, n);
|
||||
result := ropeFormat('`$1`', [result]);
|
||||
result := ropef('`$1`', [result]);
|
||||
end;
|
||||
rnInlineLiteral: begin
|
||||
inc(d.verbatim);
|
||||
result := renderRstSons(d, n);
|
||||
result := ropeFormat('``$1``', [result]);
|
||||
result := ropef('``$1``', [result]);
|
||||
dec(d.verbatim);
|
||||
end;
|
||||
rnLeaf: begin
|
||||
|
|
@ -582,10 +595,10 @@ begin
|
|||
if n.sons[2] <> nil then
|
||||
result := renderRstSons(d, n.sons[2]);
|
||||
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;
|
||||
rnContents: begin
|
||||
result := ropeFormat('$n$n$1.. contents::', [ind]);
|
||||
result := ropef('$n$n$1.. contents::', [ind]);
|
||||
end;
|
||||
else rawMessage(errCannotRenderX, rstnodeKindToStr[n.kind]);
|
||||
end;
|
||||
|
|
@ -593,7 +606,7 @@ end;
|
|||
|
||||
function renderTocEntry(d: PDoc; const e: TTocEntry): PRope;
|
||||
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]);
|
||||
end;
|
||||
|
||||
|
|
@ -614,24 +627,24 @@ begin
|
|||
break
|
||||
end;
|
||||
if lvl > 1 then
|
||||
result := ropeFormat('<ul class="simple">$1</ul>', [result]);
|
||||
result := ropef('<ul class="simple">$1</ul>', [result]);
|
||||
end;
|
||||
|
||||
function renderImage(d: PDoc; n: PRstNode): PRope;
|
||||
var
|
||||
s: string;
|
||||
begin
|
||||
result := ropeFormat('<img src="$1"', [toRope(getArgument(n))]);
|
||||
result := ropef('<img src="$1"', [toRope(getArgument(n))]);
|
||||
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');
|
||||
if s <> '' then appRopeFormat(result, ' width="$1"', [toRope(s)]);
|
||||
if s <> '' then appf(result, ' width="$1"', [toRope(s)]);
|
||||
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');
|
||||
if s <> '' then appRopeFormat(result, ' alt="$1"', [toRope(s)]);
|
||||
if s <> '' then appf(result, ' alt="$1"', [toRope(s)]);
|
||||
s := getFieldValue(n, 'align');
|
||||
if s <> '' then appRopeFormat(result, ' align="$1"', [toRope(s)]);
|
||||
if s <> '' then appf(result, ' align="$1"', [toRope(s)]);
|
||||
app(result, ' />');
|
||||
if rsonsLen(n) >= 3 then app(result, renderRstToHtml(d, n.sons[2]))
|
||||
end;
|
||||
|
|
@ -644,14 +657,14 @@ var
|
|||
lang: TSourceLanguage;
|
||||
begin
|
||||
m := n.sons[2].sons[0];
|
||||
assert(m.kind = rnLeaf);
|
||||
if (m.kind <> rnLeaf) then InternalError('renderCodeBlock');
|
||||
result := nil;
|
||||
langstr := strip(getArgument(n));
|
||||
if langstr = '' then lang := langNimrod // default language
|
||||
else lang := getSourceLanguage(langstr);
|
||||
if lang = langNone then begin
|
||||
rawMessage(warnLanguageXNotSupported, langstr);
|
||||
result := ropeFormat('<pre>$1</pre>', [toRope(m.text)])
|
||||
result := ropef('<pre>$1</pre>', [toRope(m.text)])
|
||||
end
|
||||
else begin
|
||||
initGeneralTokenizer(g, m.text);
|
||||
|
|
@ -660,15 +673,17 @@ begin
|
|||
case g.kind of
|
||||
gtEof: break;
|
||||
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
|
||||
appRopeFormat(result, '<span class="$2">$1</span>',
|
||||
[toRope(ncopy(m.text, g.start+strStart, g.len+g.start)),
|
||||
appf(result, '<span class="$2">$1</span>',
|
||||
[toRope(ncopy(m.text, g.start+strStart,
|
||||
g.len+g.start-1+strStart)),
|
||||
toRope(tokenClassToStr[g.kind])]);
|
||||
end;
|
||||
end;
|
||||
deinitGeneralTokenizer(g);
|
||||
if result <> nil then result := ropeFormat('<pre>$1</pre>', [result]);
|
||||
if result <> nil then result := ropef('<pre>$1</pre>', [result]);
|
||||
end
|
||||
end;
|
||||
|
||||
|
|
@ -719,10 +734,10 @@ begin
|
|||
rnDescription: outer := '<td align="left">$1</td>$n';
|
||||
rnOption,
|
||||
rnOptionString,
|
||||
rnOptionArgument: assert(false);
|
||||
rnOptionArgument: InternalError('renderRstToHtml');
|
||||
|
||||
rnLiteralBlock: outer := '<pre>$1</pre>'+nl;
|
||||
rnQuotedLiteralBlock: assert(false);
|
||||
rnQuotedLiteralBlock: InternalError('renderRstToHtml');
|
||||
|
||||
rnLineBlock: outer := '<p>$1</p>';
|
||||
rnLineBlockItem: outer := '$1<br />';
|
||||
|
|
@ -735,19 +750,19 @@ begin
|
|||
rnTableDataCell: outer := '<td>$1</td>';
|
||||
rnTableHeaderCell: outer := '<th>$1</th>';
|
||||
|
||||
rnLabel: assert(false); // used for footnotes and other things
|
||||
rnFootnote: assert(false); // a footnote
|
||||
rnLabel: InternalError('renderRstToHtml'); // used for footnotes and other
|
||||
rnFootnote: InternalError('renderRstToHtml'); // a footnote
|
||||
|
||||
rnCitation: assert(false); // similar to footnote
|
||||
rnCitation: InternalError('renderRstToHtml'); // similar to footnote
|
||||
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))]);
|
||||
exit
|
||||
end;
|
||||
rnStandaloneHyperlink:
|
||||
outer := '<a class="reference external" href="$1">$1</a>';
|
||||
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[1])]);
|
||||
exit
|
||||
|
|
@ -766,7 +781,7 @@ begin
|
|||
|
||||
// Inline markup:
|
||||
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[1])]);
|
||||
exit
|
||||
|
|
@ -798,7 +813,7 @@ begin
|
|||
d.meta[metaTitle] := renderRstToHtml(d, n.sons[0]);
|
||||
exit
|
||||
end;
|
||||
else assert(false);
|
||||
else InternalError('renderRstToHtml');
|
||||
end;
|
||||
result := renderAux(d, n, outer, inner);
|
||||
end;
|
||||
|
|
@ -809,11 +824,12 @@ var
|
|||
begin
|
||||
if n = nil then exit;
|
||||
case n.kind of
|
||||
nkCommentStmt: app(d.modDesc, genComment(d, n));
|
||||
nkProcDef: genItem(d, n, n.sons[namePos], skProc);
|
||||
nkIteratorDef: genItem(d, n, n.sons[namePos], skIterator);
|
||||
nkMacroDef: genItem(d, n, n.sons[namePos], skMacro);
|
||||
nkTemplateDef: genItem(d, n, n.sons[namePos], skTemplate);
|
||||
nkCommentStmt: app(d.modDesc, genComment(d, n));
|
||||
nkProcDef: genItem(d, n, n.sons[namePos], skProc);
|
||||
nkIteratorDef: genItem(d, n, n.sons[namePos], skIterator);
|
||||
nkMacroDef: genItem(d, n, n.sons[namePos], skMacro);
|
||||
nkTemplateDef: genItem(d, n, n.sons[namePos], skTemplate);
|
||||
nkConverterDef: genItem(d, n, n.sons[namePos], skConverter);
|
||||
nkVarSection: begin
|
||||
for i := 0 to sonsLen(n)-1 do
|
||||
genItem(d, n.sons[i], n.sons[i].sons[0], skVar);
|
||||
|
|
@ -860,13 +876,15 @@ var
|
|||
begin
|
||||
j := 0;
|
||||
toc := renderTocEntries(d, j, 1);
|
||||
code := nil;
|
||||
content := nil;
|
||||
title := nil;
|
||||
for i := low(TSymKind) to high(TSymKind) do begin
|
||||
genSection(d, i);
|
||||
app(toc, d.toc[i]);
|
||||
end;
|
||||
if toc <> nil then
|
||||
toc := ropeFormatNamedVars(getConfigVar('doc.toc'), ['content'], [toc]);
|
||||
code := nil;
|
||||
for i := low(TSymKind) to high(TSymKind) do
|
||||
app(code, d.section[i]);
|
||||
if d.meta[metaTitle] <> nil then
|
||||
|
|
@ -918,13 +936,16 @@ var
|
|||
filen: string;
|
||||
d: PDoc;
|
||||
rst: PRstNode;
|
||||
code: PRope;
|
||||
begin
|
||||
filen := appendFileExt(filename, 'txt');
|
||||
d := newDocumentor(filen);
|
||||
initIndexFile(d);
|
||||
rst := rstParse(readFile(filen), false, filen, 0, 1, d.hasToc);
|
||||
d.modDesc := renderRstToHtml(d, rst);
|
||||
writeRope(genHtmlFile(d), getOutFile(filename, HtmlExt));
|
||||
code := genHtmlFile(d);
|
||||
assert(ropeInvariant(code));
|
||||
writeRope(code, getOutFile(filename, HtmlExt));
|
||||
generateIndex(d);
|
||||
end;
|
||||
|
||||
|
|
|
|||
1869
nim/ecmasgen.pas
Normal file
1869
nim/ecmasgen.pas
Normal file
File diff suppressed because it is too large
Load diff
1258
nim/eval.pas
1258
nim/eval.pas
File diff suppressed because it is too large
Load diff
156
nim/extccomp.pas
156
nim/extccomp.pas
|
|
@ -15,7 +15,9 @@ interface
|
|||
{$include 'config.inc'}
|
||||
|
||||
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
|
||||
TSystemCC = (ccNone, ccGcc, ccLLVM_Gcc, ccLcc, ccBcc, ccDmc, ccWcc, ccVcc,
|
||||
|
|
@ -27,15 +29,17 @@ type
|
|||
hasCpp // CC is/contains a C++ compiler
|
||||
);
|
||||
TInfoCCProps = set of TInfoCCProp;
|
||||
TInfoCC = record
|
||||
TInfoCC = record{@tuple}
|
||||
name: string; // the short name of the compiler
|
||||
objExt: string; // the compiler's object file extenstion
|
||||
optSpeed: string; // the options for optimization for speed
|
||||
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
|
||||
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
|
||||
debug: string; // flags for debug build
|
||||
pic: string; // command for position independent code
|
||||
|
|
@ -50,10 +54,12 @@ const
|
|||
objExt: 'o'+'';
|
||||
optSpeed: ' -O3 -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';
|
||||
buildDll: ' -mdll';
|
||||
link: 'gcc $options $buildgui $builddll -o $exefile $objfiles';
|
||||
linkerExe: 'gcc';
|
||||
linkTmpl: '$options $buildgui $builddll -o $exefile $objfiles';
|
||||
includeCmd: ' -I';
|
||||
debug: '';
|
||||
pic: '-fPIC';
|
||||
|
|
@ -65,10 +71,12 @@ const
|
|||
objExt: 'o'+'';
|
||||
optSpeed: ' -O3 -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';
|
||||
buildDll: ' -mdll';
|
||||
link: 'llvm-gcc $options $buildgui $builddll -o $exefile $objfiles';
|
||||
linkerExe: 'llvm-gcc';
|
||||
linkTmpl: '$options $buildgui $builddll -o $exefile $objfiles';
|
||||
includeCmd: ' -I';
|
||||
debug: '';
|
||||
pic: '-fPIC';
|
||||
|
|
@ -80,10 +88,12 @@ const
|
|||
objExt: 'obj';
|
||||
optSpeed: ' -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';
|
||||
buildDll: ' -dll';
|
||||
link: 'lcclnk $options $buildgui $builddll -O $exefile $objfiles';
|
||||
linkerExe: 'lcclnk';
|
||||
linkTmpl: '$options $buildgui $builddll -O $exefile $objfiles';
|
||||
includeCmd: ' -I';
|
||||
debug: ' -g5 ';
|
||||
pic: '';
|
||||
|
|
@ -95,10 +105,12 @@ const
|
|||
objExt: 'obj';
|
||||
optSpeed: ' -O2 -6 ';
|
||||
optSize: ' -O1 -6 ';
|
||||
compile: 'bcc32 -c $options $include -o$objfile $file';
|
||||
compilerExe: 'bcc32';
|
||||
compileTmpl: '-c $options $include -o$objfile $file';
|
||||
buildGui: ' -tW';
|
||||
buildDll: ' -tWD';
|
||||
link: 'bcc32 $options $buildgui $builddll -e$exefile $objfiles';
|
||||
linkerExe: 'bcc32';
|
||||
linkTmpl: '$options $buildgui $builddll -e$exefile $objfiles';
|
||||
includeCmd: ' -I';
|
||||
debug: '';
|
||||
pic: '';
|
||||
|
|
@ -110,10 +122,12 @@ const
|
|||
objExt: 'obj';
|
||||
optSpeed: ' -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';
|
||||
buildDll: ' -WD';
|
||||
link: 'dmc $options $buildgui $builddll -o$exefile $objfiles';
|
||||
linkerExe: 'dmc';
|
||||
linkTmpl: '$options $buildgui $builddll -o$exefile $objfiles';
|
||||
includeCmd: ' -I';
|
||||
debug: ' -g ';
|
||||
pic: '';
|
||||
|
|
@ -125,10 +139,12 @@ const
|
|||
objExt: 'obj';
|
||||
optSpeed: ' -ox -on -6 -d0 -fp6 -zW ';
|
||||
optSize: '';
|
||||
compile: 'wcl386 -c $options $include -fo=$objfile $file';
|
||||
compilerExe: 'wcl386';
|
||||
compileTmpl: '-c $options $include -fo=$objfile $file';
|
||||
buildGui: ' -bw';
|
||||
buildDll: ' -bd';
|
||||
link: 'wcl386 $options $buildgui $builddll -fe=$exefile $objfiles ';
|
||||
linkerExe: 'wcl386';
|
||||
linkTmpl: '$options $buildgui $builddll -fe=$exefile $objfiles ';
|
||||
includeCmd: ' -i=';
|
||||
debug: ' -d2 ';
|
||||
pic: '';
|
||||
|
|
@ -140,10 +156,12 @@ const
|
|||
objExt: 'obj';
|
||||
optSpeed: ' /Ogityb2 /G7 /arch:SSE2 ';
|
||||
optSize: ' /O1 /G7 ';
|
||||
compile: 'cl /c $options $include /Fo$objfile $file';
|
||||
compilerExe: 'cl';
|
||||
compileTmpl: '/c $options $include /Fo$objfile $file';
|
||||
buildGui: ' /link /SUBSYSTEM:WINDOWS ';
|
||||
buildDll: ' /LD';
|
||||
link: 'cl $options $builddll /Fe$exefile $objfiles $buildgui';
|
||||
linkerExe: 'cl';
|
||||
linkTmpl: '$options $builddll /Fe$exefile $objfiles $buildgui';
|
||||
includeCmd: ' /I';
|
||||
debug: ' /GZ /Zi ';
|
||||
pic: '';
|
||||
|
|
@ -155,10 +173,12 @@ const
|
|||
objExt: 'o'+'';
|
||||
optSpeed: '';
|
||||
optSize: '';
|
||||
compile: 'tcc -c $options $include -o $objfile $file';
|
||||
compilerExe: 'tcc';
|
||||
compileTmpl: '-c $options $include -o $objfile $file';
|
||||
buildGui: 'UNAVAILABLE!';
|
||||
buildDll: ' -shared';
|
||||
link: 'tcc -o $exefile $options $buildgui $builddll $objfiles';
|
||||
linkerExe: 'tcc';
|
||||
linkTmpl: '-o $exefile $options $buildgui $builddll $objfiles';
|
||||
includeCmd: ' -I';
|
||||
debug: ' -g ';
|
||||
pic: '';
|
||||
|
|
@ -170,10 +190,12 @@ const
|
|||
objExt: 'obj';
|
||||
optSpeed: ' -Ox ';
|
||||
optSize: ' -Os ';
|
||||
compile: 'cc -c $options $include -Fo$objfile $file';
|
||||
compilerExe: 'cc';
|
||||
compileTmpl: '-c $options $include -Fo$objfile $file';
|
||||
buildGui: ' -SUBSYSTEM:WINDOWS';
|
||||
buildDll: ' -DLL';
|
||||
link: 'cc $options $buildgui $builddll -OUT:$exefile $objfiles';
|
||||
linkerExe: 'cc';
|
||||
linkTmpl: '$options $buildgui $builddll -OUT:$exefile $objfiles';
|
||||
includeCmd: ' -I';
|
||||
debug: ' -Zi ';
|
||||
pic: '';
|
||||
|
|
@ -185,10 +207,12 @@ const
|
|||
objExt: 'o'+'';
|
||||
optSpeed: ' -O3 ';
|
||||
optSize: ' -O1 ';
|
||||
compile: 'cc -c $options $include -o $objfile $file';
|
||||
compilerExe: 'cc';
|
||||
compileTmpl: '-c $options $include -o $objfile $file';
|
||||
buildGui: '';
|
||||
buildDll: ' -shared ';
|
||||
link: 'cc -o $exefile $options $buildgui $builddll $objfiles';
|
||||
linkerExe: 'cc';
|
||||
linkTmpl: '-o $exefile $options $buildgui $builddll $objfiles';
|
||||
includeCmd: ' -I';
|
||||
debug: '';
|
||||
pic: '';
|
||||
|
|
@ -199,10 +223,12 @@ const
|
|||
objExt: 'o'+'';
|
||||
optSpeed: ' -O3 ';
|
||||
optSize: ' -Os ';
|
||||
compile: 'icc -c $options $include -o $objfile $file';
|
||||
compilerExe: 'icc';
|
||||
compileTmpl: '-c $options $include -o $objfile $file';
|
||||
buildGui: ' -mwindows';
|
||||
buildDll: ' -mdll';
|
||||
link: 'icc $options $buildgui $builddll -o $exefile $objfiles';
|
||||
linkerExe: 'icc';
|
||||
linkTmpl: '$options $buildgui $builddll -o $exefile $objfiles';
|
||||
includeCmd: ' -I';
|
||||
debug: '';
|
||||
pic: '-fPIC';
|
||||
|
|
@ -213,10 +239,12 @@ const
|
|||
objExt: 'o'+'';
|
||||
optSpeed: ' -O3 -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';
|
||||
buildDll: ' -mdll';
|
||||
link: 'g++ $options $buildgui $builddll -o $exefile $objfiles';
|
||||
linkerExe: 'g++';
|
||||
linkTmpl: '$options $buildgui $builddll -o $exefile $objfiles';
|
||||
includeCmd: ' -I';
|
||||
debug: ' -g ';
|
||||
pic: '-fPIC';
|
||||
|
|
@ -238,6 +266,9 @@ var
|
|||
function completeCFilePath(const cfile: string;
|
||||
createSubDir: Boolean = true): string;
|
||||
|
||||
function getCompileCFileCmd(const cfilename: string;
|
||||
isExternal: bool = false): string;
|
||||
|
||||
procedure addFileToCompile(const filename: string);
|
||||
procedure addExternalFileToCompile(const filename: string);
|
||||
procedure addFileToLink(const filename: string);
|
||||
|
|
@ -260,7 +291,7 @@ procedure setCC(const ccname: string);
|
|||
implementation
|
||||
|
||||
uses
|
||||
nsystem, charsets,
|
||||
charsets,
|
||||
lists, options, ropes, nos, strutils, platform, condsyms;
|
||||
|
||||
var
|
||||
|
|
@ -389,16 +420,13 @@ begin
|
|||
result := cc[c].optSize // use default settings from this file
|
||||
end;
|
||||
|
||||
procedure CompileCFile(const list: TLinkedList;
|
||||
var script: PRope; isExternal: Boolean);
|
||||
function getCompileCFileCmd(const cfilename: string;
|
||||
isExternal: bool = false): string;
|
||||
var
|
||||
it: PStrEntry;
|
||||
compileCmd, cfile, objfile, options, includeCmd, compilePattern: string;
|
||||
cfile, objfile, options, includeCmd, compilePattern: string;
|
||||
c: TSystemCC; // an alias to ccompiler
|
||||
begin
|
||||
c := ccompiler;
|
||||
it := PStrEntry(list.head);
|
||||
|
||||
options := compileOptions;
|
||||
if optCDebug in gGlobalOptions then addStr(options, ' ' + getDebug(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
|
||||
// a workaround of a FPC bug...
|
||||
addStr(includeCmd, libpath);
|
||||
compilePattern := JoinPath(ccompilerpath, cc[c].compile);
|
||||
compilePattern := quoteIfSpaceExists(
|
||||
JoinPath(ccompilerpath, cc[c].compilerExe));
|
||||
end
|
||||
else begin
|
||||
includeCmd := '';
|
||||
compilePattern := cc[c].compile
|
||||
compilePattern := cc[c].compilerExe
|
||||
end;
|
||||
if targetOS = hostOS then
|
||||
cfile := cfilename
|
||||
else
|
||||
cfile := extractFileName(cfilename);
|
||||
|
||||
if not isExternal or (targetOS <> hostOS) then
|
||||
objfile := toObjFile(cfile)
|
||||
else
|
||||
objfile := completeCFilePath(toObjFile(cfile));
|
||||
|
||||
result := compilePattern +{&} ' ' +{&} format(cc[c].compileTmpl,
|
||||
['file', AppendFileExt(cfile, cExt),
|
||||
'objfile', objfile,
|
||||
'options', options,
|
||||
'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:
|
||||
if targetOS = hostOS then
|
||||
cfile := it.data
|
||||
else
|
||||
cfile := extractFileName(it.data);
|
||||
|
||||
if not isExternal or (targetOS <> hostOS) then
|
||||
objfile := toObjFile(cfile)
|
||||
else
|
||||
objfile := completeCFilePath(toObjFile(cfile));
|
||||
|
||||
compileCmd := format(compilePattern,
|
||||
['file', AppendFileExt(cfile, cExt),
|
||||
'objfile', objfile,
|
||||
'options', options,
|
||||
'include', includeCmd
|
||||
]);
|
||||
compileCmd := getCompileCFileCmd(it.data, isExternal);
|
||||
if not (optCompileOnly in gGlobalOptions) then
|
||||
execExternalProgram(compileCmd);
|
||||
if (optGenScript in gGlobalOptions) then begin
|
||||
|
|
@ -469,9 +509,9 @@ begin
|
|||
if not (optNoLinking in gGlobalOptions) then begin
|
||||
// call the linker:
|
||||
if (hostOS <> targetOS) then
|
||||
linkCmd := cc[c].link
|
||||
linkCmd := cc[c].linkerExe
|
||||
else
|
||||
linkCmd := JoinPath(ccompilerpath, cc[c].link);
|
||||
linkCmd := quoteIfSpaceExists(JoinPath(ccompilerpath, cc[c].linkerExe));
|
||||
|
||||
if optGenDynLib in gGlobalOptions then
|
||||
buildDll := cc[c].buildDll
|
||||
|
|
@ -506,12 +546,14 @@ begin
|
|||
it := PStrEntry(it.next);
|
||||
end;
|
||||
|
||||
linkCmd := format(linkCmd, [
|
||||
linkCmd := linkCmd +{&} ' ' +{&} format(cc[c].linkTmpl, [
|
||||
'builddll', builddll,
|
||||
'buildgui', buildgui,
|
||||
'options', linkOptions,
|
||||
'objfiles', objfiles,
|
||||
'exefile', exefile
|
||||
'exefile', exefile,
|
||||
'nimrod', getPrefixDir(),
|
||||
'lib', libpath
|
||||
]);
|
||||
if not (optCompileOnly in gGlobalOptions) then
|
||||
execExternalProgram(linkCmd);
|
||||
|
|
|
|||
175
nim/genhelp.pas
175
nim/genhelp.pas
|
|
@ -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.
|
||||
|
|
@ -60,7 +60,9 @@ type
|
|||
function nextPowerOfTwo(x: int): int;
|
||||
begin
|
||||
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 8);
|
||||
result := result or (result shr 4);
|
||||
|
|
|
|||
|
|
@ -137,6 +137,11 @@ procedure initGeneralTokenizer(var g: TGeneralTokenizer;
|
|||
begin
|
||||
{@ignore} fillChar(g, sizeof(g), 0); {@emit}
|
||||
g.buf := PChar(buf);
|
||||
g.kind := low(TTokenClass);
|
||||
g.start := 0;
|
||||
g.len := 0;
|
||||
g.pos := 0;
|
||||
g.state := low(TTokenClass);
|
||||
end;
|
||||
|
||||
procedure deinitGeneralTokenizer(var g: TGeneralTokenizer);
|
||||
|
|
|
|||
|
|
@ -42,8 +42,9 @@ var
|
|||
j: int;
|
||||
etyp: PType; // enumeration type
|
||||
begin
|
||||
copy := copySym(s, s.owner);
|
||||
copy.ast := s.ast; // BUGFIX
|
||||
//copy := copySym(s, true);
|
||||
//copy.ast := s.ast;
|
||||
copy := s; // do not copy symbols when importing!
|
||||
// check if we have already a symbol of the same name:
|
||||
check := StrTableGet(c.tab.stack[importTablePos], s.name);
|
||||
if check <> nil then begin
|
||||
|
|
@ -55,17 +56,17 @@ begin
|
|||
end;
|
||||
StrTableAdd(c.tab.stack[importTablePos], copy);
|
||||
if s.kind = skType then begin
|
||||
// types are special: we need to copy types but need to
|
||||
// consider private fields
|
||||
etyp := s.typ;
|
||||
if etyp.kind = tyEnum then begin
|
||||
for j := 0 to sonsLen(etyp.n)-1 do begin
|
||||
e := etyp.n.sons[j].sym;
|
||||
assert(e.Kind = skEnumField);
|
||||
rawImportSymbol(c, e)
|
||||
if (e.Kind = skEnumField) then rawImportSymbol(c, e)
|
||||
else InternalError(s.info, 'rawImportSymbol');
|
||||
end
|
||||
end
|
||||
end;
|
||||
end
|
||||
else if s.kind = skConverter then
|
||||
addConverter(c, s);
|
||||
end;
|
||||
|
||||
procedure importSymbol(c: PContext; ident: PNode; fromMod: PSym);
|
||||
|
|
@ -73,18 +74,20 @@ var
|
|||
s, e: PSym;
|
||||
it: TIdentIter;
|
||||
begin
|
||||
assert(ident.kind = nkIdent);
|
||||
if (ident.kind <> nkIdent) then InternalError(ident.info, 'importSymbol');
|
||||
s := StrTableGet(fromMod.tab, ident.ident);
|
||||
if s = nil then
|
||||
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
|
||||
case s.Kind of
|
||||
skProc, skIterator, skMacro, skTemplate: begin
|
||||
// for a overloadable syms add all overloaded routines
|
||||
skProc, skIterator, skMacro, skTemplate, skConverter: begin
|
||||
// for a overloadable syms add all overloaded routines
|
||||
e := InitIdentIter(it, fromMod.tab, s.name);
|
||||
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);
|
||||
e := NextIdentIter(it, fromMod.tab);
|
||||
end
|
||||
|
|
@ -101,8 +104,11 @@ begin
|
|||
s := InitTabIter(i, fromMod.tab);
|
||||
while s <> nil do begin
|
||||
if s.kind <> skModule then begin
|
||||
assert(s.Kind in ExportableSymKinds);
|
||||
rawImportSymbol(c, s); // this is correct!
|
||||
if s.kind <> skEnumField then begin
|
||||
if not (s.Kind in ExportableSymKinds) then
|
||||
InternalError(s.info, 'importAllSymbols');
|
||||
rawImportSymbol(c, s); // this is correct!
|
||||
end
|
||||
end;
|
||||
s := NextIter(i, fromMod.tab)
|
||||
end
|
||||
|
|
@ -129,6 +135,7 @@ var
|
|||
i: int;
|
||||
begin
|
||||
result := n;
|
||||
checkMinSonsLen(n, 2);
|
||||
m := c.ImportModule(getModuleFile(n.sons[0]), c.b);
|
||||
n.sons[0] := newSymNode(m);
|
||||
addDecl(c, m); // add symbol to symbol table of module
|
||||
|
|
@ -140,7 +147,7 @@ var
|
|||
i: int;
|
||||
x: PNode;
|
||||
begin
|
||||
result := newNode(nkStmtList);
|
||||
result := newNodeI(nkStmtList, n.info);
|
||||
for i := 0 to sonsLen(n)-1 do begin
|
||||
x := c.includeFile(getModuleFile(n.sons[i]));
|
||||
x := semStmt(c, x);
|
||||
|
|
|
|||
|
|
@ -21,11 +21,12 @@ type
|
|||
newOwner: PSym;
|
||||
instantiator: TLineInfo;
|
||||
end;
|
||||
PInstClosure = ^TInstantiateClosure;
|
||||
PInstantiateClosure = ^TInstantiateClosure;
|
||||
PInstClosure = PInstantiateClosure;
|
||||
|
||||
function instantiateTree(var c: TInstantiateClosure; t: PNode): PNode; forward;
|
||||
|
||||
function instantiateSym(var c: TInstantiateClosure; sym: PSym): PSym; forward;
|
||||
function instantiateTree(c: PInstantiateClosure; t: PNode): PNode; forward;
|
||||
function instantiateSym(c: PInstantiateClosure; sym: PSym): PSym; forward;
|
||||
function instantiateType(c: PInstantiateClosure; typ: PType): PType; forward;
|
||||
|
||||
function containsGenericTypeIter(t: PType; closure: PObject): bool;
|
||||
begin
|
||||
|
|
@ -37,35 +38,58 @@ begin
|
|||
result := iterOverType(t, containsGenericTypeIter, nil);
|
||||
end;
|
||||
|
||||
|
||||
function instantiateTypeMutator(typ: PType; c: PObject): PType;
|
||||
function instTypeNode(c: PInstantiateClosure; n: PNode): PNode;
|
||||
var
|
||||
i: int;
|
||||
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 containsGenericType(typ) then begin
|
||||
result := copyType(typ, PInstClosure(c).newOwner);
|
||||
idTablePut(PInstClosure(c).mapping, typ, result)
|
||||
result := copyType(typ, c.newOwner);
|
||||
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
|
||||
else
|
||||
result := typ;
|
||||
if result.Kind in GenericTypes then begin
|
||||
liMessage(PInstClosure(c).instantiator, errCannotInstantiateX,
|
||||
liMessage(c.instantiator, errCannotInstantiateX,
|
||||
TypeToString(typ, preferName));
|
||||
end
|
||||
else if result.kind = tyVar then begin
|
||||
if result.sons[0].kind = tyVar then
|
||||
liMessage(c.instantiator, errVarVarTypeNotAllowed);
|
||||
end;
|
||||
end;
|
||||
|
||||
function instantiateType(var c: TInstantiateClosure; typ: PType): PType;
|
||||
begin
|
||||
result := mutateType(typ, instantiateTypeMutator, {@cast}PObject(addr(c)));
|
||||
end;
|
||||
|
||||
function instantiateSym(var c: TInstantiateClosure; sym: PSym): PSym;
|
||||
function instantiateSym(c: PInstantiateClosure; sym: PSym): PSym;
|
||||
begin
|
||||
if sym = nil then begin result := nil; exit end; // BUGFIX
|
||||
result := PSym(idTableGet(c.mapping, sym));
|
||||
if (result = nil) 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;
|
||||
include(result.flags, sfIsCopy);
|
||||
idTablePut(c.mapping, sym, result); // BUGFIX
|
||||
|
|
@ -83,7 +107,7 @@ begin
|
|||
end
|
||||
end;
|
||||
|
||||
function instantiateTree(var c: TInstantiateClosure; t: PNode): PNode;
|
||||
function instantiateTree(c: PInstantiateClosure; t: PNode): PNode;
|
||||
var
|
||||
len, i: int;
|
||||
begin
|
||||
|
|
@ -124,7 +148,8 @@ begin
|
|||
q := n.sons[i].sym;
|
||||
s := newSym(skType, q.name, getCurrOwner(c));
|
||||
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);
|
||||
s.typ := t;
|
||||
addDecl(c, s);
|
||||
|
|
@ -138,7 +163,8 @@ var
|
|||
begin
|
||||
result := nil;
|
||||
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;
|
||||
if genericSym.id = a.id then begin
|
||||
b := c.generics.sons[i].sons[1].sym;
|
||||
|
|
@ -173,8 +199,8 @@ var
|
|||
n: PNode;
|
||||
begin
|
||||
oldP := c.p; // restore later
|
||||
result := copySym(fn, getCurrOwner(c));
|
||||
result.id := getId();
|
||||
result := copySym(fn);
|
||||
result.owner := getCurrOwner(c);
|
||||
n := copyTree(fn.ast);
|
||||
result.ast := n;
|
||||
pushOwner(c, result);
|
||||
|
|
@ -202,7 +228,7 @@ begin
|
|||
addDecl(c, result);
|
||||
if n.sons[codePos] <> nil then begin
|
||||
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);
|
||||
addResultNode(c, n);
|
||||
end;
|
||||
|
|
@ -221,8 +247,12 @@ end;
|
|||
function generateTypeInstance(p: PContext; const pt: TIdTable;
|
||||
const instantiator: TLineInfo; t: PType): PType;
|
||||
var
|
||||
c: TInstantiateClosure;
|
||||
c: PInstantiateClosure;
|
||||
begin
|
||||
new(c);
|
||||
{@ignore}
|
||||
fillChar(c^, sizeof(c^), 0);
|
||||
{@emit}
|
||||
c.mapping := pt; // making a copy is not necessary
|
||||
c.fn := nil;
|
||||
c.instantiator := instantiator;
|
||||
|
|
|
|||
|
|
@ -227,7 +227,7 @@ begin
|
|||
L.linenumber := 1; // lines start at 1
|
||||
L.fileOpened := false;
|
||||
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;
|
||||
end
|
||||
else
|
||||
|
|
|
|||
|
|
@ -12,8 +12,7 @@
|
|||
function getSymRepr(s: PSym): string;
|
||||
begin
|
||||
case s.kind of
|
||||
skProc, skConverter, skIterator:
|
||||
result := getProcHeader(s);
|
||||
skProc, skConverter, skIterator: result := getProcHeader(s);
|
||||
else result := s.name.s
|
||||
end
|
||||
end;
|
||||
|
|
@ -24,7 +23,7 @@ var
|
|||
s: PSym;
|
||||
begin
|
||||
// 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]);
|
||||
while s <> nil do begin
|
||||
if sfForward in s.flags then
|
||||
|
|
@ -59,7 +58,8 @@ procedure addOverloadableSymAt(c: PContext; fn: PSym; at: Natural);
|
|||
var
|
||||
check: PSym;
|
||||
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);
|
||||
if (check <> nil) and (check.Kind <> fn.kind) then
|
||||
liMessage(fn.info, errAttemptToRedefine, fn.Name.s);
|
||||
|
|
@ -70,7 +70,7 @@ procedure AddInterfaceDeclAux(c: PContext; sym: PSym);
|
|||
begin
|
||||
if (sfInInterface in sym.flags) then begin
|
||||
// add to interface:
|
||||
assert(c.module <> nil);
|
||||
if c.module = nil then InternalError(sym.info, 'AddInterfaceDeclAux');
|
||||
StrTableAdd(c.module.tab, sym);
|
||||
end;
|
||||
if getCurrOwner(c).kind = skModule then
|
||||
|
|
@ -92,12 +92,21 @@ end;
|
|||
function lookUp(c: PContext; n: PNode): PSym;
|
||||
// Looks up a symbol. Generates an error in case of nil.
|
||||
begin
|
||||
if n.kind = nkAccQuoted then result := lookup(c, n.sons[0])
|
||||
else begin
|
||||
assert(n.kind = nkIdent);
|
||||
result := SymtabGet(c.Tab, n.ident);
|
||||
if result = nil then liMessage(n.info, errUndeclaredIdentifier, n.ident.s);
|
||||
include(result.flags, sfUsed);
|
||||
case n.kind of
|
||||
nkAccQuoted: result := lookup(c, n.sons[0]);
|
||||
nkSym: begin
|
||||
result := SymtabGet(c.Tab, n.sym.name);
|
||||
if result = nil then
|
||||
liMessage(n.info, errUndeclaredIdentifier, n.sym.name.s);
|
||||
include(result.flags, sfUsed);
|
||||
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;
|
||||
|
||||
|
|
@ -115,6 +124,14 @@ begin
|
|||
and StrTableContains(c.AmbigiousSymbols, result) then
|
||||
liMessage(n.info, errUseQualifier, n.ident.s)
|
||||
end;
|
||||
nkSym: begin
|
||||
result := SymtabGet(c.Tab, n.sym.name);
|
||||
if result = nil then
|
||||
liMessage(n.info, errUndeclaredIdentifier, n.sym.name.s)
|
||||
else if ambigiousCheck
|
||||
and StrTableContains(c.AmbigiousSymbols, result) then
|
||||
liMessage(n.info, errUseQualifier, n.sym.name.s)
|
||||
end;
|
||||
nkDotExpr, nkQualified: begin
|
||||
result := nil;
|
||||
m := qualifiedLookUp(c, n.sons[0], false);
|
||||
|
|
@ -165,6 +182,15 @@ begin
|
|||
result := InitIdentIter(o.it, c.tab.stack[o.stackPtr], n.ident);
|
||||
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
|
||||
o.mode := oimOtherModule;
|
||||
o.m := qualifiedLookUp(c, n.sons[0], false);
|
||||
|
|
@ -199,7 +225,8 @@ begin
|
|||
while (result = nil) do begin
|
||||
dec(o.stackPtr);
|
||||
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
|
||||
else result := nil;
|
||||
|
|
|
|||
31
nim/main.pas
31
nim/main.pas
|
|
@ -17,7 +17,8 @@ interface
|
|||
uses
|
||||
nsystem, strutils, ast, astalgo, scanner, pnimsyn, rnimsyn, options, msgs,
|
||||
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);
|
||||
|
||||
|
|
@ -109,7 +110,9 @@ begin
|
|||
// compile the module
|
||||
// XXX: here caching could be implemented
|
||||
result := compileModule(filename, backend, false, false);
|
||||
end;
|
||||
end
|
||||
else if sfSystemModule in result.flags then
|
||||
liMessage(result.info, errAttemptToRedefine, result.Name.s);
|
||||
end;
|
||||
|
||||
function CompileModule(const filename: string; backend: PBackend;
|
||||
|
|
@ -131,8 +134,8 @@ begin
|
|||
openScope(c.tab); // scope for imported symbols
|
||||
SymTabAdd(c.tab, result);
|
||||
if not isSystemFile then begin
|
||||
importAllSymbols(c, magicsys.SystemModule);
|
||||
SymTabAdd(c.tab, magicsys.SystemModule); // import the "System" identifier
|
||||
importAllSymbols(c, magicsys.SystemModule);
|
||||
SymTabAdd(c.tab, newIsMainModuleSym(result, isMainFile));
|
||||
end
|
||||
else begin
|
||||
|
|
@ -142,7 +145,6 @@ begin
|
|||
end;
|
||||
{@discard} semModule(c, ast);
|
||||
rawCloseScope(c.tab); // imported symbols; don't check for unused ones!
|
||||
// XXX: compile the generated generic procs!
|
||||
msgCompiled(result.name.s);
|
||||
end;
|
||||
|
||||
|
|
@ -161,8 +163,8 @@ var
|
|||
|
||||
procedure addDependencyAux(importing, imported: PSym);
|
||||
begin
|
||||
appRopeFormat(gDotGraph, '$1 -> $2;$n', [toRope(importing.name.s),
|
||||
toRope(imported.name.s)]);
|
||||
appf(gDotGraph, '$1 -> $2;$n', [toRope(importing.name.s),
|
||||
toRope(imported.name.s)]);
|
||||
// s1 -> s2_4 [label="[0-9]"];
|
||||
end;
|
||||
|
||||
|
|
@ -193,7 +195,7 @@ end;
|
|||
procedure generateDot(const project: string);
|
||||
begin
|
||||
writeRope(
|
||||
ropeFormat('digraph $1 {$n$2}$n', [
|
||||
ropef('digraph $1 {$n$2}$n', [
|
||||
toRope(changeFileExt(extractFileName(project), '')), gDotGraph]),
|
||||
changeFileExt(project, 'dot') );
|
||||
end;
|
||||
|
|
@ -257,6 +259,14 @@ begin
|
|||
extccomp.CallCCompiler(changeFileExt(filename, ''));
|
||||
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);
|
||||
|
|
@ -279,7 +289,7 @@ begin
|
|||
for i := 0 to sonsLen(n)-1 do begin
|
||||
exSymbol(n.sons[i].sons[0]);
|
||||
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])
|
||||
end
|
||||
end;
|
||||
|
|
@ -406,6 +416,11 @@ begin
|
|||
wantFile(filename);
|
||||
CommandCompileToC(filename);
|
||||
end;
|
||||
wCompileToEcmaScript: begin
|
||||
gCmd := cmdCompileToEcmaScript;
|
||||
wantFile(filename);
|
||||
CommandCompileToEcmaScript(filename);
|
||||
end;
|
||||
wPretty: begin
|
||||
// compile means compileToC currently
|
||||
gCmd := cmdPretty;
|
||||
|
|
|
|||
73
nim/msgs.pas
73
nim/msgs.pas
|
|
@ -74,10 +74,6 @@ type
|
|||
errTokenExpected,
|
||||
errStringAfterIncludeExpected,
|
||||
errRecursiveInclude,
|
||||
errAtIfExpected,
|
||||
errAtIfExpectedBeforeElse,
|
||||
errAtIfExpectedBeforeElif,
|
||||
errAtEndExpected,
|
||||
errOnOrOffExpected,
|
||||
errNoneSpeedOrSizeExpected,
|
||||
errInvalidPragma,
|
||||
|
|
@ -186,7 +182,7 @@ type
|
|||
errSizeTooBig,
|
||||
errSetTooBig,
|
||||
errBaseTypeMustBeOrdinal,
|
||||
errInheritanceOnlyWithObjects,
|
||||
errInheritanceOnlyWithNonFinalObjects,
|
||||
errInheritanceOnlyWithEnums,
|
||||
errIllegalRecursionInTypeX,
|
||||
errCannotInstantiateX,
|
||||
|
|
@ -267,6 +263,20 @@ type
|
|||
errWhitespaceExpected,
|
||||
errXisNoValidIndexFile,
|
||||
errCannotRenderX,
|
||||
errVarVarTypeNotAllowed,
|
||||
errIsExpectsTwoArguments,
|
||||
errIsExpectsObjectTypes,
|
||||
errXcanNeverBeOfThisSubtype,
|
||||
errTooManyIterations,
|
||||
errCannotInterpretNodeX,
|
||||
errFieldXNotFound,
|
||||
errInvalidConversionFromTypeX,
|
||||
errAssertionFailed,
|
||||
errCannotGenerateCodeForX,
|
||||
errXNeedsReturnType,
|
||||
errXRequiresOneArgument,
|
||||
errUnhandledExceptionX,
|
||||
errCyclicTree,
|
||||
errUser,
|
||||
warnCannotOpenFile,
|
||||
warnOctalEscape,
|
||||
|
|
@ -291,6 +301,8 @@ type
|
|||
hintMo2FileInvalid,
|
||||
hintModuleHasChanged,
|
||||
hintCannotOpenMo2File,
|
||||
hintQuitCalled,
|
||||
hintProcessing,
|
||||
hintUser);
|
||||
|
||||
const
|
||||
|
|
@ -310,7 +322,7 @@ const
|
|||
'invalid token: $1',
|
||||
'line too long',
|
||||
'$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',
|
||||
'closing '']'' expected, but end of file reached',
|
||||
'missing final ''',
|
||||
|
|
@ -319,10 +331,6 @@ const
|
|||
'''$1'' expected',
|
||||
'string after ''include'' expected',
|
||||
'recursive include file: ''$1''',
|
||||
'''@if'' expected',
|
||||
'''@if'' expected before ''@else''',
|
||||
'''@if'' expected before ''@elif''',
|
||||
'''@end'' expected',
|
||||
'''on'' or ''off'' expected',
|
||||
'''none'', ''speed'' or ''size'' expected',
|
||||
'invalid pragma',
|
||||
|
|
@ -431,12 +439,12 @@ const
|
|||
'computing the type''s size produced an overflow',
|
||||
'set is too large',
|
||||
'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',
|
||||
'illegal recursion in type ''$1''',
|
||||
'cannot instantiate: ''$1''',
|
||||
'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: got (',
|
||||
'but expected one of: ',
|
||||
|
|
@ -512,6 +520,20 @@ const
|
|||
'whitespace expected, got ''$1''',
|
||||
'''$1'' is no valid index file',
|
||||
'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',
|
||||
'cannot open ''$1'' [CannotOpenFile]',
|
||||
'octal escape sequences do not exist; leading zero is ignored [OctalEscape]',
|
||||
|
|
@ -536,6 +558,8 @@ const
|
|||
'mo2 file ''$1'' is invalid [Mo2FileInvalid]',
|
||||
'module ''$1'' has been changed [ModuleHasChanged]',
|
||||
'mo2 file ''$1'' does not exist [CannotOpenMo2File]',
|
||||
'quit() called [QuitCalled]',
|
||||
'processing [Processing]',
|
||||
'$1 [User]'
|
||||
);
|
||||
const
|
||||
|
|
@ -556,7 +580,7 @@ const
|
|||
'User'
|
||||
);
|
||||
const
|
||||
HintsToStr: array [0..9] of string = (
|
||||
HintsToStr: array [0..11] of string = (
|
||||
'Success',
|
||||
'LineTooLong',
|
||||
'XDeclaredButNotUsed',
|
||||
|
|
@ -566,6 +590,8 @@ const
|
|||
'Mo2FileInvalid',
|
||||
'ModuleHasChanged',
|
||||
'CannotOpenMo2File',
|
||||
'QuitCalled',
|
||||
'Processing',
|
||||
'User'
|
||||
);
|
||||
//[[[end]]]
|
||||
|
|
@ -593,12 +619,7 @@ type
|
|||
fileIndex: int32;
|
||||
end;
|
||||
|
||||
const
|
||||
UnknownLineInfo: TLineInfo = (
|
||||
line: -1;
|
||||
col: -1;
|
||||
fileIndex: -1;
|
||||
);
|
||||
function UnknownLineInfo(): TLineInfo;
|
||||
|
||||
var
|
||||
gNotes: TNoteKinds = [low(TNoteKind)..high(TNoteKind)];
|
||||
|
|
@ -649,6 +670,13 @@ procedure popInfoContext;
|
|||
|
||||
implementation
|
||||
|
||||
function UnknownLineInfo(): TLineInfo;
|
||||
begin
|
||||
result.line := -1;
|
||||
result.col := -1;
|
||||
result.fileIndex := -1;
|
||||
end;
|
||||
|
||||
{@ignore}
|
||||
var
|
||||
filenames: array of string;
|
||||
|
|
@ -782,12 +810,13 @@ end;
|
|||
procedure handleError(const msg: TMsgKind);
|
||||
begin
|
||||
if (msg >= fatalMin) and (msg <= fatalMax) then begin
|
||||
assert(false); halt(1)
|
||||
if optVerbose in gGlobalOptions then assert(false);
|
||||
halt(1)
|
||||
end;
|
||||
if (msg >= errMin) and (msg <= errMax) then begin
|
||||
inc(gErrorCounter);
|
||||
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
|
||||
end
|
||||
end
|
||||
|
|
@ -797,7 +826,7 @@ procedure writeContext;
|
|||
var
|
||||
i: int;
|
||||
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]),
|
||||
coordToStr(msgContext[i].line),
|
||||
coordToStr(msgContext[i].col),
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ var
|
|||
|
||||
procedure doEnd(var L: TLexer; tok: PToken);
|
||||
begin
|
||||
if high(condStack) < 0 then lexMessage(L, errAtIfExpected);
|
||||
if high(condStack) < 0 then lexMessage(L, errTokenExpected, '@if');
|
||||
ppGetTok(L, tok); // skip 'end'
|
||||
setLength(condStack, high(condStack))
|
||||
end;
|
||||
|
|
@ -114,7 +114,7 @@ procedure jumpToDirective(var L: TLexer; tok: PToken; dest: TJumpDest); forward;
|
|||
procedure doElse(var L: TLexer; tok: PToken);
|
||||
begin
|
||||
if high(condStack) < 0 then
|
||||
lexMessage(L, errAtIfExpectedBeforeElse);
|
||||
lexMessage(L, errTokenExpected, '@if');
|
||||
ppGetTok(L, tok);
|
||||
if tok.tokType = tkColon then ppGetTok(L, tok);
|
||||
if condStack[high(condStack)] then
|
||||
|
|
@ -126,7 +126,7 @@ var
|
|||
res: bool;
|
||||
begin
|
||||
if high(condStack) < 0 then
|
||||
lexMessage(L, errAtIfExpectedBeforeElif);
|
||||
lexMessage(L, errTokenExpected, '@if');
|
||||
res := EvalppIf(L, tok);
|
||||
if condStack[high(condStack)] or not res then
|
||||
jumpToDirective(L, tok, jdElseEndif)
|
||||
|
|
@ -168,7 +168,7 @@ begin
|
|||
ppGetTok(L, tok)
|
||||
end
|
||||
else if tok.tokType = tkEof then
|
||||
lexMessage(L, errAtEndExpected)
|
||||
lexMessage(L, errTokenExpected, '@end')
|
||||
else
|
||||
ppGetTok(L, tok)
|
||||
end
|
||||
|
|
@ -303,7 +303,7 @@ begin
|
|||
while tok.tokType <> tkEof do
|
||||
parseAssignment(L, tok);
|
||||
if length(condStack) > 0 then
|
||||
lexMessage(L, errAtEndExpected);
|
||||
lexMessage(L, errTokenExpected, '@end');
|
||||
closeLexer(L)
|
||||
end
|
||||
end;
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
// See the file "copying.txt", included in this
|
||||
// distribution, for details about the copyright.
|
||||
//
|
||||
program nim;
|
||||
program nimrod;
|
||||
|
||||
{$include 'config.inc'}
|
||||
{@ignore}
|
||||
|
|
@ -18,39 +18,37 @@ program nim;
|
|||
uses
|
||||
nsystem,
|
||||
charsets, sysutils, commands, scanner, condsyms, options, msgs, nversion,
|
||||
nimconf, ropes, extccomp, strutils, nos, platform, main;
|
||||
nimconf, ropes, extccomp, strutils, nos, platform, main, parseopt;
|
||||
|
||||
var
|
||||
arguments: string = ''; // the arguments to be passed to the program that
|
||||
// should be run
|
||||
cmdLineInfo: TLineInfo;
|
||||
|
||||
function ProcessCmdLine(pass: TCmdLinePass): string;
|
||||
procedure ProcessCmdLine(pass: TCmdLinePass; var command, filename: string);
|
||||
var
|
||||
i, paramCounter: int;
|
||||
param: string;
|
||||
p: TOptParser;
|
||||
begin
|
||||
i := 1;
|
||||
result := '';
|
||||
paramCounter := paramCount();
|
||||
while i <= paramCounter do begin
|
||||
param := ParamStr(i);
|
||||
if param[strStart] = '-' then begin
|
||||
commands.ProcessCommand(param, pass);
|
||||
p := parseopt.init();
|
||||
while true do begin
|
||||
parseopt.next(p);
|
||||
case p.kind of
|
||||
cmdEnd: break;
|
||||
cmdLongOption, cmdShortOption:
|
||||
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
|
||||
else if i > 1 then begin
|
||||
result := unixToNativePath(param); // BUGFIX for portable build scripts
|
||||
options.compilerArgs := i;
|
||||
break // do not process the arguments
|
||||
end;
|
||||
Inc(i)
|
||||
end;
|
||||
inc(i); // skip program file
|
||||
// collect the arguments:
|
||||
if pass = passCmd2 then begin
|
||||
while i <= paramCounter do begin
|
||||
arguments := arguments + ' ' +{&} paramStr(i);
|
||||
inc(i)
|
||||
end;
|
||||
arguments := getRestOfCommandLine(p);
|
||||
if not (optRun in gGlobalOptions) and (arguments <> '') then
|
||||
rawMessage(errArgsNeedRunOption);
|
||||
end
|
||||
|
|
@ -58,42 +56,36 @@ end;
|
|||
|
||||
procedure HandleCmdLine;
|
||||
var
|
||||
inp: string;
|
||||
command, filename: string;
|
||||
begin
|
||||
if paramCount() = 0 then
|
||||
writeCommandLineUsage()
|
||||
else begin
|
||||
// Process command line arguments:
|
||||
inp := ProcessCmdLine(passCmd1);
|
||||
if inp <> '' then begin
|
||||
command := '';
|
||||
filename := '';
|
||||
ProcessCmdLine(passCmd1, command, filename);
|
||||
if filename <> '' then begin
|
||||
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
|
||||
// command line can overwite the config file's settings
|
||||
extccomp.initVars();
|
||||
inp := ProcessCmdLine(passCmd2);
|
||||
command := '';
|
||||
filename := '';
|
||||
ProcessCmdLine(passCmd2, command, filename);
|
||||
end;
|
||||
MainCommand(paramStr(1), inp);
|
||||
MainCommand(command, filename);
|
||||
if (gCmd <> cmdInterpret) and (msgs.gErrorCounter = 0) then
|
||||
rawMessage(hintSuccess);
|
||||
if optRun in gGlobalOptions then
|
||||
execExternalProgram(changeFileExt(inp, '') +{&} arguments)
|
||||
execExternalProgram(changeFileExt(filename, '') +{&} ' ' +{&} arguments)
|
||||
end
|
||||
end;
|
||||
|
||||
{@ignore}
|
||||
var
|
||||
Saved8087CW: Word;
|
||||
{@emit}
|
||||
begin
|
||||
{@ignore}
|
||||
Saved8087CW := Default8087CW;
|
||||
Set8087CW($133f); // Disable all fpu exceptions
|
||||
{@emit}
|
||||
cmdLineInfo := newLineInfo('command line', -1, -1);
|
||||
condsyms.InitDefines();
|
||||
HandleCmdLine();
|
||||
{@ignore}
|
||||
Set8087CW(Saved8087CW);
|
||||
{@emit}
|
||||
halt(options.gExitcode);
|
||||
end.
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ function inSet(s: PNode; const elem: PNode): Boolean;
|
|||
var
|
||||
i: int;
|
||||
begin
|
||||
assert(s.kind in [nkSetConstr, nkConstSetConstr]);
|
||||
if s.kind <> nkCurly then InternalError(s.info, 'inSet');
|
||||
for i := 0 to sonsLen(s)-1 do
|
||||
if s.sons[i].kind = nkRange then begin
|
||||
if leValue(s.sons[i].sons[0], elem)
|
||||
|
|
@ -95,7 +95,7 @@ function SomeInSet(s: PNode; const a, b: PNode): Boolean;
|
|||
var
|
||||
i: int;
|
||||
begin
|
||||
assert(s.kind in [nkSetConstr, nkConstSetConstr]);
|
||||
if s.kind <> nkCurly then InternalError(s.info, 'SomeInSet');
|
||||
for i := 0 to sonsLen(s)-1 do
|
||||
if s.sons[i].kind = nkRange then begin
|
||||
if leValue(s.sons[i].sons[0], b)
|
||||
|
|
@ -142,7 +142,7 @@ var
|
|||
begin
|
||||
elemType := settype.sons[0];
|
||||
first := firstOrd(elemType);
|
||||
result := newNode(nkConstSetConstr);
|
||||
result := newNode(nkCurly);
|
||||
result.typ := settype;
|
||||
result.info := info;
|
||||
|
||||
|
|
@ -244,7 +244,7 @@ function SetHasRange(s: PNode): Boolean;
|
|||
var
|
||||
i: int;
|
||||
begin
|
||||
assert(s.kind in [nkSetConstr, nkConstSetConstr]);
|
||||
if s.kind <> nkCurly then InternalError(s.info, 'SetHasRange');
|
||||
for i := 0 to sonsLen(s)-1 do
|
||||
if s.sons[i].kind = nkRange then begin
|
||||
result := true; exit
|
||||
|
|
|
|||
35
nim/nos.pas
35
nim/nos.pas
|
|
@ -22,8 +22,8 @@ uses
|
|||
{$ifdef mswindows}
|
||||
windows,
|
||||
{$else}
|
||||
unix,
|
||||
dos,
|
||||
unix,
|
||||
{$endif}
|
||||
strutils,
|
||||
nsystem;
|
||||
|
|
@ -83,6 +83,14 @@ function sameFile(const path1, path2: string): boolean;
|
|||
|
||||
implementation
|
||||
|
||||
function UnixToNativePath(const path: string): string;
|
||||
begin
|
||||
if dirSep <> '/' then
|
||||
result := replaceStr(path, '/', dirSep)
|
||||
else
|
||||
result := path;
|
||||
end;
|
||||
|
||||
function expandFilename(filename: string): string;
|
||||
begin
|
||||
result := sysutils.expandFilename(filename)
|
||||
|
|
@ -90,16 +98,8 @@ end;
|
|||
|
||||
function sameFile(const path1, path2: string): boolean;
|
||||
begin
|
||||
result := cmpIgnoreCase(expandFilename(path1),
|
||||
expandFilename(path2)) = 0;
|
||||
end;
|
||||
|
||||
function UnixToNativePath(const path: string): string;
|
||||
begin
|
||||
if dirSep <> '/' then
|
||||
result := replaceStr(path, '/', dirSep)
|
||||
else
|
||||
result := path;
|
||||
result := cmpIgnoreCase(expandFilename(UnixToNativePath(path1)),
|
||||
expandFilename(UnixToNativePath(path2))) = 0;
|
||||
end;
|
||||
|
||||
procedure createDir(dir: string);
|
||||
|
|
@ -417,8 +417,9 @@ begin
|
|||
SI.hStdError := GetStdHandle(STD_ERROR_HANDLE);
|
||||
SI.hStdInput := GetStdHandle(STD_INPUT_HANDLE);
|
||||
SI.hStdOutput := GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
if not Windows.CreateProcess(nil, PChar(cmd), nil, nil, true,
|
||||
NORMAL_PRIORITY_CLASS, Windows.GetEnvironmentStrings(), nil, SI, ProcInfo)
|
||||
if not Windows.CreateProcess(nil, PChar(cmd), nil, nil, false,
|
||||
NORMAL_PRIORITY_CLASS, nil {Windows.GetEnvironmentStrings()},
|
||||
nil, SI, ProcInfo)
|
||||
then
|
||||
result := getLastError()
|
||||
else begin
|
||||
|
|
@ -435,11 +436,19 @@ begin
|
|||
end;
|
||||
|
||||
{$else}
|
||||
{$ifdef windows}
|
||||
function executeProcess(const cmd: string): int;
|
||||
begin
|
||||
result := dos.Exec(cmd, '')
|
||||
end;
|
||||
//C:\Eigenes\compiler\MinGW\bin;
|
||||
{$else}
|
||||
// fpc has a portable function for this
|
||||
function executeProcess(const cmd: string): int;
|
||||
begin
|
||||
result := shell(cmd);
|
||||
end;
|
||||
{$endif}
|
||||
{$endif}
|
||||
|
||||
{$ifdef windows}
|
||||
|
|
|
|||
|
|
@ -90,10 +90,11 @@ type
|
|||
TAddress = longint;
|
||||
{$endif}
|
||||
|
||||
var
|
||||
NaN: float;
|
||||
inf: float;
|
||||
NegInf: float;
|
||||
{$ifdef fpc}
|
||||
const
|
||||
inf = math.Infinity;
|
||||
NegInf = -inf;
|
||||
{$else}
|
||||
{$ifopt Q+}
|
||||
{$define Q_on}
|
||||
|
|
@ -150,6 +151,10 @@ function shlU(a, b: biggestInt): biggestInt;
|
|||
function shrU(a, b: biggestInt): biggestInt;
|
||||
function ltU(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}
|
||||
|
||||
function alloc(size: int): Pointer;
|
||||
|
|
@ -257,6 +262,23 @@ function leU(a, b: biggestInt): bool;
|
|||
begin
|
||||
result := biggestUInt(a) < biggestUInt(b);
|
||||
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}
|
||||
|
||||
procedure addChar(var s: string; c: Char);
|
||||
|
|
@ -486,4 +508,21 @@ end;
|
|||
|
||||
{$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.
|
||||
|
|
|
|||
|
|
@ -18,22 +18,32 @@ interface
|
|||
uses
|
||||
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
|
||||
MaxSetElements = 1 shl 16; // (2^16) to support unicode character sets?
|
||||
defaultAsmMarkerSymbol = '!';
|
||||
|
||||
//[[[cog
|
||||
//from koch import NIMROD_VERSION
|
||||
//cog.outl("VersionAsString = '%s';" % NIMROD_VERSION)
|
||||
//cog.outl("VersionAsString = '%s'+VersionStar;" % NIMROD_VERSION)
|
||||
//ver = NIMROD_VERSION.split('.')
|
||||
//cog.outl('VersionMajor = %s;' % ver[0])
|
||||
//cog.outl('VersionMinor = %s;' % ver[1])
|
||||
//cog.outl('VersionPatch = %s;' % ver[2])
|
||||
//]]]
|
||||
VersionAsString = '0.5.1';
|
||||
VersionAsString = '0.6.0'+VersionStar;
|
||||
VersionMajor = 0;
|
||||
VersionMinor = 5;
|
||||
VersionPatch = 1;
|
||||
VersionMinor = 6;
|
||||
VersionPatch = 0;
|
||||
//[[[[end]]]]
|
||||
|
||||
implementation
|
||||
|
|
|
|||
34
nim/optast.pas
Normal file
34
nim/optast.pas
Normal 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.
|
||||
|
||||
|
|
@ -13,12 +13,14 @@ interface
|
|||
{$include 'config.inc'}
|
||||
|
||||
uses
|
||||
nsystem, nos, lists, strutils;
|
||||
nsystem, nos, lists, strutils, strtabs;
|
||||
|
||||
type
|
||||
// please make sure we have under 32 options
|
||||
// (improves code efficiency a lot!)
|
||||
TOption = (optNone, optRangeCheck,
|
||||
TOption = (optNone,
|
||||
optObjCheck,
|
||||
optFieldCheck, optRangeCheck,
|
||||
optBoundsCheck, optOverflowCheck, optNilCheck, optAssert, optLineDir,
|
||||
optWarns, optHints,
|
||||
optOptimizeSpeed,
|
||||
|
|
@ -56,6 +58,7 @@ type
|
|||
cmdNone,
|
||||
cmdCompileToC,
|
||||
cmdCompileToCpp,
|
||||
cmdCompileToEcmaScript,
|
||||
cmdInterpret,
|
||||
cmdPretty,
|
||||
cmdDoc,
|
||||
|
|
@ -69,32 +72,27 @@ type
|
|||
cmdDebugTrans, // debug a transformation pass
|
||||
cmdRst2html // convert a reStructuredText file to HTML
|
||||
);
|
||||
|
||||
TNumericalBase = (base10, // base10 is listed as the first element,
|
||||
// so that it is the correct default value
|
||||
base2,
|
||||
base8,
|
||||
base16);
|
||||
|
||||
TStringSeq = array of string;
|
||||
|
||||
const
|
||||
ChecksOptions = {@set}[optRangeCheck, optNilCheck, optOverflowCheck,
|
||||
optBoundsCheck, optAssert];
|
||||
ChecksOptions = {@set}[optObjCheck, optFieldCheck, optRangeCheck,
|
||||
optNilCheck, optOverflowCheck, optBoundsCheck,
|
||||
optAssert];
|
||||
optionToStr: array [TOption] of string = (
|
||||
'optNone', 'optRangeCheck',
|
||||
'optNone', 'optObjCheck', 'optFieldCheck', 'optRangeCheck',
|
||||
'optBoundsCheck', 'optOverflowCheck', 'optNilCheck', 'optAssert',
|
||||
'optLineDir', 'optWarns', 'optHints', 'optOptimizeSpeed',
|
||||
'optOptimizeSize', 'optStackTrace', 'optLineTrace', 'optEmdb',
|
||||
'optByRef', 'optCheckpoints'
|
||||
);
|
||||
var
|
||||
gOptions: TOptions = {@set}[optRangeCheck, optBoundsCheck, optOverflowCheck,
|
||||
gOptions: TOptions = {@set}[optObjCheck, optFieldCheck, optRangeCheck,
|
||||
optBoundsCheck, optOverflowCheck,
|
||||
optAssert, optWarns, optHints, optLineDir,
|
||||
optStackTrace, optLineTrace];
|
||||
|
||||
gGlobalOptions: TGlobalOptions = {@set}[optRefcGC];
|
||||
|
||||
compilerArgs: int;
|
||||
gExitcode: Byte;
|
||||
searchPaths: TLinkedList;
|
||||
outFile: string = '';
|
||||
|
|
@ -124,22 +122,15 @@ function getPrefixDir: string;
|
|||
// gets the application directory
|
||||
|
||||
// additional configuration variables:
|
||||
type
|
||||
TPair = record
|
||||
key, val: string;
|
||||
end;
|
||||
TPairs = array of TPair;
|
||||
|
||||
TStringSeq = array of string;
|
||||
var
|
||||
gConfigVars: TPairs = {@ignore} nil {@emit []};
|
||||
gConfigVars: PStringTable;
|
||||
libpath: string = '';
|
||||
gKeepComments: boolean = true; // whether the parser needs to keep comments
|
||||
gImplicitMods: TStringSeq = {@ignore} nil {@emit []};
|
||||
// modules that are to be implicitly imported
|
||||
|
||||
procedure setConfigVar(const key, val: string);
|
||||
function getConfigVar(const key: string): string;
|
||||
procedure setConfigVar(const key, val: string);
|
||||
|
||||
procedure addImplicitMod(const filename: string);
|
||||
|
||||
|
|
@ -149,6 +140,16 @@ function binaryStrSearch(const x: array of string; const y: string): int;
|
|||
|
||||
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;
|
||||
begin
|
||||
if options.outFile <> '' then result := options.outFile
|
||||
|
|
@ -172,38 +173,6 @@ begin
|
|||
SplitPath(appdir, result, bin);
|
||||
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;
|
||||
var
|
||||
head, tail: string;
|
||||
|
|
@ -261,4 +230,6 @@ begin
|
|||
result := -1
|
||||
end;
|
||||
|
||||
initialization
|
||||
gConfigVars := newStringTable([], modeStyleInsensitive);
|
||||
end.
|
||||
|
|
|
|||
414
nim/parsecfg.pas
Normal file
414
nim/parsecfg.pas
Normal 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
153
nim/parseopt.pas
Normal 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.
|
||||
|
|
@ -70,6 +70,7 @@ type
|
|||
pxSymbol, // a symbol
|
||||
|
||||
pxIntLit,
|
||||
pxInt64Lit, // long constant like 0x00000070fffffff or out of int range
|
||||
pxFloatLit,
|
||||
|
||||
pxParLe, pxParRi, pxBracketLe, pxBracketRi,
|
||||
|
|
@ -110,7 +111,8 @@ const
|
|||
'with', 'xor',
|
||||
//[[[end]]]
|
||||
'pxComment', 'pxCommand',
|
||||
'{&}', '{%}', 'pxStrLit', '[IDENTIFIER]', 'pxIntLit', 'pxFloatLit',
|
||||
'{&}', '{%}', 'pxStrLit', '[IDENTIFIER]', 'pxIntLit', 'pxInt64Lit',
|
||||
'pxFloatLit',
|
||||
'('+'', ')'+'', '['+'', ']'+'',
|
||||
','+'', ';'+'', ':'+'',
|
||||
':=', '='+'', '.'+'', '..', '^'+'', '+'+'', '-'+'', '*'+'', '/'+'',
|
||||
|
|
@ -135,7 +137,7 @@ implementation
|
|||
function pastokToStr(const tok: TPasTok): string;
|
||||
begin
|
||||
case tok.xkind of
|
||||
pxIntLit:
|
||||
pxIntLit, pxInt64Lit:
|
||||
result := toString(tok.iNumber);
|
||||
pxFloatLit:
|
||||
result := toStringF(tok.fNumber);
|
||||
|
|
@ -271,7 +273,7 @@ end;
|
|||
|
||||
procedure getNumber2(var L: TPasLex; var tok: TPasTok);
|
||||
var
|
||||
pos: int;
|
||||
pos, bits: int;
|
||||
xi: biggestInt;
|
||||
begin
|
||||
pos := L.bufpos+1; // skip %
|
||||
|
|
@ -284,6 +286,7 @@ begin
|
|||
|
||||
tok.base := base2;
|
||||
xi := 0;
|
||||
bits := 0;
|
||||
while true do begin
|
||||
case L.buf[pos] of
|
||||
'A'..'Z', 'a'..'z', '2'..'9', '.': begin
|
||||
|
|
@ -294,23 +297,28 @@ begin
|
|||
'0', '1': begin
|
||||
xi := (xi shl 1) or (ord(L.buf[pos]) - ord('0'));
|
||||
inc(pos);
|
||||
inc(bits);
|
||||
end;
|
||||
else break;
|
||||
end
|
||||
end;
|
||||
tok.iNumber := xi;
|
||||
tok.xkind := pxIntLit;
|
||||
if (bits > 32) then //or (xi < low(int32)) or (xi > high(int32)) then
|
||||
tok.xkind := pxInt64Lit
|
||||
else
|
||||
tok.xkind := pxIntLit;
|
||||
L.bufpos := pos;
|
||||
end;
|
||||
|
||||
procedure getNumber16(var L: TPasLex; var tok: TPasTok);
|
||||
var
|
||||
pos: int;
|
||||
pos, bits: int;
|
||||
xi: biggestInt;
|
||||
begin
|
||||
pos := L.bufpos+1; // skip $
|
||||
tok.base := base16;
|
||||
xi := 0;
|
||||
bits := 0;
|
||||
while true do begin
|
||||
case L.buf[pos] of
|
||||
'G'..'Z', 'g'..'z', '.': begin
|
||||
|
|
@ -321,20 +329,26 @@ begin
|
|||
'0'..'9': begin
|
||||
xi := (xi shl 4) or (ord(L.buf[pos]) - ord('0'));
|
||||
inc(pos);
|
||||
inc(bits, 4);
|
||||
end;
|
||||
'a'..'f': begin
|
||||
xi := (xi shl 4) or (ord(L.buf[pos]) - ord('a') + 10);
|
||||
inc(pos);
|
||||
inc(bits, 4);
|
||||
end;
|
||||
'A'..'F': begin
|
||||
xi := (xi shl 4) or (ord(L.buf[pos]) - ord('A') + 10);
|
||||
inc(pos);
|
||||
inc(bits, 4);
|
||||
end;
|
||||
else break;
|
||||
end
|
||||
end;
|
||||
tok.iNumber := xi;
|
||||
tok.xkind := pxIntLit;
|
||||
if (bits > 32) then // (xi < low(int32)) or (xi > high(int32)) then
|
||||
tok.xkind := pxInt64Lit
|
||||
else
|
||||
tok.xkind := pxIntLit;
|
||||
L.bufpos := pos;
|
||||
end;
|
||||
|
||||
|
|
@ -354,7 +368,10 @@ begin
|
|||
end
|
||||
else begin
|
||||
tok.iNumber := ParseInt(tok.literal);
|
||||
tok.xkind := pxIntLit;
|
||||
if (tok.iNumber < low(int32)) or (tok.iNumber > high(int32)) then
|
||||
tok.xkind := pxInt64Lit
|
||||
else
|
||||
tok.xkind := pxIntLit;
|
||||
end;
|
||||
except
|
||||
on EInvalidValue do
|
||||
|
|
|
|||
104
nim/pasparse.pas
104
nim/pasparse.pas
|
|
@ -322,6 +322,10 @@ begin
|
|||
result := newNodeP(nkPtrTy, p);
|
||||
getTok(p); eat(p, pxCurlyDirRi);
|
||||
end
|
||||
else if p.tok.ident.id = getIdent('tuple').id then begin
|
||||
result := newNodeP(nkTupleTy, p);
|
||||
getTok(p); eat(p, pxCurlyDirRi);
|
||||
end
|
||||
else begin
|
||||
parMessage(p, errUnknownDirective, pasTokToStr(p.tok));
|
||||
while true do begin
|
||||
|
|
@ -481,6 +485,16 @@ begin
|
|||
exprListAux(p, elemKind, endTok, sepTok, result);
|
||||
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;
|
||||
var
|
||||
a: PNode;
|
||||
|
|
@ -493,12 +507,17 @@ begin
|
|||
// literals
|
||||
pxIntLit: begin
|
||||
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);
|
||||
end;
|
||||
pxFloatLit: begin
|
||||
result := newFloatNodeP(nkFloatLit, p.tok.fNumber, p);
|
||||
result.base := p.tok.base;
|
||||
setBaseFlags(result, p.tok.base);
|
||||
getTok(p);
|
||||
end;
|
||||
pxStrLit: begin
|
||||
|
|
@ -683,8 +702,9 @@ begin
|
|||
end
|
||||
else begin end
|
||||
end;
|
||||
for i := 0 to sonsLen(n)-1 do
|
||||
result.sons[i] := fixExpr(n.sons[i])
|
||||
if not (n.kind in [nkEmpty..nkNilLit]) then
|
||||
for i := 0 to sonsLen(n)-1 do
|
||||
result.sons[i] := fixExpr(n.sons[i])
|
||||
end;
|
||||
|
||||
function parseExpr(var p: TPasParser): PNode;
|
||||
|
|
@ -948,6 +968,7 @@ begin
|
|||
if p.tok.xkind <> pxIf then begin
|
||||
// ordinary else part:
|
||||
branch := newNodeP(nkElse, p);
|
||||
skipCom(p, result); // BUGFIX
|
||||
addSon(branch, parseStmt(p));
|
||||
addSon(result, branch);
|
||||
break
|
||||
|
|
@ -1235,6 +1256,14 @@ begin
|
|||
noBody := true;
|
||||
getTok(p); opt(p, pxSemicolon);
|
||||
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
|
||||
if result = nil then result := newNodeP(nkPragma, p);
|
||||
addSon(result, newIdentNodeP(getIdent('varargs'), p));
|
||||
|
|
@ -1464,7 +1493,7 @@ begin
|
|||
nkIdent, nkAccQuoted: begin
|
||||
a := newNode(nkPostFix);
|
||||
a.info := n.info;
|
||||
addSon(a, newIdentNode(getIdent('*'+'')));
|
||||
addSon(a, newIdentNode(getIdent('*'+''), n.info));
|
||||
addSon(a, n);
|
||||
n := a
|
||||
end;
|
||||
|
|
@ -1486,7 +1515,7 @@ begin
|
|||
end
|
||||
end;
|
||||
nkRecList, nkRecWhen, nkElse, nkOfBranch, nkElifBranch,
|
||||
nkRecordTy, nkObjectTy: begin
|
||||
nkObjectTy: begin
|
||||
for i := 0 to sonsLen(n)-1 do fixRecordDef(n.sons[i])
|
||||
end;
|
||||
nkIdentDefs: begin
|
||||
|
|
@ -1497,6 +1526,19 @@ begin
|
|||
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;
|
||||
var
|
||||
a: PNode;
|
||||
|
|
@ -1512,19 +1554,14 @@ begin
|
|||
eat(p, pxParRi);
|
||||
end
|
||||
else addSon(result, nil);
|
||||
skipCom(p, result);
|
||||
a := parseRecordPart(p);
|
||||
fixRecordDef(a);
|
||||
addSon(result, a);
|
||||
eat(p, pxEnd);
|
||||
opt(p, pxSemicolon);
|
||||
skipCom(p, result);
|
||||
parseRecordBody(p, result);
|
||||
end;
|
||||
|
||||
function parseTypeDesc(var p: TPasParser): PNode;
|
||||
var
|
||||
oldcontext: TPasContext;
|
||||
a, r: PNode;
|
||||
i: int;
|
||||
begin
|
||||
oldcontext := p.context;
|
||||
p.context := conTypeDesc;
|
||||
|
|
@ -1532,7 +1569,28 @@ begin
|
|||
case p.tok.xkind of
|
||||
pxCommand: result := parseCommand(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);
|
||||
pxParLe: result := parseEnum(p);
|
||||
pxArray: begin
|
||||
|
|
@ -1591,13 +1649,29 @@ begin
|
|||
end;
|
||||
|
||||
function parseTypeDef(var p: TPasParser): PNode;
|
||||
var
|
||||
a, e, pragmasNode: PNode;
|
||||
begin
|
||||
result := newNodeP(nkTypeDef, p);
|
||||
addSon(result, identVis(p));
|
||||
addSon(result, nil); // generic params
|
||||
if p.tok.xkind = pxEquals then begin
|
||||
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
|
||||
else
|
||||
addSon(result, nil);
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ unit platform;
|
|||
// 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.
|
||||
// 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
|
||||
|
||||
|
|
@ -45,7 +45,8 @@ type
|
|||
osAtari,
|
||||
osNetware,
|
||||
osMacos,
|
||||
osMacosx
|
||||
osMacosx,
|
||||
osEcmaScript
|
||||
);
|
||||
type
|
||||
TInfoOSProp = (
|
||||
|
|
@ -55,7 +56,7 @@ type
|
|||
);
|
||||
|
||||
TInfoOSProps = set of TInfoOSProp;
|
||||
TInfoOS = record
|
||||
TInfoOS = record{@tuple}
|
||||
name: string;
|
||||
parDir: string;
|
||||
dllExt: string;
|
||||
|
|
@ -360,6 +361,22 @@ const
|
|||
exeExt: '';
|
||||
extSep: '.'+'';
|
||||
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
|
||||
|
|
@ -377,11 +394,12 @@ type
|
|||
cpuIa64,
|
||||
cpuAmd64,
|
||||
cpuMips,
|
||||
cpuArm
|
||||
cpuArm,
|
||||
cpuEcmaScript
|
||||
);
|
||||
type
|
||||
TEndian = (littleEndian, bigEndian);
|
||||
TInfoCPU = record
|
||||
TInfoCPU = record{@tuple}
|
||||
name: string;
|
||||
intSize: int;
|
||||
endian: TEndian;
|
||||
|
|
@ -460,6 +478,13 @@ const
|
|||
endian: littleEndian;
|
||||
floatSize: 64;
|
||||
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
|
||||
// mechanism
|
||||
{@emit
|
||||
procedure nimCPU(): cstring; importc;}
|
||||
procedure nimCPU(): cstring; importc; noconv;}
|
||||
{@emit
|
||||
procedure nimOS(): cstring; importc;}
|
||||
procedure nimOS(): cstring; importc; noconv;}
|
||||
|
||||
{@ignore}
|
||||
initialization
|
||||
|
|
|
|||
130
nim/pnimsyn.pas
130
nim/pnimsyn.pas
|
|
@ -240,6 +240,9 @@ begin
|
|||
end;
|
||||
|
||||
function parseSymbol(var p: TParser): PNode;
|
||||
var
|
||||
s: string;
|
||||
id: PIdent;
|
||||
begin
|
||||
case p.tok.tokType of
|
||||
tkSymbol: begin
|
||||
|
|
@ -251,9 +254,31 @@ begin
|
|||
getTok(p);
|
||||
case p.tok.tokType of
|
||||
tkBracketLe: begin
|
||||
addSon(result, newIdentNodeP(getIdent('[]'), p));
|
||||
s := '['+'';
|
||||
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);
|
||||
s := s + ']'+'';
|
||||
if p.tok.tokType = tkEquals then begin
|
||||
s := s + '='; getTok(p);
|
||||
end;
|
||||
addSon(result, newIdentNodeP(getIdent(s), p));
|
||||
end;
|
||||
tkParLe: begin
|
||||
addSon(result, newIdentNodeP(getIdent('()'), p));
|
||||
|
|
@ -261,8 +286,14 @@ begin
|
|||
eat(p, tkParRi);
|
||||
end;
|
||||
tokKeywordLow..tokKeywordHigh, tkSymbol, tkOpr: begin
|
||||
addSon(result, newIdentNodeP(p.tok.ident, p));
|
||||
id := p.tok.ident;
|
||||
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;
|
||||
else begin
|
||||
parMessage(p, errIdentifierExpected, tokToStr(p.tok));
|
||||
|
|
@ -350,7 +381,7 @@ var
|
|||
begin
|
||||
case p.tok.tokType of
|
||||
tkDotDot: result := dotdotExpr(p);
|
||||
tkVar, tkRef, tkPtr, tkProc, tkType: result := parseTypeDescK(p);
|
||||
tkVar, tkRef, tkPtr, tkProc, tkTuple, tkType: result := parseTypeDescK(p);
|
||||
else begin
|
||||
a := parseExpr(p);
|
||||
case p.tok.tokType of
|
||||
|
|
@ -519,6 +550,16 @@ begin
|
|||
eat(p, tkParRi);
|
||||
end;
|
||||
|
||||
procedure setBaseFlags(n: PNode; base: TNumericalBase);
|
||||
begin
|
||||
case base of
|
||||
base10: begin end;
|
||||
base2: include(n.flags, nfBase2);
|
||||
base8: include(n.flags, nfBase8);
|
||||
base16: include(n.flags, nfBase16);
|
||||
end
|
||||
end;
|
||||
|
||||
function identOrLiteral(var p: TParser): PNode;
|
||||
begin
|
||||
case p.tok.tokType of
|
||||
|
|
@ -530,42 +571,42 @@ begin
|
|||
// literals
|
||||
tkIntLit: begin
|
||||
result := newIntNodeP(nkIntLit, p.tok.iNumber, p);
|
||||
result.base := p.tok.base;
|
||||
setBaseFlags(result, p.tok.base);
|
||||
getTok(p);
|
||||
end;
|
||||
tkInt8Lit: begin
|
||||
result := newIntNodeP(nkInt8Lit, p.tok.iNumber, p);
|
||||
result.base := p.tok.base;
|
||||
setBaseFlags(result, p.tok.base);
|
||||
getTok(p);
|
||||
end;
|
||||
tkInt16Lit: begin
|
||||
result := newIntNodeP(nkInt16Lit, p.tok.iNumber, p);
|
||||
result.base := p.tok.base;
|
||||
setBaseFlags(result, p.tok.base);
|
||||
getTok(p);
|
||||
end;
|
||||
tkInt32Lit: begin
|
||||
result := newIntNodeP(nkInt32Lit, p.tok.iNumber, p);
|
||||
result.base := p.tok.base;
|
||||
setBaseFlags(result, p.tok.base);
|
||||
getTok(p);
|
||||
end;
|
||||
tkInt64Lit: begin
|
||||
result := newIntNodeP(nkInt64Lit, p.tok.iNumber, p);
|
||||
result.base := p.tok.base;
|
||||
setBaseFlags(result, p.tok.base);
|
||||
getTok(p);
|
||||
end;
|
||||
tkFloatLit: begin
|
||||
result := newFloatNodeP(nkFloatLit, p.tok.fNumber, p);
|
||||
result.base := p.tok.base;
|
||||
setBaseFlags(result, p.tok.base);
|
||||
getTok(p);
|
||||
end;
|
||||
tkFloat32Lit: begin
|
||||
result := newFloatNodeP(nkFloat32Lit, p.tok.fNumber, p);
|
||||
result.base := p.tok.base;
|
||||
setBaseFlags(result, p.tok.base);
|
||||
getTok(p);
|
||||
end;
|
||||
tkFloat64Lit: begin
|
||||
result := newFloatNodeP(nkFloat64Lit, p.tok.fNumber, p);
|
||||
result.base := p.tok.base;
|
||||
setBaseFlags(result, p.tok.base);
|
||||
getTok(p);
|
||||
end;
|
||||
tkStrLit: begin
|
||||
|
|
@ -584,10 +625,6 @@ begin
|
|||
result := newIntNodeP(nkCharLit, ord(p.tok.literal[strStart]), p);
|
||||
getTok(p);
|
||||
end;
|
||||
tkRCharLit: begin
|
||||
result := newIntNodeP(nkRCharLit, ord(p.tok.literal[strStart]), p);
|
||||
getTok(p);
|
||||
end;
|
||||
tkNil: begin
|
||||
result := newNodeP(nkNilLit, p);
|
||||
getTok(p);
|
||||
|
|
@ -598,8 +635,7 @@ begin
|
|||
tkColon);
|
||||
end;
|
||||
tkCurlyLe: begin // {} constructor
|
||||
result := exprColonEqExprList(p, nkCurly, nkRange, tkCurlyRi,
|
||||
tkDotDot);
|
||||
result := exprColonEqExprList(p, nkCurly, nkRange, tkCurlyRi, tkDotDot);
|
||||
end;
|
||||
tkBracketLe: begin // [] constructor
|
||||
result := exprColonEqExprList(p, nkBracket, nkExprColonExpr, tkBracketRi,
|
||||
|
|
@ -1278,6 +1314,8 @@ begin
|
|||
end;
|
||||
|
||||
function parseTypeDescK(var p: TParser): PNode;
|
||||
var
|
||||
a: PNode;
|
||||
begin
|
||||
case p.tok.tokType of
|
||||
tkVar: result := parseTypeDescKAux(p, nkVarTy);
|
||||
|
|
@ -1298,7 +1336,25 @@ begin
|
|||
addSon(result, parsePragma(p))
|
||||
else
|
||||
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
|
||||
InternalError(parLineInfo(p), 'pnimsyn.parseTypeDescK');
|
||||
result := nil
|
||||
|
|
@ -1309,7 +1365,7 @@ end;
|
|||
function parseTypeDesc(var p: TParser): PNode;
|
||||
begin
|
||||
case p.tok.tokType of
|
||||
tkVar, tkRef, tkPtr, tkProc, tkType:
|
||||
tkVar, tkRef, tkPtr, tkProc, tkType, tkTuple:
|
||||
result := parseTypeDescK(p);
|
||||
else result := primary(p)
|
||||
end
|
||||
|
|
@ -1599,7 +1655,7 @@ begin
|
|||
if kind = nkObjectTy then
|
||||
addSon(result, a)
|
||||
else
|
||||
parMessage(p, errInheritanceOnlyWithObjects);
|
||||
parMessage(p, errInheritanceOnlyWithNonFinalObjects);
|
||||
end
|
||||
else addSon(result, nil);
|
||||
skipComment(p, result);
|
||||
|
|
@ -1617,7 +1673,6 @@ begin
|
|||
if p.tok.tokType = tkEquals then begin
|
||||
getTok(p); optInd(p, result);
|
||||
case p.tok.tokType of
|
||||
tkRecord: a := parseRecordOrObject(p, nkRecordTy);
|
||||
tkObject: a := parseRecordOrObject(p, nkObjectTy);
|
||||
tkEnum: a := parseEnum(p);
|
||||
else a := parseTypeDesc(p);
|
||||
|
|
@ -1660,22 +1715,23 @@ end;
|
|||
function complexOrSimpleStmt(var p: TParser): PNode;
|
||||
begin
|
||||
case p.tok.tokType of
|
||||
tkIf: result := parseIfOrWhen(p, nkIfStmt);
|
||||
tkWhile: result := parseWhile(p);
|
||||
tkCase: result := parseCase(p);
|
||||
tkTry: result := parseTry(p);
|
||||
tkFor: result := parseFor(p);
|
||||
tkBlock: result := parseBlock(p);
|
||||
tkAsm: result := parseAsm(p);
|
||||
tkProc: result := parseRoutine(p, nkProcDef);
|
||||
tkIterator: result := parseRoutine(p, nkIteratorDef);
|
||||
tkMacro: result := parseRoutine(p, nkMacroDef);
|
||||
tkTemplate: result := parseRoutine(p, nkTemplateDef);
|
||||
tkType: result := parseSection(p, nkTypeSection, parseTypeDef);
|
||||
tkConst: result := parseSection(p, nkConstSection, parseConstant);
|
||||
tkWhen: result := parseIfOrWhen(p, nkWhenStmt);
|
||||
tkVar: result := parseSection(p, nkVarSection, parseVariable);
|
||||
else result := simpleStmt(p);
|
||||
tkIf: result := parseIfOrWhen(p, nkIfStmt);
|
||||
tkWhile: result := parseWhile(p);
|
||||
tkCase: result := parseCase(p);
|
||||
tkTry: result := parseTry(p);
|
||||
tkFor: result := parseFor(p);
|
||||
tkBlock: result := parseBlock(p);
|
||||
tkAsm: result := parseAsm(p);
|
||||
tkProc: result := parseRoutine(p, nkProcDef);
|
||||
tkIterator: result := parseRoutine(p, nkIteratorDef);
|
||||
tkMacro: result := parseRoutine(p, nkMacroDef);
|
||||
tkTemplate: result := parseRoutine(p, nkTemplateDef);
|
||||
tkConverter: result := parseRoutine(p, nkConverterDef);
|
||||
tkType: result := parseSection(p, nkTypeSection, parseTypeDef);
|
||||
tkConst: result := parseSection(p, nkConstSection, parseConstant);
|
||||
tkWhen: result := parseIfOrWhen(p, nkWhenStmt);
|
||||
tkVar: result := parseSection(p, nkVarSection, parseVariable);
|
||||
else result := simpleStmt(p);
|
||||
end
|
||||
end;
|
||||
|
||||
|
|
|
|||
|
|
@ -26,10 +26,9 @@ begin
|
|||
if (it.kind = nkExprColonExpr) and (it.sons[0].kind = nkIdent) then begin
|
||||
case whichKeyword(it.sons[0].ident) of
|
||||
wAsmQuote: begin
|
||||
case it.sons[1].kind of
|
||||
nkCharLit, nkRCharLit: result := chr(int(it.sons[1].intVal));
|
||||
else invalidPragma(it)
|
||||
end
|
||||
if it.sons[1].kind = nkCharLit then
|
||||
result := chr(int(it.sons[1].intVal))
|
||||
else invalidPragma(it)
|
||||
end
|
||||
else
|
||||
invalidPragma(it)
|
||||
|
|
@ -246,6 +245,8 @@ begin
|
|||
sw := whichKeyword(n.sons[0].ident);
|
||||
case sw of
|
||||
wChecks: OnOff(c, n, checksOptions);
|
||||
wObjChecks: OnOff(c, n, {@set}[optObjCheck]);
|
||||
wFieldchecks: OnOff(c, n, {@set}[optFieldCheck]);
|
||||
wRangechecks: OnOff(c, n, {@set}[optRangeCheck]);
|
||||
wBoundchecks: OnOff(c, n, {@set}[optBoundsCheck]);
|
||||
wOverflowchecks: OnOff(c, n, {@set}[optOverflowCheck]);
|
||||
|
|
@ -373,12 +374,12 @@ begin
|
|||
end
|
||||
end;
|
||||
|
||||
procedure Breakpoint(c: PContext; n: PNode);
|
||||
procedure PragmaBreakpoint(c: PContext; n: PNode);
|
||||
begin
|
||||
{@discard} getOptionalStr(c, n, '');
|
||||
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
|
||||
var
|
||||
info: TLineInfo;
|
||||
|
|
@ -427,7 +428,10 @@ begin
|
|||
liMessage(it.info, errPowerOfTwoExpected);
|
||||
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;
|
||||
wRegister: begin noVal(it); include(sym.flags, sfRegister); end;
|
||||
wMagic: processMagic(c, it, sym);
|
||||
|
|
@ -444,7 +448,6 @@ begin
|
|||
wNosideeffect: begin noVal(it); Include(sym.flags, sfNoSideEffect); end;
|
||||
wNoReturn: begin noVal(it); Include(sym.flags, sfNoReturn); end;
|
||||
wDynLib: processDynLib(c, it, sym);
|
||||
wReturnsNew: begin noVal(it); Include(sym.flags, sfReturnsNew); end;
|
||||
wCompilerProc: begin
|
||||
noVal(it); // compilerproc may not get a string!
|
||||
makeExternExport(sym, sym.name.s);
|
||||
|
|
@ -464,6 +467,14 @@ begin
|
|||
noVal(it);
|
||||
include(sym.typ.flags, tfVarargs);
|
||||
end;
|
||||
wFinal: begin
|
||||
noVal(it);
|
||||
include(sym.typ.flags, tfFinal);
|
||||
end;
|
||||
wTypeCheck: begin
|
||||
noVal(it);
|
||||
include(sym.flags, sfTypeCheck);
|
||||
end;
|
||||
|
||||
// statement pragmas:
|
||||
wHint: liMessage(it.info, hintUser, expectStrLit(c, it));
|
||||
|
|
@ -478,6 +489,9 @@ begin
|
|||
wCompile: processCompile(c, it);
|
||||
wLink: processCommonLink(c, it, linkNormal);
|
||||
wLinkSys: processCommonLink(c, it, linkSys);
|
||||
wPassL: extccomp.addLinkOption(expectStrLit(c, it));
|
||||
wPassC: extccomp.addCompileOption(expectStrLit(c, it));
|
||||
|
||||
// fixupSystem not even documented:
|
||||
wFixupSystem: begin
|
||||
if c.module = magicSys.SystemModule then
|
||||
|
|
@ -485,12 +499,13 @@ begin
|
|||
else
|
||||
invalidPragma(it)
|
||||
end;
|
||||
wBreakpoint: Breakpoint(c, it);
|
||||
wCheckpoint: Checkpoint(c, it);
|
||||
wBreakpoint: PragmaBreakpoint(c, it);
|
||||
wCheckpoint: PragmaCheckpoint(c, it);
|
||||
|
||||
wPush: begin processPush(c, n, i+1); break end;
|
||||
wPop: processPop(c, it);
|
||||
wChecks, wRangechecks, wBoundchecks, wOverflowchecks, wNilchecks,
|
||||
wChecks, wObjChecks, wFieldChecks,
|
||||
wRangechecks, wBoundchecks, wOverflowchecks, wNilchecks,
|
||||
wAssertions, wWarnings, wHints, wLinedir, wStacktrace,
|
||||
wLinetrace, wOptimization, wByRef, wCallConv, wDebugger:
|
||||
processOption(c, it);
|
||||
|
|
@ -528,20 +543,28 @@ begin
|
|||
wCppMethod, wDeprecated, wVarargs]);
|
||||
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);
|
||||
begin
|
||||
pragma(c, s, n, {@set}[FirstCallConv..LastCallConv,
|
||||
wImportc, wExportc, wNodecl, wMagic, wDeprecated]);
|
||||
end;
|
||||
|
||||
procedure pragmaStmt(c: PContext; n: PNode);
|
||||
procedure pragmaStmt(c: PContext; s: PSym; n: PNode);
|
||||
begin
|
||||
pragma(c, nil, n, {@set}[wChecks, wRangechecks, wBoundchecks,
|
||||
wOverflowchecks, wNilchecks, wAssertions, wWarnings,
|
||||
pragma(c, s, n, {@set}[wChecks, wObjChecks, wFieldChecks, wRangechecks,
|
||||
wBoundchecks, wOverflowchecks, wNilchecks, wAssertions, wWarnings,
|
||||
wHints, wLinedir, wStacktrace, wLinetrace, wOptimization,
|
||||
wHint, wWarning, wError, wFatal, wDefine, wUndef,
|
||||
wCompile, wLink, wLinkSys,
|
||||
wPush, wPop, wFixupSystem, wBreakpoint, wCheckpoint]);
|
||||
wCompile, wLink, wLinkSys, wPure,
|
||||
wPush, wPop, wFixupSystem, wBreakpoint, wCheckpoint,
|
||||
wPassL, wPassC]);
|
||||
end;
|
||||
|
||||
procedure pragmaLambda(c: PContext; s: PSym; n: PNode);
|
||||
|
|
@ -554,7 +577,7 @@ end;
|
|||
procedure pragmaType(c: PContext; s: PSym; n: PNode);
|
||||
begin
|
||||
pragma(c, s, n, {@set}[wImportc, wExportc, wDeprecated, wMagic,
|
||||
wNodecl, wPure, wHeader, wCompilerProc]);
|
||||
wNodecl, wPure, wHeader, wCompilerProc, wFinal]);
|
||||
end;
|
||||
|
||||
procedure pragmaField(c: PContext; s: PSym; n: PNode);
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue