From 8b8a21cb592cdff15d8e448945b3d019eab42564 Mon Sep 17 00:00:00 2001 From: Reimer Behrends Date: Fri, 23 May 2014 11:27:39 +0200 Subject: [PATCH 001/234] Fixed parsing of float literals. Float literals were not parsed properly when their fractional part exceeded 53 significant bits. This affected in particular math.PI and math.E. Rather than reinventing the wheel, this patch reuses C's strtod() implementation, which already does the heavy lifting with respect to correctness, though some caution is necessary to keep float parsing locale-independent. --- lib/pure/parseutils.nim | 94 ++++++++++++++++++++++------------------- tests/float/tfloat4.nim | 42 ++++++++++++++++++ 2 files changed, 92 insertions(+), 44 deletions(-) create mode 100644 tests/float/tfloat4.nim diff --git a/lib/pure/parseutils.nim b/lib/pure/parseutils.nim index 484ba5184d..9b3f79a74e 100644 --- a/lib/pure/parseutils.nim +++ b/lib/pure/parseutils.nim @@ -231,33 +231,43 @@ proc parseInt*(s: string, number: var int, start = 0): int {. else: number = int(res) -proc tenToThePowerOf(b: int): BiggestFloat = - var b = b - var a = 10.0 - result = 1.0 - while true: - if (b and 1) == 1: - result *= a - b = b shr 1 - if b == 0: break - a *= a - proc parseBiggestFloat*(s: string, number: var BiggestFloat, start = 0): int {. rtl, extern: "npuParseBiggestFloat", noSideEffect.} = ## parses a float starting at `start` and stores the value into `number`. - ## Result is the number of processed chars or 0 if there occured a parsing - ## error. + ## Result is the number of processed chars or 0 if a parsing error + ## occurred. + + type struct_lconv {.importc: "struct lconv",header:"".} = + object + # Unneeded fields have been omitted. + decimal_point: cstring + + proc localeconv(): ptr struct_lconv {.importc, header: "", + noSideEffect.} + + proc strtod(buf: cstring, endptr: ptr cstring): float64 {.importc, + header: "", noSideEffect.} + + # This routine leverages `strtod()` for the non-trivial task of + # parsing floating point numbers correctly. Because `strtod()` is + # locale-dependent with respect to the radix character, we create + # a copy where the decimal point is replaced with the locale's + # radix character. + var - esign = 1.0 - sign = 1.0 i = start - exponent: int - flags: int - number = 0.0 - if s[i] == '+': inc(i) - elif s[i] == '-': - sign = -1.0 + sign = 1.0 + t = "" + hasdigits = false + + # Sign? + if s[i] == '+' or s[i] == '-': + if s[i] == '-': + sign = -1.0 + add(t, s[i]) inc(i) + + # NaN? if s[i] == 'N' or s[i] == 'n': if s[i+1] == 'A' or s[i+1] == 'a': if s[i+2] == 'N' or s[i+2] == 'n': @@ -265,6 +275,8 @@ proc parseBiggestFloat*(s: string, number: var BiggestFloat, start = 0): int {. number = NaN return i+3 - start return 0 + + # Inf? if s[i] == 'I' or s[i] == 'i': if s[i+1] == 'N' or s[i+1] == 'n': if s[i+2] == 'F' or s[i+2] == 'f': @@ -272,46 +284,40 @@ proc parseBiggestFloat*(s: string, number: var BiggestFloat, start = 0): int {. number = Inf*sign return i+3 - start return 0 + + # Integer part? while s[i] in {'0'..'9'}: - # Read integer part - flags = flags or 1 - number = number * 10.0 + toFloat(ord(s[i]) - ord('0')) + hasdigits = true + add(t, s[i]) inc(i) while s[i] == '_': inc(i) - # Decimal? + + # Fractional part? if s[i] == '.': - var hd = 1.0 + add(t, localeconv().decimal_point) inc(i) while s[i] in {'0'..'9'}: - # Read fractional part - flags = flags or 2 - number = number * 10.0 + toFloat(ord(s[i]) - ord('0')) - hd = hd * 10.0 + hasdigits = true + add(t, s[i]) inc(i) while s[i] == '_': inc(i) - number = number / hd # this complicated way preserves precision - # Again, read integer and fractional part - if flags == 0: return 0 + if not hasdigits: + return 0 + # Exponent? if s[i] in {'e', 'E'}: + add(t, s[i]) inc(i) - if s[i] == '+': - inc(i) - elif s[i] == '-': - esign = -1.0 + if s[i] in {'+', '-'}: + add(t, s[i]) inc(i) if s[i] notin {'0'..'9'}: return 0 while s[i] in {'0'..'9'}: - exponent = exponent * 10 + ord(s[i]) - ord('0') + add(t, s[i]) inc(i) while s[i] == '_': inc(i) - # Calculate Exponent - let hd = tenToThePowerOf(exponent) - if esign > 0.0: number = number * hd - else: number = number / hd - # evaluate sign - number = number * sign + number = strtod(t, nil) result = i - start proc parseFloat*(s: string, number: var float, start = 0): int {. diff --git a/tests/float/tfloat4.nim b/tests/float/tfloat4.nim new file mode 100644 index 0000000000..960c4e5f71 --- /dev/null +++ b/tests/float/tfloat4.nim @@ -0,0 +1,42 @@ +import math, strutils + +proc c_sprintf(buf, fmt: cstring) {.importc:"sprintf", header: "", varargs.} + +proc floatToStr(f: float64): string = + var buffer: array[128, char] + c_sprintf(buffer, "%.16e", f) + result = "" + for ch in buffer: + if ch == '\0': + return + add(result, ch) + +let testFloats = [ + "0", "-1", "1", "1.", ".3", "3.3", "-.3", "-99.99", + "1.1e10", "-2e100", "1.234e-10", "1.234e+10", + "-inf", "inf", "+inf", + "3.14159265358979323846264338327950288", + "1.57079632679489661923132169163975144", + "0.785398163397448309615660845819875721", + "1.41421356237309504880168872420969808", + "0.707106781186547524400844362104849039", + "2.71828182845904523536028747135266250", + "0.00097656250000000021684043449710088680149056017398834228515625" +] + +for num in testFloats: + assert num.parseFloat.floatToStr.parseFloat == num.parseFloat + +assert "0".parseFloat == 0.0 +assert "-.1".parseFloat == -0.1 +assert "2.5e1".parseFloat == 25.0 +assert "1e10".parseFloat == 10_000_000_000.0 +assert "0.000_005".parseFloat == 5.000_000e-6 +assert "1.234_567e+2".parseFloat == 123.4567 +assert "1e1_00".parseFloat == "1e100".parseFloat +assert "3.1415926535897932384626433".parseFloat == + 3.1415926535897932384626433 +assert "2.71828182845904523536028747".parseFloat == + 2.71828182845904523536028747 +assert 0.00097656250000000021684043449710088680149056017398834228515625 == + "0.00097656250000000021684043449710088680149056017398834228515625".parseFloat From cea2a9087d44378802c77ba041a4f54cd7b6087d Mon Sep 17 00:00:00 2001 From: katlogic Date: Sun, 15 Jun 2014 01:49:14 +0200 Subject: [PATCH 002/234] More human readable `$`(float) The output matches that of Python (eg 1e100, not 1.0e100), but also reflects locale (assuming it was set using setlocale() before). --- lib/system/ansi_c.nim | 5 ++++- lib/system/repr.nim | 4 ++-- lib/system/sysstr.nim | 14 ++++++++++---- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/lib/system/ansi_c.nim b/lib/system/ansi_c.nim index 5111bc3cf5..da101cc2c6 100644 --- a/lib/system/ansi_c.nim +++ b/lib/system/ansi_c.nim @@ -106,10 +106,13 @@ proc c_fopen(filename, mode: cstring): C_TextFileStar {. importc: "fopen", header: "".} proc c_fclose(f: C_TextFileStar) {.importc: "fclose", header: "".} -proc c_sprintf(buf, frmt: cstring) {.header: "", +proc c_sprintf(buf, frmt: cstring): int {.header: "", importc: "sprintf", varargs, noSideEffect.} # we use it only in a way that cannot lead to security issues +proc c_localeconv():ptr cstring {.header: "", + importc: "localeconv", noSideEffect.} + proc c_fread(buf: pointer, size, n: int, f: C_BinaryFileStar): int {. importc: "fread", header: "".} proc c_fseek(f: C_BinaryFileStar, offset: clong, whence: int): int {. diff --git a/lib/system/repr.nim b/lib/system/repr.nim index 487bac0527..f8f9496680 100644 --- a/lib/system/repr.nim +++ b/lib/system/repr.nim @@ -17,12 +17,12 @@ proc reprFloat(x: float): string {.compilerproc.} = return $x proc reprPointer(x: pointer): string {.compilerproc.} = var buf: array [0..59, char] - c_sprintf(buf, "%p", x) + discard c_sprintf(buf, "%p", x) return $buf proc `$`(x: uint64): string = var buf: array [0..59, char] - c_sprintf(buf, "%llu", x) + discard c_sprintf(buf, "%llu", x) return $buf proc reprStrAux(result: var string, s: string) = diff --git a/lib/system/sysstr.nim b/lib/system/sysstr.nim index 4244bae4cb..183ea0c8d1 100644 --- a/lib/system/sysstr.nim +++ b/lib/system/sysstr.nim @@ -250,10 +250,16 @@ proc nimIntToStr(x: int): string {.compilerRtl.} = for j in 0..i div 2 - 1: swap(result[j], result[i-j-1]) -proc nimFloatToStr(x: float): string {.compilerproc.} = - var buf: array [0..59, char] - c_sprintf(buf, "%#.16e", x) - return $buf +proc nimFloatToStr(f: float): string {.compilerproc.} = + var buf: array [0..64, char] + var n:int = c_sprintf(buf, "%.16g", f) + for i in 0..n-1: + if buf[i] notin {'0'..'9','-'}: + return $buf + buf[n] = c_localeconv()[0] + buf[n+1] = '0' + buf[n+2] = '\0' + result = $buf proc nimInt64ToStr(x: int64): string {.compilerRtl.} = result = newString(sizeof(x)*4) From 9532951cfc4280d815160a4c86c7fec60d2a2001 Mon Sep 17 00:00:00 2001 From: katlogic Date: Sun, 15 Jun 2014 01:53:09 +0200 Subject: [PATCH 003/234] Tests for `$`(float) --- tests/matrix/tmatrix2.nim | 2 +- tests/showoff/tdrdobbs_examples.nim | 2 +- tests/system/tfloatToString.nim | 22 ++++++++++++++++++++++ 3 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 tests/system/tfloatToString.nim diff --git a/tests/matrix/tmatrix2.nim b/tests/matrix/tmatrix2.nim index 442096e93a..82990f1a59 100644 --- a/tests/matrix/tmatrix2.nim +++ b/tests/matrix/tmatrix2.nim @@ -1,5 +1,5 @@ discard """ - output: "5.0000000000000000e+00" + output: "5.0" """ type diff --git a/tests/showoff/tdrdobbs_examples.nim b/tests/showoff/tdrdobbs_examples.nim index 8a39990ba5..13a685950e 100644 --- a/tests/showoff/tdrdobbs_examples.nim +++ b/tests/showoff/tdrdobbs_examples.nim @@ -1,7 +1,7 @@ discard """ output: '''108 11 -1 1936 -4.0000000000000002e-01 +0.4 true truefalse''' """ diff --git a/tests/system/tfloatToString.nim b/tests/system/tfloatToString.nim new file mode 100644 index 0000000000..bb45a91d70 --- /dev/null +++ b/tests/system/tfloatToString.nim @@ -0,0 +1,22 @@ +discard """ + output:'''2.3242 +2.982 +123912.1 +123912.1823 +5.0 +1e+100 +inf +-inf +nan +''' +""" + +echo($(2.3242)) +echo($(2.982)) +echo($(123912.1)) +echo($(123912.1823)) +echo($(5.0)) +echo($(1e100)) +echo($(1e1000000)) +echo($(-1e1000000)) +echo($(0.0/0.0)) From bd8f5c8392fc6f28381170d029f67801789fd78d Mon Sep 17 00:00:00 2001 From: Billingsly Wetherfordshire Date: Thu, 19 Jun 2014 13:00:11 -0500 Subject: [PATCH 004/234] json.== handles nil now --- lib/pure/json.nim | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/pure/json.nim b/lib/pure/json.nim index 4e369b854d..871713f1ce 100644 --- a/lib/pure/json.nim +++ b/lib/pure/json.nim @@ -621,9 +621,13 @@ proc `%`*(elements: openArray[PJsonNode]): PJsonNode = proc `==`* (a,b: PJsonNode): bool = ## Check two nodes for equality - if a.kind != b.kind: false + if a.isNil: + if b.isNil: return true + return false + elif b.isNil or a.kind != b.kind: + return false else: - case a.kind + return case a.kind of JString: a.str == b.str of JInt: From e712dbaef55070fd418e66f2a069f5c94714da7d Mon Sep 17 00:00:00 2001 From: Araq Date: Thu, 26 Jun 2014 15:52:23 +0200 Subject: [PATCH 005/234] added OEMCP for the default OEM codepage --- lib/pure/encodings.nim | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/pure/encodings.nim b/lib/pure/encodings.nim index 94d21ed4ee..633ea60205 100644 --- a/lib/pure/encodings.nim +++ b/lib/pure/encodings.nim @@ -41,6 +41,7 @@ when defined(windows): const winEncodings = [ + (1, "OEMCP"), # current OEM codepage (037, "IBM037"), # IBM EBCDIC US-Canada (437, "IBM437"), # OEM United States (500, "IBM500"), # IBM EBCDIC International From eed443d4b390b10e710d80619f5a7bc19fefb8d1 Mon Sep 17 00:00:00 2001 From: Araq Date: Thu, 26 Jun 2014 15:58:41 +0200 Subject: [PATCH 006/234] rewrote lambdalifting; fixes deeply nested closures --- bin/empty.txt | 2 +- compiler/ast.nim | 3 +- compiler/lambdalifting.nim | 688 ++++++++++-------- compiler/lowerings.nim | 16 + .../android/scripts/jnibuild.sh | 0 .../android/scripts/nimbuild.sh | 0 .../cross_calculator/android/scripts/tags.sh | 0 examples/cross_calculator/ios/scripts/tags.sh | 0 .../ios/scripts/xcode_prebuild.sh | 0 lib/pure/unidecode/gen.py | 0 lib/system.nim | 3 +- tests/closure/tclosure.nim | 8 +- tests/closure/tnestedclosure.nim | 36 + tinyc/tests/gcctestsuite.sh | 0 tinyc/texi2pod.pl | 0 15 files changed, 458 insertions(+), 298 deletions(-) mode change 100755 => 100644 examples/cross_calculator/android/scripts/jnibuild.sh mode change 100755 => 100644 examples/cross_calculator/android/scripts/nimbuild.sh mode change 100755 => 100644 examples/cross_calculator/android/scripts/tags.sh mode change 100755 => 100644 examples/cross_calculator/ios/scripts/tags.sh mode change 100755 => 100644 examples/cross_calculator/ios/scripts/xcode_prebuild.sh mode change 100755 => 100644 lib/pure/unidecode/gen.py create mode 100644 tests/closure/tnestedclosure.nim mode change 100755 => 100644 tinyc/tests/gcctestsuite.sh mode change 100755 => 100644 tinyc/texi2pod.pl diff --git a/bin/empty.txt b/bin/empty.txt index 6661420738..20f9a91e35 100644 --- a/bin/empty.txt +++ b/bin/empty.txt @@ -1 +1 @@ -This file keeps several tools from deleting this subdirectory. +This file keeps several tools from deleting this subdirectory. diff --git a/compiler/ast.nim b/compiler/ast.nim index eb4574928a..1755dcce9a 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -417,6 +417,7 @@ type # efficiency nfTransf, # node has been transformed nfSem # node has been checked for semantics + nfLL # node has gone through lambda lifting nfDotField # the call can use a dot operator nfDotSetter # the call can use a setter dot operarator nfExplicitCall # x.y() was used instead of x.y @@ -1504,7 +1505,7 @@ proc isGenericRoutine*(s: PSym): bool = proc skipGenericOwner*(s: PSym): PSym = internalAssert s.kind in skProcKinds ## Generic instantiations are owned by their originating generic - ## symbol. This proc skips such owners and goes straigh to the owner + ## symbol. This proc skips such owners and goes straight to the owner ## of the generic itself (the module or the enclosing proc). result = if sfFromGeneric in s.flags: s.owner.owner else: s.owner diff --git a/compiler/lambdalifting.nim b/compiler/lambdalifting.nim index c5b9d0f006..f3398187ac 100644 --- a/compiler/lambdalifting.nim +++ b/compiler/lambdalifting.nim @@ -103,43 +103,50 @@ discard """ """ +# Important things to keep in mind: +# * Don't base the analysis on nkProcDef et al. This doesn't work for +# instantiated (formerly generic) procs. The analysis has to look at nkSym. +# This also means we need to prevent the same proc is processed multiple +# times via the 'processed' set. +# * Keep in mind that the owner of some temporaries used to be unreliable. +# * For closure iterators we merge the "real" potential closure with the +# local storage requirements for efficiency. This means closure iterators +# have slightly different semantics from ordinary closures. + + const upName* = ":up" # field name for the 'up' reference - paramName* = ":env" + paramName* = ":envP" envName* = ":env" type - PInnerContext = ref TInnerContext POuterContext = ref TOuterContext + TIter = object + fn, closureParam, state, resultSym: PSym # most are only valid if + # fn.kind == skClosureIterator + obj: PType + PEnv = ref TEnv - TDep = tuple[e: PEnv, field: PSym] TEnv {.final.} = object of TObject - attachedNode: PNode + attachedNode, replacementNode: PNode createdVar: PSym # if != nil it is a used environment createdVarComesFromIter: bool capturedVars: seq[PSym] # captured variables in this environment - deps: seq[TDep] # dependencies - up: PEnv + up, next: PEnv # outer scope and next to keep all in a list + upField: PSym # if != nil the dependency to the outer scope is used obj: PType - - TInnerContext = object - fn: PSym - closureParam: PSym - localsToAccess: TIdNodeTable + fn: PSym # function that belongs to this scope; + # if up.fn != fn then we cross function boundaries. + # This is an important case to consider. + vars: TIntSet # variables belonging to this environment TOuterContext = object fn: PSym # may also be a module! - currentEnv: PEnv - isIter: bool # first class iterator? + head: PEnv capturedVars, processed: TIntSet - localsToEnv: TIdTable # PSym->PEnv mapping localsToAccess: TIdNodeTable lambdasToEnv: TIdTable # PSym->PEnv mapping - up: POuterContext - - closureParam, state, resultSym: PSym # only if isIter - obj: PType # only if isIter proc getStateType(iter: PSym): PType = var n = newNodeI(nkRange, iter.info) @@ -164,6 +171,7 @@ proc newIterResult(iter: PSym): PSym = iter.ast.add newSymNode(result) proc addHiddenParam(routine: PSym, param: PSym) = + assert param.kind == skParam var params = routine.ast.sons[paramsPos] # -1 is correct here as param.position is 0 based but we have at position 0 # some nkEffect node: @@ -175,7 +183,7 @@ proc addHiddenParam(routine: PSym, param: PSym) = proc getHiddenParam(routine: PSym): PSym = let params = routine.ast.sons[paramsPos] let hidden = lastSon(params) - assert hidden.kind == nkSym + internalAssert hidden.kind == nkSym and hidden.sym.kind == skParam result = hidden.sym proc getEnvParam(routine: PSym): PSym = @@ -184,161 +192,182 @@ proc getEnvParam(routine: PSym): PSym = if hidden.kind == nkSym and hidden.sym.name.s == paramName: result = hidden.sym -proc initIterContext(c: POuterContext, iter: PSym) = - c.fn = iter - c.capturedVars = initIntSet() +proc initIter(iter: PSym): TIter = + result.fn = iter + if iter.kind == skClosureIterator: + var cp = getEnvParam(iter) + if cp == nil: + result.obj = createObj(iter, iter.info) - var cp = getEnvParam(iter) - if cp == nil: - c.obj = createObj(iter, iter.info) + cp = newSym(skParam, getIdent(paramName), iter, iter.info) + incl(cp.flags, sfFromGeneric) + cp.typ = newType(tyRef, iter) + rawAddSon(cp.typ, result.obj) + addHiddenParam(iter, cp) - cp = newSym(skParam, getIdent(paramName), iter, iter.info) - incl(cp.flags, sfFromGeneric) - cp.typ = newType(tyRef, iter) - rawAddSon(cp.typ, c.obj) - addHiddenParam(iter, cp) - - c.state = createStateField(iter) - addField(c.obj, c.state) - else: - c.obj = cp.typ.sons[0] - assert c.obj.kind == tyObject - if c.obj.n.len > 0: - c.state = c.obj.n[0].sym + result.state = createStateField(iter) + rawAddField(result.obj, result.state) else: - c.state = createStateField(iter) - addField(c.obj, c.state) + result.obj = cp.typ.sons[0] + assert result.obj.kind == tyObject + if result.obj.n.len > 0: + result.state = result.obj.n[0].sym + else: + result.state = createStateField(iter) + rawAddField(result.obj, result.state) + result.closureParam = cp + if iter.typ.sons[0] != nil: + result.resultSym = newIterResult(iter) + #iter.ast.add(newSymNode(c.resultSym)) - c.closureParam = cp - if iter.typ.sons[0] != nil: - c.resultSym = newIterResult(iter) - #iter.ast.add(newSymNode(c.resultSym)) - -proc newOuterContext(fn: PSym, up: POuterContext = nil): POuterContext = +proc newOuterContext(fn: PSym): POuterContext = new(result) result.fn = fn result.capturedVars = initIntSet() result.processed = initIntSet() initIdNodeTable(result.localsToAccess) - initIdTable(result.localsToEnv) initIdTable(result.lambdasToEnv) - result.isIter = fn.kind == skClosureIterator - if result.isIter: initIterContext(result, fn) -proc newInnerContext(fn: PSym): PInnerContext = +proc newEnv(o: POuterContext; up: PEnv, n: PNode; owner: PSym): PEnv = new(result) - result.fn = fn - initIdNodeTable(result.localsToAccess) - -proc newEnv(outerProc: PSym, up: PEnv, n: PNode): PEnv = - new(result) - result.deps = @[] result.capturedVars = @[] - result.obj = createObj(outerProc, outerProc.info) + result.obj = createObj(owner, owner.info) result.up = up result.attachedNode = n + result.fn = owner + result.vars = initIntSet() + result.next = o.head + o.head = result proc addCapturedVar(e: PEnv, v: PSym) = for x in e.capturedVars: if x == v: return - # XXX meh, just add the state field for every closure for now, it's too + # YYY meh, just add the state field for every closure for now, it's too # hard to figure out if it comes from a closure iterator: if e.obj.n.len == 0: addField(e.obj, createStateField(v.owner)) e.capturedVars.add(v) addField(e.obj, v) - -proc addDep(e, d: PEnv, owner: PSym): PSym = - for x, field in items(e.deps): - if x == d: return field - var pos = sonsLen(e.obj.n) - result = newSym(skField, getIdent(upName & $pos), owner, owner.info) - result.typ = newType(tyRef, owner) - result.position = pos - assert d.obj != nil - rawAddSon(result.typ, d.obj) - addField(e.obj, result) - e.deps.add((d, result)) proc newCall(a, b: PSym): PNode = result = newNodeI(nkCall, a.info) result.add newSymNode(a) result.add newSymNode(b) -proc isInnerProc(s, outerProc: PSym): bool {.inline.} = - result = s.kind in {skProc, skMethod, skConverter, skClosureIterator} and - s.skipGenericOwner == outerProc +proc isInnerProc(s, outerProc: PSym): bool = + if s.kind in {skProc, skMethod, skConverter, skClosureIterator}: + var owner = s.skipGenericOwner + while true: + if owner.isNil: return false + if owner == outerProc: return true + owner = owner.owner #s.typ.callConv == ccClosure -proc addClosureParam(i: PInnerContext, e: PEnv) = - var cp = getEnvParam(i.fn) +proc addClosureParam(fn: PSym; e: PEnv): PSym = + var cp = getEnvParam(fn) if cp == nil: - cp = newSym(skParam, getIdent(paramName), i.fn, i.fn.info) + cp = newSym(skParam, getIdent(paramName), fn, fn.info) incl(cp.flags, sfFromGeneric) - cp.typ = newType(tyRef, i.fn) + cp.typ = newType(tyRef, fn) rawAddSon(cp.typ, e.obj) - addHiddenParam(i.fn, cp) + addHiddenParam(fn, cp) else: + #assert e.obj == nil or e.obj == cp.typ.sons[0] e.obj = cp.typ.sons[0] assert e.obj.kind == tyObject - i.closureParam = cp - #echo "closure param added for ", i.fn.name.s, " ", i.fn.id - -proc dummyClosureParam(o: POuterContext, i: PInnerContext) = - var e = o.currentEnv - if idTableGet(o.lambdasToEnv, i.fn) == nil: - idTablePut(o.lambdasToEnv, i.fn, e) - if i.closureParam == nil: addClosureParam(i, e) + result = cp proc illegalCapture(s: PSym): bool {.inline.} = result = skipTypes(s.typ, abstractInst).kind in {tyVar, tyOpenArray, tyVarargs} or s.kind == skResult -proc captureVar(o: POuterContext, i: PInnerContext, local: PSym, - info: TLineInfo) = - # for inlined variables the owner is still wrong, so it can happen that it's - # not a captured variable at all ... *sigh* - var it = PEnv(idTableGet(o.localsToEnv, local)) - if it == nil: return - - if illegalCapture(local) or o.fn.id != local.owner.id or - i.fn.typ.callConv notin {ccClosure, ccDefault}: - # Currently captures are restricted to a single level of nesting: - localError(info, errIllegalCaptureX, local.name.s) - i.fn.typ.callConv = ccClosure - #echo "captureVar ", i.fn.name.s, i.fn.id, " ", local.name.s, local.id - - incl(i.fn.typ.flags, tfCapturesEnv) - - # we need to remember which inner most closure belongs to this lambda: - var e = o.currentEnv - if idTableGet(o.lambdasToEnv, i.fn) == nil: - idTablePut(o.lambdasToEnv, i.fn, e) - - # variable already captured: - if idNodeTableGet(i.localsToAccess, local) != nil: return - if i.closureParam == nil: addClosureParam(i, e) - - # check which environment `local` belongs to: - var access = newSymNode(i.closureParam) - addCapturedVar(it, local) - if it == e: - # common case: local directly in current environment: - discard - else: - # it's in some upper environment: - access = indirectAccess(access, addDep(e, it, i.fn), info) - access = indirectAccess(access, local, info) - if o.isIter: - if not containsOrIncl(o.capturedVars, local.id): addField(o.obj, local) - else: - incl(o.capturedVars, local.id) - idNodeTablePut(i.localsToAccess, local, access) - proc interestingVar(s: PSym): bool {.inline.} = result = s.kind in {skVar, skLet, skTemp, skForVar, skParam, skResult} and sfGlobal notin s.flags +proc nestedAccess(top: PEnv; local: PSym): PNode = + # Parts after the transformation are in []: + # + # proc main = + # var [:env.]foo = 23 + # proc outer(:paramO) = + # [var :envO; createClosure(:envO); :envO.up = paramO] + # proc inner(:paramI) = + # echo [:paramI.up.]foo + # inner([:envO]) + # outer([:env]) + if not (interestingVar(local) and top.fn != local.owner): + return nil + # check it's in fact a captured variable: + var it = top + while it != nil: + if it.vars.contains(local.id): break + it = it.up + if it == nil: return nil + let envParam = top.fn.getEnvParam + internalAssert(not envParam.isNil) + var access = newSymNode(envParam) + # we could also simply check the tuple type for the field here, I think. + it = top.up + while it != nil: + if it.vars.contains(local.id): + access = indirectAccess(access, local, local.info) + return access + internalAssert it.upField != nil + access = indirectAccess(access, it.upField, local.info) + it = it.up + return nil + +proc createUpField(obj, fieldType: PType): PSym = + let pos = obj.n.len + result = newSym(skField, getIdent(upName), obj.owner, obj.owner.info) + result.typ = newType(tyRef, obj.owner) + result.position = pos + rawAddSon(result.typ, fieldType) + addField(obj, result) + +proc captureVar(o: POuterContext; top: PEnv; local: PSym; + info: TLineInfo): bool = + # first check if we should be concerned at all: + var it = top + while it != nil: + if it.vars.contains(local.id): break + it = it.up + if it == nil: return false + # yes, so mark every 'up' pointer as taken: + if illegalCapture(local) or top.fn.typ.callConv notin {ccClosure, ccDefault}: + localError(info, errIllegalCaptureX, local.name.s) + it = top + while it != nil: + if it.vars.contains(local.id): break + # keep in mind that the first element of the chain belong to top.fn itself + # and these don't need any upFields + if it.upField == nil and it.up != nil and it.fn != top.fn: + it.upField = createUpField(it.obj, it.up.obj) + + if it.fn != local.owner: + it.fn.typ.callConv = ccClosure + incl(it.fn.typ.flags, tfCapturesEnv) + discard addClosureParam(it.fn, it.up) + + if idTableGet(o.lambdasToEnv, it.fn) == nil: + idTablePut(o.lambdasToEnv, it.fn, it.up) + + it = it.up + # don't do this: 'top' might not require a closure: + #if idTableGet(o.lambdasToEnv, it.fn) == nil: + # idTablePut(o.lambdasToEnv, it.fn, top) + + # mark as captured: + #if top.iter != nil: + # if not containsOrIncl(o.capturedVars, local.id): + # #addField(top.iter.obj, local) + # addCapturedVar(it, local) + #else: + incl(o.capturedVars, local.id) + addCapturedVar(it, local) + result = true + proc semCaptureSym*(s, owner: PSym) = if interestingVar(s) and owner.id != s.owner.id and s.kind != skResult: if owner.typ != nil and not isGenericRoutine(owner): @@ -350,28 +379,20 @@ proc semCaptureSym*(s, owner: PSym) = # since the analysis is not entirely correct, we don't set 'tfCapturesEnv' # here -proc gatherVars(o: POuterContext, i: PInnerContext, n: PNode) = - # gather used vars for closure generation - if n == nil: return +proc gatherVars(o: POuterContext; e: PEnv; n: PNode): int = + # gather used vars for closure generation; returns number of captured vars + if n == nil: return 0 case n.kind of nkSym: var s = n.sym - if interestingVar(s) and i.fn.id != s.owner.id: - captureVar(o, i, s, n.info) - elif s.kind in {skProc, skMethod, skConverter} and - s.skipGenericOwner == o.fn and - tfCapturesEnv in s.typ.flags and s != i.fn: - # call to some other inner proc; we need to track the dependencies for - # this: - let env = PEnv(idTableGet(o.lambdasToEnv, i.fn)) - if env == nil: internalError(n.info, "no environment computed") - if o.currentEnv != env: - discard addDep(o.currentEnv, env, i.fn) - internalError(n.info, "too complex environment handling required") - of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit, nkClosure: discard + if interestingVar(s) and e.fn != s.owner: + if captureVar(o, e, s, n.info): result = 1 + of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit, nkClosure, nkProcDef, + nkMethodDef, nkConverterDef, nkMacroDef, nkTemplateDef, nkTypeSection: + discard else: - for k in countup(0, sonsLen(n) - 1): - gatherVars(o, i, n.sons[k]) + for k in countup(0, sonsLen(n) - 1): + result += gatherVars(o, e, n.sons[k]) proc generateThunk(prc: PNode, dest: PType): PNode = ## Converts 'prc' into '(thunk, nil)' so that it's compatible with @@ -403,61 +424,112 @@ proc makeClosure(prc, env: PSym, info: TLineInfo): PNode = else: result.add(newSymNode(env)) -proc transformInnerProc(o: POuterContext, i: PInnerContext, n: PNode): PNode = +proc newClosureCreationVar(e: PEnv): PSym = + result = newSym(skVar, getIdent(envName), e.fn, e.attachedNode.info) + incl(result.flags, sfShadowed) + result.typ = newType(tyRef, e.fn) + result.typ.rawAddSon(e.obj) + +proc getClosureVar(e: PEnv): PSym = + if e.createdVar == nil: + result = newClosureCreationVar(e) + e.createdVar = result + else: + result = e.createdVar + +proc findEnv(o: POuterContext; s: PSym): PEnv = + var env = o.head + while env != nil: + if env.fn == s: break + env = env.next + internalAssert env != nil and env.up != nil + result = env.up + while result.fn == s: result = result.up + +proc transformInnerProc(o: POuterContext; e: PEnv, n: PNode): PNode = case n.kind of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit: discard of nkSym: let s = n.sym - if s == i.fn: + if s == e.fn: # recursive calls go through (lambda, hiddenParam): - assert i.closureParam != nil, i.fn.name.s - result = makeClosure(s, i.closureParam, n.info) + result = makeClosure(s, getEnvParam(s), n.info) elif isInnerProc(s, o.fn) and s.typ.callConv == ccClosure: - # ugh: call to some other inner proc; - assert i.closureParam != nil - # XXX this is not correct in general! may also be some 'closure.upval' - result = makeClosure(s, i.closureParam, n.info) + # ugh: call to some other inner proc; + result = makeClosure(s, findEnv(o, s).getClosureVar, n.info) else: # captured symbol? - result = idNodeTableGet(i.localsToAccess, n.sym) - of nkLambdaKinds, nkIteratorDef: - if n.typ != nil: - result = transformInnerProc(o, i, n.sons[namePos]) + result = nestedAccess(e, n.sym) + #result = idNodeTableGet(i.localsToAccess, n.sym) + #of nkLambdaKinds, nkIteratorDef: + # if n.typ != nil: + # result = transformInnerProc(o, e, n.sons[namePos]) + #of nkClosure: + # let x = transformInnerProc(o, e, n.sons[0]) + # if x != nil: n.sons[0] = x of nkProcDef, nkMethodDef, nkConverterDef, nkMacroDef, nkTemplateDef, - nkClosure: + nkLambdaKinds, nkIteratorDef, nkClosure: # don't recurse here: discard else: for j in countup(0, sonsLen(n) - 1): - let x = transformInnerProc(o, i, n.sons[j]) + let x = transformInnerProc(o, e, n.sons[j]) if x != nil: n.sons[j] = x proc closureCreationPoint(n: PNode): PNode = - result = newNodeI(nkStmtList, n.info) - result.add(emptyNode) - result.add(n) + if n.kind == nkStmtList and n.len >= 1 and n[0].kind == nkEmpty: + # we already have a free slot + result = n + else: + result = newNodeI(nkStmtList, n.info) + result.add(emptyNode) + result.add(n) + #result.flags.incl nfLL -proc searchForInnerProcs(o: POuterContext, n: PNode) = +proc addParamsToEnv(fn: PSym; env: PEnv) = + let params = fn.typ.n + for i in 1.. declaredBlock. Note: The definition # counts, not the block where it is captured! @@ -481,26 +550,29 @@ proc searchForInnerProcs(o: POuterContext, n: PNode) = if it.kind == nkCommentStmt: discard elif it.kind == nkIdentDefs: var L = sonsLen(it) - if it.sons[0].kind != nkSym: internalError(it.info, "transformOuter") - #echo "set: ", it.sons[0].sym.name.s, " ", o.currentBlock == nil - idTablePut(o.localsToEnv, it.sons[0].sym, o.currentEnv) - searchForInnerProcs(o, it.sons[L-1]) + if it.sons[0].kind == nkSym: + # this can be false for recursive invokations that already + # transformed it into 'env.varName': + env.vars.incl(it.sons[0].sym.id) + searchForInnerProcs(o, it.sons[L-1], env) elif it.kind == nkVarTuple: var L = sonsLen(it) for j in countup(0, L-3): #echo "set: ", it.sons[j].sym.name.s, " ", o.currentBlock == nil - idTablePut(o.localsToEnv, it.sons[j].sym, o.currentEnv) - searchForInnerProcs(o, it.sons[L-1]) + if it.sons[j].kind == nkSym: + env.vars.incl(it.sons[j].sym.id) + searchForInnerProcs(o, it.sons[L-1], env) else: - internalError(it.info, "transformOuter") + internalError(it.info, "searchForInnerProcs") + of nkClosure: + searchForInnerProcs(o, n.sons[0], env) of nkProcDef, nkMethodDef, nkConverterDef, nkMacroDef, nkTemplateDef, - nkClosure, nkTypeSection: + nkTypeSection: # don't recurse here: - # XXX recurse here and setup 'up' pointers discard else: for i in countup(0, sonsLen(n) - 1): - searchForInnerProcs(o, n.sons[i]) + searchForInnerProcs(o, n.sons[i], env) proc newAsgnStmt(le, ri: PNode, info: TLineInfo): PNode = # Bugfix: unfortunately we cannot use 'nkFastAsgn' here as that would @@ -512,19 +584,6 @@ proc newAsgnStmt(le, ri: PNode, info: TLineInfo): PNode = result.sons[0] = le result.sons[1] = ri -proc newClosureCreationVar(o: POuterContext; e: PEnv): PSym = - result = newSym(skVar, getIdent(envName), o.fn, e.attachedNode.info) - incl(result.flags, sfShadowed) - result.typ = newType(tyRef, o.fn) - result.typ.rawAddSon(e.obj) - -proc getClosureVar(o: POuterContext; e: PEnv): PSym = - if e.createdVar == nil: - result = newClosureCreationVar(o, e) - e.createdVar = result - else: - result = e.createdVar - proc rawClosureCreation(o: POuterContext, scope: PEnv; env: PSym): PNode = result = newNodeI(nkStmtList, env.info) var v = newNodeI(nkVarSection, env.info) @@ -548,21 +607,25 @@ proc rawClosureCreation(o: POuterContext, scope: PEnv; env: PSym): PNode = idNodeTablePut(o.localsToAccess, local, fieldAccess) else: result.add(newAsgnStmt(fieldAccess, existing, env.info)) - # add support for 'up' references: - for e, field in items(scope.deps): - # add ``env.up = env2`` - result.add(newAsgnStmt(indirectAccess(env, field, env.info), - newSymNode(getClosureVar(o, e)), env.info)) + if scope.upField != nil: + # "up" chain has been used: + if scope.up.fn != scope.fn: + # crosses function boundary: + result.add(newAsgnStmt(indirectAccess(env, scope.upField, env.info), + newSymNode(getEnvParam(scope.fn)), env.info)) + else: + result.add(newAsgnStmt(indirectAccess(env, scope.upField, env.info), + newSymNode(getClosureVar(scope.up)), env.info)) proc generateClosureCreation(o: POuterContext, scope: PEnv): PNode = - var env = getClosureVar(o, scope) + var env = getClosureVar(scope) result = rawClosureCreation(o, scope, env) proc generateIterClosureCreation(o: POuterContext; env: PEnv; scope: PNode): PSym = if env.createdVarComesFromIter or env.createdVar.isNil: # we have to create a new closure: - result = newClosureCreationVar(o, env) + result = newClosureCreationVar(env) let cc = rawClosureCreation(o, env, result) var insertPoint = scope.sons[0] if insertPoint.kind == nkEmpty: scope.sons[0] = cc @@ -577,21 +640,22 @@ proc generateIterClosureCreation(o: POuterContext; env: PEnv; proc interestingIterVar(s: PSym): bool {.inline.} = result = s.kind in {skVar, skLet, skTemp, skForVar} and sfGlobal notin s.flags -proc transformOuterProc(o: POuterContext, n: PNode): PNode +proc transformOuterProc(o: POuterContext, n: PNode, it: TIter): PNode -proc transformYield(c: POuterContext, n: PNode): PNode = - inc c.state.typ.n.sons[1].intVal - let stateNo = c.state.typ.n.sons[1].intVal +proc transformYield(c: POuterContext, n: PNode, it: TIter): PNode = + inc it.state.typ.n.sons[1].intVal + let stateNo = it.state.typ.n.sons[1].intVal var stateAsgnStmt = newNodeI(nkAsgn, n.info) - stateAsgnStmt.add(indirectAccess(newSymNode(c.closureParam),c.state,n.info)) + stateAsgnStmt.add(rawIndirectAccess(newSymNode(it.closureParam), + it.state, n.info)) stateAsgnStmt.add(newIntTypeNode(nkIntLit, stateNo, getSysType(tyInt))) var retStmt = newNodeI(nkReturnStmt, n.info) if n.sons[0].kind != nkEmpty: var a = newNodeI(nkAsgn, n.sons[0].info) - var retVal = transformOuterProc(c, n.sons[0]) - addSon(a, newSymNode(c.resultSym)) + var retVal = transformOuterProc(c, n.sons[0], it) + addSon(a, newSymNode(it.resultSym)) addSon(a, if retVal.isNil: n.sons[0] else: retVal) retStmt.add(a) else: @@ -605,17 +669,18 @@ proc transformYield(c: POuterContext, n: PNode): PNode = result.add(retStmt) result.add(stateLabelStmt) -proc transformReturn(c: POuterContext, n: PNode): PNode = +proc transformReturn(c: POuterContext, n: PNode, it: TIter): PNode = result = newNodeI(nkStmtList, n.info) var stateAsgnStmt = newNodeI(nkAsgn, n.info) - stateAsgnStmt.add(indirectAccess(newSymNode(c.closureParam),c.state,n.info)) + stateAsgnStmt.add(rawIndirectAccess(newSymNode(it.closureParam), it.state, + n.info)) stateAsgnStmt.add(newIntTypeNode(nkIntLit, -1, getSysType(tyInt))) result.add(stateAsgnStmt) result.add(n) -proc outerProcSons(o: POuterContext, n: PNode) = +proc outerProcSons(o: POuterContext, n: PNode, it: TIter) = for i in countup(0, sonsLen(n) - 1): - let x = transformOuterProc(o, n.sons[i]) + let x = transformOuterProc(o, n.sons[i], it) if x != nil: n.sons[i] = x proc liftIterSym*(n: PNode): PNode = @@ -631,27 +696,106 @@ proc liftIterSym*(n: PNode): PNode = addVar(v, newSymNode(env)) result.add(v) # add 'new' statement: - result.add(newCall(getSysSym"internalNew", env)) + result.add newCall(getSysSym"internalNew", env) result.add makeClosure(iter, env, n.info) -proc transformOuterProc(o: POuterContext, n: PNode): PNode = - if n == nil: return nil +template envActive(env): expr = + (env.capturedVars.len > 0 or env.upField != nil) + +# We have to split up environment creation in 2 steps: +# 1. Generate it and store it in env.replacementNode +# 2. Insert replacementNode into its forseen slot. +# This split is necessary so that assignments belonging to closure +# creation like 'env.param = param' are not transformed +# into 'env.param = env.param'. +proc createEnvironments(o: POuterContext) = + var env = o.head + while env != nil: + if envActive(env): + var scope = env.attachedNode + assert scope.kind == nkStmtList + if scope.sons[0].kind == nkEmpty: + # prepare for closure construction: + env.replacementNode = generateClosureCreation(o, env) + env = env.next + +proc finishEnvironments(o: POuterContext) = + var env = o.head + while env != nil: + if env.replacementNode != nil: + var scope = env.attachedNode + assert scope.kind == nkStmtList + if scope.sons[0].kind == nkEmpty: + # change the empty node to contain the closure construction: + scope.sons[0] = env.replacementNode + env = env.next + +proc transformOuterProcBody(o: POuterContext, n: PNode; it: TIter): PNode = + if nfLL in n.flags: + result = nil + elif it.fn.kind == skClosureIterator: + # unfortunately control flow is still convoluted and we can end up + # multiple times here for the very same iterator. We shield against this + # with some rather primitive check for now: + if n.kind == nkStmtList and n.len > 0: + if n.sons[0].kind == nkGotoState: return nil + if n.len > 1 and n[1].kind == nkStmtList and n[1].len > 0 and + n[1][0].kind == nkGotoState: + return nil + result = newNodeI(nkStmtList, it.fn.info) + var gs = newNodeI(nkGotoState, it.fn.info) + assert it.closureParam != nil + assert it.state != nil + gs.add(rawIndirectAccess(newSymNode(it.closureParam), it.state, it.fn.info)) + result.add(gs) + var state0 = newNodeI(nkState, it.fn.info) + state0.add(newIntNode(nkIntLit, 0)) + result.add(state0) + + let newBody = transformOuterProc(o, n, it) + if newBody != nil: + result.add(newBody) + else: + result.add(n) + + var stateAsgnStmt = newNodeI(nkAsgn, it.fn.info) + stateAsgnStmt.add(rawIndirectAccess(newSymNode(it.closureParam), + it.state, it.fn.info)) + stateAsgnStmt.add(newIntTypeNode(nkIntLit, -1, getSysType(tyInt))) + result.add(stateAsgnStmt) + result.flags.incl nfLL + else: + result = transformOuterProc(o, n, it) + if result != nil: result.flags.incl nfLL + +proc transformOuterProc(o: POuterContext, n: PNode; it: TIter): PNode = + if n == nil or nfLL in n.flags: return nil case n.kind of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit: discard of nkSym: var local = n.sym - if o.isIter and interestingIterVar(local) and o.fn.id == local.owner.id: - if not containsOrIncl(o.capturedVars, local.id): addField(o.obj, local) - return indirectAccess(newSymNode(o.closureParam), local, n.info) + if isInnerProc(local, o.fn) and o.processed.contains(local.id): + o.processed.excl(local.id) + let body = local.getBody + let newBody = transformOuterProcBody(o, body, initIter(local)) + if newBody != nil: + local.ast.sons[bodyPos] = newBody + + if it.fn.kind == skClosureIterator and interestingIterVar(local) and + it.fn == local.owner: + # every local goes through the closure: + if not containsOrIncl(o.capturedVars, local.id): + addField(it.obj, local) + return indirectAccess(newSymNode(it.closureParam), local, n.info) var closure = PEnv(idTableGet(o.lambdasToEnv, local)) - if local.kind == skClosureIterator: # consider: [i1, i2, i1] Since we merged the iterator's closure # with the captured owning variables, we need to generate the # closure generation code again: - if local == o.fn: message(n.info, errRecursiveDependencyX, local.name.s) + if local == o.fn or local == it.fn: + message(n.info, errRecursiveDependencyX, local.name.s) # XXX why doesn't this work? if closure.isNil: return liftIterSym(n) @@ -662,7 +806,6 @@ proc transformOuterProc(o: POuterContext, n: PNode): PNode = if closure != nil: # we need to replace the lambda with '(lambda, env)': - let a = closure.createdVar if a != nil: return makeClosure(local, a, n.info) @@ -678,14 +821,6 @@ proc transformOuterProc(o: POuterContext, n: PNode): PNode = return makeClosure(local, x, n.info) if not contains(o.capturedVars, local.id): return - var env = PEnv(idTableGet(o.localsToEnv, local)) - if env == nil: return - var scope = env.attachedNode - assert scope.kind == nkStmtList - if scope.sons[0].kind == nkEmpty: - # change the empty node to contain the closure construction: - scope.sons[0] = generateClosureCreation(o, env) - # change 'local' to 'closure.local', unless it's a 'byCopy' variable: # if sfByCopy notin local.flags: result = idNodeTableGet(o.localsToAccess, local) @@ -694,73 +829,46 @@ proc transformOuterProc(o: POuterContext, n: PNode): PNode = # to access the local as a local. of nkLambdaKinds, nkIteratorDef: if n.typ != nil: - result = transformOuterProc(o, n.sons[namePos]) + result = transformOuterProc(o, n.sons[namePos], it) of nkProcDef, nkMethodDef, nkConverterDef, nkMacroDef, nkTemplateDef, nkClosure: # don't recurse here: discard of nkHiddenStdConv, nkHiddenSubConv, nkConv: - let x = transformOuterProc(o, n.sons[1]) + let x = transformOuterProc(o, n.sons[1], it) if x != nil: n.sons[1] = x result = transformOuterConv(n) of nkYieldStmt: - if o.isIter: result = transformYield(o, n) - else: outerProcSons(o, n) + if it.fn.kind == skClosureIterator: result = transformYield(o, n, it) + else: outerProcSons(o, n, it) of nkReturnStmt: - if o.isIter: result = transformReturn(o, n) - else: outerProcSons(o, n) + if it.fn.kind == skClosureIterator: result = transformReturn(o, n, it) + else: outerProcSons(o, n, it) else: - outerProcSons(o, n) - -proc liftIterator(c: POuterContext, body: PNode): PNode = - let iter = c.fn - result = newNodeI(nkStmtList, iter.info) - var gs = newNodeI(nkGotoState, iter.info) - gs.add(indirectAccess(newSymNode(c.closureParam), c.state, iter.info)) - result.add(gs) - var state0 = newNodeI(nkState, iter.info) - state0.add(newIntNode(nkIntLit, 0)) - result.add(state0) - - let newBody = transformOuterProc(c, body) - if newBody != nil: - result.add(newBody) - else: - result.add(body) - - var stateAsgnStmt = newNodeI(nkAsgn, iter.info) - stateAsgnStmt.add(indirectAccess(newSymNode(c.closureParam), - c.state,iter.info)) - stateAsgnStmt.add(newIntTypeNode(nkIntLit, -1, getSysType(tyInt))) - result.add(stateAsgnStmt) + outerProcSons(o, n, it) proc liftLambdas*(fn: PSym, body: PNode): PNode = # XXX gCmd == cmdCompileToJS does not suffice! The compiletime stuff needs # the transformation even when compiling to JS ... - if body.kind == nkEmpty or gCmd == cmdCompileToJS: + if body.kind == nkEmpty or gCmd == cmdCompileToJS or + fn.skipGenericOwner.kind != skModule: # ignore forward declaration: result = body else: var o = newOuterContext(fn) let ex = closureCreationPoint(body) - o.currentEnv = newEnv(fn, nil, ex) - # put all params into the environment so they can be captured: - let params = fn.typ.n - for i in 1.. B is 1 discard -proc deepCopy*[T](x: T): T {.magic: "DeepCopy", noSideEffect.} +proc deepCopy*[T](x: T): T {.magic: "DeepCopy", noSideEffect.} = ## performs a deep copy of `x`. This is also used by the code generator ## for the implementation of ``spawn``. + discard when not defined(booting): type diff --git a/tests/closure/tclosure.nim b/tests/closure/tclosure.nim index d9e7b8ee4a..764aaa97d1 100644 --- a/tests/closure/tclosure.nim +++ b/tests/closure/tclosure.nim @@ -1,7 +1,6 @@ discard """ file: "tclosure.nim" - output: "2 4 6 8 10" - disabled: true + output: "1 3 6 11 20" """ # Test the closure implementation @@ -30,7 +29,8 @@ proc testA() = testA() myData.each do (x: int): - write(stout, x) + write(stdout, x) + write(stdout, " ") #OUT 2 4 6 8 10 @@ -42,6 +42,6 @@ type proc getInterf(): ITest = var shared: int - return (setter: proc (x) = shared = x, + return (setter: proc (x: int) = shared = x, getter: proc (): int = return shared) diff --git a/tests/closure/tnestedclosure.nim b/tests/closure/tnestedclosure.nim new file mode 100644 index 0000000000..6a76e003e0 --- /dev/null +++ b/tests/closure/tnestedclosure.nim @@ -0,0 +1,36 @@ +discard """ + output: '''foo88 +23 24foo 88 +foo88 +23 24foo 88''' +""" + +# test nested closure +proc main(param: int) = + var foo = 23 + proc outer(outerParam: string) = + var outerVar = 88 + echo outerParam, outerVar + proc inner() = + block Test: + echo foo, " ", param, outerParam, " ", outerVar + inner() + outer("foo") + +# test simple closure within dummy 'main': +proc dummy = + proc main2(param: int) = + var foo = 23 + proc outer(outerParam: string) = + var outerVar = 88 + echo outerParam, outerVar + proc inner() = + block Test: + echo foo, " ", param, outerParam, " ", outerVar + inner() + outer("foo") + main2(24) + +dummy() + +main(24) diff --git a/tinyc/tests/gcctestsuite.sh b/tinyc/tests/gcctestsuite.sh old mode 100755 new mode 100644 diff --git a/tinyc/texi2pod.pl b/tinyc/texi2pod.pl old mode 100755 new mode 100644 From 7014d0c5c82b942c7e3e299c5b29d28ac70831fe Mon Sep 17 00:00:00 2001 From: Araq Date: Fri, 27 Jun 2014 16:03:11 +0200 Subject: [PATCH 007/234] some progress for jester+async --- compiler/lambdalifting.nim | 77 +- compiler/lowerings.nim | 17 +- compiler/magicsys.nim | 2 + tests/closure/tnestedclosure.nim | 17 +- tests/manyloc/keineschweine/lib/gl.nim | 1536 +++++++ tests/manyloc/keineschweine/lib/glext.nim | 4673 +++++++++++++++++++++ tests/manyloc/keineschweine/lib/glu.nim | 335 ++ tests/manyloc/keineschweine/lib/glut.nim | 438 ++ tests/manyloc/keineschweine/lib/glx.nim | 153 + tests/manyloc/keineschweine/lib/wingl.nim | 368 ++ tests/manyloc/packages/package1/p1.babel | 0 tests/manyloc/packages/package2/p2.babel | 0 12 files changed, 7587 insertions(+), 29 deletions(-) create mode 100644 tests/manyloc/keineschweine/lib/gl.nim create mode 100644 tests/manyloc/keineschweine/lib/glext.nim create mode 100644 tests/manyloc/keineschweine/lib/glu.nim create mode 100644 tests/manyloc/keineschweine/lib/glut.nim create mode 100644 tests/manyloc/keineschweine/lib/glx.nim create mode 100644 tests/manyloc/keineschweine/lib/wingl.nim create mode 100644 tests/manyloc/packages/package1/p1.babel create mode 100644 tests/manyloc/packages/package2/p2.babel diff --git a/compiler/lambdalifting.nim b/compiler/lambdalifting.nim index f3398187ac..402ad7d3de 100644 --- a/compiler/lambdalifting.nim +++ b/compiler/lambdalifting.nim @@ -154,12 +154,20 @@ proc getStateType(iter: PSym): PType = addSon(n, newIntNode(nkIntLit, 0)) result = newType(tyRange, iter) result.n = n - rawAddSon(result, getSysType(tyInt)) + var intType = nilOrSysInt() + if intType.isNil: intType = newType(tyInt, iter) + rawAddSon(result, intType) proc createStateField(iter: PSym): PSym = result = newSym(skField, getIdent(":state"), iter, iter.info) result.typ = getStateType(iter) +proc createEnvObj(owner: PSym): PType = + # YYY meh, just add the state field for every closure for now, it's too + # hard to figure out if it comes from a closure iterator: + result = createObj(owner, owner.info) + rawAddField(result, createStateField(owner)) + proc newIterResult(iter: PSym): PSym = if resultPos < iter.ast.len: result = iter.ast.sons[resultPos].sym @@ -197,24 +205,18 @@ proc initIter(iter: PSym): TIter = if iter.kind == skClosureIterator: var cp = getEnvParam(iter) if cp == nil: - result.obj = createObj(iter, iter.info) + result.obj = createEnvObj(iter) cp = newSym(skParam, getIdent(paramName), iter, iter.info) incl(cp.flags, sfFromGeneric) cp.typ = newType(tyRef, iter) rawAddSon(cp.typ, result.obj) addHiddenParam(iter, cp) - - result.state = createStateField(iter) - rawAddField(result.obj, result.state) else: result.obj = cp.typ.sons[0] assert result.obj.kind == tyObject - if result.obj.n.len > 0: - result.state = result.obj.n[0].sym - else: - result.state = createStateField(iter) - rawAddField(result.obj, result.state) + internalAssert result.obj.n.len > 0 + result.state = result.obj.n[0].sym result.closureParam = cp if iter.typ.sons[0] != nil: result.resultSym = newIterResult(iter) @@ -231,20 +233,26 @@ proc newOuterContext(fn: PSym): POuterContext = proc newEnv(o: POuterContext; up: PEnv, n: PNode; owner: PSym): PEnv = new(result) result.capturedVars = @[] - result.obj = createObj(owner, owner.info) result.up = up result.attachedNode = n result.fn = owner result.vars = initIntSet() result.next = o.head o.head = result + if owner.kind != skModule and (up == nil or up.fn != owner): + if owner.ast == nil: + debug owner + echo owner.name.s + let param = getEnvParam(owner) + if param != nil: + result.obj = param.typ.sons[0] + assert result.obj.kind == tyObject + if result.obj.isNil: + result.obj = createEnvObj(owner) proc addCapturedVar(e: PEnv, v: PSym) = for x in e.capturedVars: if x == v: return - # YYY meh, just add the state field for every closure for now, it's too - # hard to figure out if it comes from a closure iterator: - if e.obj.n.len == 0: addField(e.obj, createStateField(v.owner)) e.capturedVars.add(v) addField(e.obj, v) @@ -262,7 +270,7 @@ proc isInnerProc(s, outerProc: PSym): bool = owner = owner.owner #s.typ.callConv == ccClosure -proc addClosureParam(fn: PSym; e: PEnv): PSym = +proc addClosureParam(fn: PSym; e: PEnv) = var cp = getEnvParam(fn) if cp == nil: cp = newSym(skParam, getIdent(paramName), fn, fn.info) @@ -270,11 +278,9 @@ proc addClosureParam(fn: PSym; e: PEnv): PSym = cp.typ = newType(tyRef, fn) rawAddSon(cp.typ, e.obj) addHiddenParam(fn, cp) - else: - #assert e.obj == nil or e.obj == cp.typ.sons[0] - e.obj = cp.typ.sons[0] - assert e.obj.kind == tyObject - result = cp + #else: + #cp.typ.sons[0] = e.obj + #assert e.obj.kind == tyObject proc illegalCapture(s: PSym): bool {.inline.} = result = skipTypes(s.typ, abstractInst).kind in @@ -296,7 +302,7 @@ proc nestedAccess(top: PEnv; local: PSym): PNode = # echo [:paramI.up.]foo # inner([:envO]) # outer([:env]) - if not (interestingVar(local) and top.fn != local.owner): + if not interestingVar(local) or top.fn == local.owner: return nil # check it's in fact a captured variable: var it = top @@ -307,7 +313,6 @@ proc nestedAccess(top: PEnv; local: PSym): PNode = let envParam = top.fn.getEnvParam internalAssert(not envParam.isNil) var access = newSymNode(envParam) - # we could also simply check the tuple type for the field here, I think. it = top.up while it != nil: if it.vars.contains(local.id): @@ -316,6 +321,17 @@ proc nestedAccess(top: PEnv; local: PSym): PNode = internalAssert it.upField != nil access = indirectAccess(access, it.upField, local.info) it = it.up + when false: + # Type based expression construction works too, but turned out to hide + # other bugs: + while true: + let obj = access.typ.sons[0] + let field = getFieldFromObj(obj, local) + if field != nil: + return rawIndirectAccess(access, field, local.info) + let upField = lookupInRecord(obj.n, getIdent(upName)) + if upField == nil: break + access = rawIndirectAccess(access, upField, local.info) return nil proc createUpField(obj, fieldType: PType): PSym = @@ -324,6 +340,7 @@ proc createUpField(obj, fieldType: PType): PSym = result.typ = newType(tyRef, obj.owner) result.position = pos rawAddSon(result.typ, fieldType) + #rawAddField(obj, result) addField(obj, result) proc captureVar(o: POuterContext; top: PEnv; local: PSym; @@ -348,10 +365,13 @@ proc captureVar(o: POuterContext; top: PEnv; local: PSym; if it.fn != local.owner: it.fn.typ.callConv = ccClosure incl(it.fn.typ.flags, tfCapturesEnv) - discard addClosureParam(it.fn, it.up) + + var u = it.up + while u != nil and u.fn == it.fn: u = u.up + addClosureParam(it.fn, u) if idTableGet(o.lambdasToEnv, it.fn) == nil: - idTablePut(o.lambdasToEnv, it.fn, it.up) + if u != nil: idTablePut(o.lambdasToEnv, it.fn, u) it = it.up # don't do this: 'top' might not require a closure: @@ -521,7 +541,7 @@ proc searchForInnerProcs(o: POuterContext, n: PNode, env: PEnv) = #assert tfCapturesEnv notin n.sym.typ.flags if idTableGet(o.lambdasToEnv, fn) == nil: idTablePut(o.lambdasToEnv, fn, env) - discard addClosureParam(fn, env) + addClosureParam(fn, env) elif fn.getEnvParam != nil: # only transform if it really needs a closure: @@ -616,7 +636,7 @@ proc rawClosureCreation(o: POuterContext, scope: PEnv; env: PSym): PNode = else: result.add(newAsgnStmt(indirectAccess(env, scope.upField, env.info), newSymNode(getClosureVar(scope.up)), env.info)) - + proc generateClosureCreation(o: POuterContext, scope: PEnv): PNode = var env = getClosureVar(scope) result = rawClosureCreation(o, scope, env) @@ -643,6 +663,9 @@ proc interestingIterVar(s: PSym): bool {.inline.} = proc transformOuterProc(o: POuterContext, n: PNode, it: TIter): PNode proc transformYield(c: POuterContext, n: PNode, it: TIter): PNode = + assert it.state != nil + assert it.state.typ != nil + assert it.state.typ.n != nil inc it.state.typ.n.sons[1].intVal let stateNo = it.state.typ.n.sons[1].intVal @@ -867,7 +890,7 @@ proc liftLambdas*(fn: PSym, body: PNode): PNode = discard transformOuterProcBody(o, body, initIter(fn)) result = ex finishEnvironments(o) - #if fn.name.s == "factory" or fn.name.s == "factory2": + #if fn.name.s == "cbOuter" or fn.name.s == "factory2": # echo rendertree(result, {renderIds}) proc liftLambdasForTopLevel*(module: PSym, body: PNode): PNode = diff --git a/compiler/lowerings.nim b/compiler/lowerings.nim index 4a2f6a12b0..e7b5cd9870 100644 --- a/compiler/lowerings.nim +++ b/compiler/lowerings.nim @@ -111,13 +111,28 @@ proc indirectAccess*(a: PNode, b: string, info: TLineInfo): PNode = t = t.sons[0] if t == nil: break t = t.skipTypes(abstractInst) - assert field != nil, b + #if field == nil: + # debug deref.typ + # echo deref.typ.id + internalAssert field != nil, b addSon(deref, a) result = newNodeI(nkDotExpr, info) addSon(result, deref) addSon(result, newSymNode(field)) result.typ = field.typ +proc getFieldFromObj*(t: PType; v: PSym): PSym = + assert v.kind != skField + let fieldName = getIdent(v.name.s & $v.id) + var t = t + while true: + assert t.kind == tyObject + result = getSymFromList(t.n, fieldName) + if result != nil: break + t = t.sons[0] + if t == nil: break + t = t.skipTypes(abstractInst) + proc indirectAccess*(a: PNode, b: PSym, info: TLineInfo): PNode = # returns a[].b as a node result = indirectAccess(a, b.name.s & $b.id, info) diff --git a/compiler/magicsys.nim b/compiler/magicsys.nim index b4f6e043d4..4753261614 100644 --- a/compiler/magicsys.nim +++ b/compiler/magicsys.nim @@ -27,6 +27,8 @@ var gSysTypes: array[TTypeKind, PType] compilerprocs: TStrTable +proc nilOrSysInt*: PType = gSysTypes[tyInt] + proc registerSysType(t: PType) = if gSysTypes[t.kind] == nil: gSysTypes[t.kind] = t diff --git a/tests/closure/tnestedclosure.nim b/tests/closure/tnestedclosure.nim index 6a76e003e0..c8f1e231ba 100644 --- a/tests/closure/tnestedclosure.nim +++ b/tests/closure/tnestedclosure.nim @@ -2,7 +2,8 @@ discard """ output: '''foo88 23 24foo 88 foo88 -23 24foo 88''' +23 24foo 88 +hohoho''' """ # test nested closure @@ -34,3 +35,17 @@ proc dummy = dummy() main(24) + +# Jester + async triggered this bug: +proc cbOuter() = + var response = "hohoho" + block: + proc cbIter() = + block: + proc fooIter() = + echo response + fooIter() + + cbIter() + +cbOuter() diff --git a/tests/manyloc/keineschweine/lib/gl.nim b/tests/manyloc/keineschweine/lib/gl.nim new file mode 100644 index 0000000000..9387b5bc9e --- /dev/null +++ b/tests/manyloc/keineschweine/lib/gl.nim @@ -0,0 +1,1536 @@ +# +# +# Adaption of the delphi3d.net OpenGL units to FreePascal +# Sebastian Guenther (sg@freepascal.org) in 2002 +# These units are free to use +# +#****************************************************************************** +# Converted to Delphi by Tom Nuydens (tom@delphi3d.net) +# For the latest updates, visit Delphi3D: http://www.delphi3d.net +#****************************************************************************** + +when defined(windows): + {.push, callconv: stdcall.} +else: + {.push, callconv: cdecl.} +when defined(windows): + const + dllname* = "opengl32.dll" +elif defined(macosx): + const + dllname* = "/System/Library/Frameworks/OpenGL.framework/Libraries/libGL.dylib" +else: + const + dllname* = "libGL.so.1" +type + PGLenum* = ptr TGLenum + PGLboolean* = ptr TGLboolean + PGLbitfield* = ptr TGLbitfield + TGLbyte* = int8 + PGLbyte* = ptr TGlbyte + PGLshort* = ptr TGLshort + PGLint* = ptr TGLint + PGLsizei* = ptr TGLsizei + PGLubyte* = ptr TGLubyte + PGLushort* = ptr TGLushort + PGLuint* = ptr TGLuint + PGLfloat* = ptr TGLfloat + PGLclampf* = ptr TGLclampf + PGLdouble* = ptr TGLdouble + PGLclampd* = ptr TGLclampd + PGLvoid* = Pointer + PPGLvoid* = ptr PGLvoid + TGLenum* = cint + TGLboolean* = bool + TGLbitfield* = cint + TGLshort* = int16 + TGLint* = cint + TGLsizei* = int + TGLubyte* = int8 + TGLushort* = int16 + TGLuint* = cint + TGLfloat* = float32 + TGLclampf* = float32 + TGLdouble* = float + TGLclampd* = float + +const # Version + GL_VERSION_1_1* = 1 # AccumOp + constGL_ACCUM* = 0x00000100 + GL_LOAD* = 0x00000101 + GL_RETURN* = 0x00000102 + GL_MULT* = 0x00000103 + GL_ADD* = 0x00000104 # AlphaFunction + GL_NEVER* = 0x00000200 + GL_LESS* = 0x00000201 + GL_EQUAL* = 0x00000202 + GL_LEQUAL* = 0x00000203 + GL_GREATER* = 0x00000204 + GL_NOTEQUAL* = 0x00000205 + GL_GEQUAL* = 0x00000206 + GL_ALWAYS* = 0x00000207 # AttribMask + GL_CURRENT_BIT* = 0x00000001 + GL_POINT_BIT* = 0x00000002 + GL_LINE_BIT* = 0x00000004 + GL_POLYGON_BIT* = 0x00000008 + GL_POLYGON_STIPPLE_BIT* = 0x00000010 + GL_PIXEL_MODE_BIT* = 0x00000020 + GL_LIGHTING_BIT* = 0x00000040 + GL_FOG_BIT* = 0x00000080 + GL_DEPTH_BUFFER_BIT* = 0x00000100 + GL_ACCUM_BUFFER_BIT* = 0x00000200 + GL_STENCIL_BUFFER_BIT* = 0x00000400 + GL_VIEWPORT_BIT* = 0x00000800 + GL_TRANSFORM_BIT* = 0x00001000 + GL_ENABLE_BIT* = 0x00002000 + GL_COLOR_BUFFER_BIT* = 0x00004000 + GL_HINT_BIT* = 0x00008000 + GL_EVAL_BIT* = 0x00010000 + GL_LIST_BIT* = 0x00020000 + GL_TEXTURE_BIT* = 0x00040000 + GL_SCISSOR_BIT* = 0x00080000 + GL_ALL_ATTRIB_BITS* = 0x000FFFFF # BeginMode + GL_POINTS* = 0x00000000 + GL_LINES* = 0x00000001 + GL_LINE_LOOP* = 0x00000002 + GL_LINE_STRIP* = 0x00000003 + GL_TRIANGLES* = 0x00000004 + GL_TRIANGLE_STRIP* = 0x00000005 + GL_TRIANGLE_FAN* = 0x00000006 + GL_QUADS* = 0x00000007 + GL_QUAD_STRIP* = 0x00000008 + GL_POLYGON* = 0x00000009 # BlendingFactorDest + GL_ZERO* = 0 + GL_ONE* = 1 + GL_SRC_COLOR* = 0x00000300 + GL_ONE_MINUS_SRC_COLOR* = 0x00000301 + GL_SRC_ALPHA* = 0x00000302 + GL_ONE_MINUS_SRC_ALPHA* = 0x00000303 + GL_DST_ALPHA* = 0x00000304 + GL_ONE_MINUS_DST_ALPHA* = 0x00000305 # BlendingFactorSrc + # GL_ZERO + # GL_ONE + GL_DST_COLOR* = 0x00000306 + GL_ONE_MINUS_DST_COLOR* = 0x00000307 + GL_SRC_ALPHA_SATURATE* = 0x00000308 # GL_SRC_ALPHA + # GL_ONE_MINUS_SRC_ALPHA + # GL_DST_ALPHA + # GL_ONE_MINUS_DST_ALPHA + # Boolean + GL_TRUE* = 1 + GL_FALSE* = 0 # ClearBufferMask + # GL_COLOR_BUFFER_BIT + # GL_ACCUM_BUFFER_BIT + # GL_STENCIL_BUFFER_BIT + # GL_DEPTH_BUFFER_BIT + # ClientArrayType + # GL_VERTEX_ARRAY + # GL_NORMAL_ARRAY + # GL_COLOR_ARRAY + # GL_INDEX_ARRAY + # GL_TEXTURE_COORD_ARRAY + # GL_EDGE_FLAG_ARRAY + # ClipPlaneName + GL_CLIP_PLANE0* = 0x00003000 + GL_CLIP_PLANE1* = 0x00003001 + GL_CLIP_PLANE2* = 0x00003002 + GL_CLIP_PLANE3* = 0x00003003 + GL_CLIP_PLANE4* = 0x00003004 + GL_CLIP_PLANE5* = 0x00003005 # ColorMaterialFace + # GL_FRONT + # GL_BACK + # GL_FRONT_AND_BACK + # ColorMaterialParameter + # GL_AMBIENT + # GL_DIFFUSE + # GL_SPECULAR + # GL_EMISSION + # GL_AMBIENT_AND_DIFFUSE + # ColorPointerType + # GL_BYTE + # GL_UNSIGNED_BYTE + # GL_SHORT + # GL_UNSIGNED_SHORT + # GL_INT + # GL_UNSIGNED_INT + # GL_FLOAT + # GL_DOUBLE + # CullFaceMode + # GL_FRONT + # GL_BACK + # GL_FRONT_AND_BACK + # DataType + GL_BYTE* = 0x00001400 + GL_UNSIGNED_BYTE* = 0x00001401 + GL_SHORT* = 0x00001402 + GL_UNSIGNED_SHORT* = 0x00001403 + GL_INT* = 0x00001404 + GL_UNSIGNED_INT* = 0x00001405 + GL_FLOAT* = 0x00001406 + GL_2_BYTES* = 0x00001407 + GL_3_BYTES* = 0x00001408 + GL_4_BYTES* = 0x00001409 + GL_DOUBLE* = 0x0000140A # DepthFunction + # GL_NEVER + # GL_LESS + # GL_EQUAL + # GL_LEQUAL + # GL_GREATER + # GL_NOTEQUAL + # GL_GEQUAL + # GL_ALWAYS + # DrawBufferMode + GL_NONE* = 0 + GL_FRONT_LEFT* = 0x00000400 + GL_FRONT_RIGHT* = 0x00000401 + GL_BACK_LEFT* = 0x00000402 + GL_BACK_RIGHT* = 0x00000403 + GL_FRONT* = 0x00000404 + GL_BACK* = 0x00000405 + GL_LEFT* = 0x00000406 + GL_RIGHT* = 0x00000407 + GL_FRONT_AND_BACK* = 0x00000408 + GL_AUX0* = 0x00000409 + GL_AUX1* = 0x0000040A + GL_AUX2* = 0x0000040B + GL_AUX3* = 0x0000040C # Enable + # GL_FOG + # GL_LIGHTING + # GL_TEXTURE_1D + # GL_TEXTURE_2D + # GL_LINE_STIPPLE + # GL_POLYGON_STIPPLE + # GL_CULL_FACE + # GL_ALPHA_TEST + # GL_BLEND + # GL_INDEX_LOGIC_OP + # GL_COLOR_LOGIC_OP + # GL_DITHER + # GL_STENCIL_TEST + # GL_DEPTH_TEST + # GL_CLIP_PLANE0 + # GL_CLIP_PLANE1 + # GL_CLIP_PLANE2 + # GL_CLIP_PLANE3 + # GL_CLIP_PLANE4 + # GL_CLIP_PLANE5 + # GL_LIGHT0 + # GL_LIGHT1 + # GL_LIGHT2 + # GL_LIGHT3 + # GL_LIGHT4 + # GL_LIGHT5 + # GL_LIGHT6 + # GL_LIGHT7 + # GL_TEXTURE_GEN_S + # GL_TEXTURE_GEN_T + # GL_TEXTURE_GEN_R + # GL_TEXTURE_GEN_Q + # GL_MAP1_VERTEX_3 + # GL_MAP1_VERTEX_4 + # GL_MAP1_COLOR_4 + # GL_MAP1_INDEX + # GL_MAP1_NORMAL + # GL_MAP1_TEXTURE_COORD_1 + # GL_MAP1_TEXTURE_COORD_2 + # GL_MAP1_TEXTURE_COORD_3 + # GL_MAP1_TEXTURE_COORD_4 + # GL_MAP2_VERTEX_3 + # GL_MAP2_VERTEX_4 + # GL_MAP2_COLOR_4 + # GL_MAP2_INDEX + # GL_MAP2_NORMAL + # GL_MAP2_TEXTURE_COORD_1 + # GL_MAP2_TEXTURE_COORD_2 + # GL_MAP2_TEXTURE_COORD_3 + # GL_MAP2_TEXTURE_COORD_4 + # GL_POINT_SMOOTH + # GL_LINE_SMOOTH + # GL_POLYGON_SMOOTH + # GL_SCISSOR_TEST + # GL_COLOR_MATERIAL + # GL_NORMALIZE + # GL_AUTO_NORMAL + # GL_VERTEX_ARRAY + # GL_NORMAL_ARRAY + # GL_COLOR_ARRAY + # GL_INDEX_ARRAY + # GL_TEXTURE_COORD_ARRAY + # GL_EDGE_FLAG_ARRAY + # GL_POLYGON_OFFSET_POINT + # GL_POLYGON_OFFSET_LINE + # GL_POLYGON_OFFSET_FILL + # ErrorCode + GL_NO_ERROR* = 0 + GL_INVALID_ENUM* = 0x00000500 + GL_INVALID_VALUE* = 0x00000501 + GL_INVALID_OPERATION* = 0x00000502 + GL_STACK_OVERFLOW* = 0x00000503 + GL_STACK_UNDERFLOW* = 0x00000504 + GL_OUT_OF_MEMORY* = 0x00000505 # FeedBackMode + GL_2D* = 0x00000600 + GL_3D* = 0x00000601 + GL_3D_COLOR* = 0x00000602 + GL_3D_COLOR_TEXTURE* = 0x00000603 + GL_4D_COLOR_TEXTURE* = 0x00000604 # FeedBackToken + GL_PASS_THROUGH_TOKEN* = 0x00000700 + GL_POINT_TOKEN* = 0x00000701 + GL_LINE_TOKEN* = 0x00000702 + GL_POLYGON_TOKEN* = 0x00000703 + GL_BITMAP_TOKEN* = 0x00000704 + GL_DRAW_PIXEL_TOKEN* = 0x00000705 + GL_COPY_PIXEL_TOKEN* = 0x00000706 + GL_LINE_RESET_TOKEN* = 0x00000707 # FogMode + # GL_LINEAR + GL_EXP* = 0x00000800 + GL_EXP2* = 0x00000801 # FogParameter + # GL_FOG_COLOR + # GL_FOG_DENSITY + # GL_FOG_END + # GL_FOG_INDEX + # GL_FOG_MODE + # GL_FOG_START + # FrontFaceDirection + GL_CW* = 0x00000900 + GL_CCW* = 0x00000901 # GetMapTarget + GL_COEFF* = 0x00000A00 + GL_ORDER* = 0x00000A01 + GL_DOMAIN* = 0x00000A02 # GetPixelMap + # GL_PIXEL_MAP_I_TO_I + # GL_PIXEL_MAP_S_TO_S + # GL_PIXEL_MAP_I_TO_R + # GL_PIXEL_MAP_I_TO_G + # GL_PIXEL_MAP_I_TO_B + # GL_PIXEL_MAP_I_TO_A + # GL_PIXEL_MAP_R_TO_R + # GL_PIXEL_MAP_G_TO_G + # GL_PIXEL_MAP_B_TO_B + # GL_PIXEL_MAP_A_TO_A + # GetPointerTarget + # GL_VERTEX_ARRAY_POINTER + # GL_NORMAL_ARRAY_POINTER + # GL_COLOR_ARRAY_POINTER + # GL_INDEX_ARRAY_POINTER + # GL_TEXTURE_COORD_ARRAY_POINTER + # GL_EDGE_FLAG_ARRAY_POINTER + # GetTarget + GL_CURRENT_COLOR* = 0x00000B00 + GL_CURRENT_INDEX* = 0x00000B01 + GL_CURRENT_NORMAL* = 0x00000B02 + GL_CURRENT_TEXTURE_COORDS* = 0x00000B03 + GL_CURRENT_RASTER_COLOR* = 0x00000B04 + GL_CURRENT_RASTER_INDEX* = 0x00000B05 + GL_CURRENT_RASTER_TEXTURE_COORDS* = 0x00000B06 + GL_CURRENT_RASTER_POSITION* = 0x00000B07 + GL_CURRENT_RASTER_POSITION_VALID* = 0x00000B08 + GL_CURRENT_RASTER_DISTANCE* = 0x00000B09 + GL_POINT_SMOOTH* = 0x00000B10 + constGL_POINT_SIZE* = 0x00000B11 + GL_POINT_SIZE_RANGE* = 0x00000B12 + GL_POINT_SIZE_GRANULARITY* = 0x00000B13 + GL_LINE_SMOOTH* = 0x00000B20 + constGL_LINE_WIDTH* = 0x00000B21 + GL_LINE_WIDTH_RANGE* = 0x00000B22 + GL_LINE_WIDTH_GRANULARITY* = 0x00000B23 + constGL_LINE_STIPPLE* = 0x00000B24 + GL_LINE_STIPPLE_PATTERN* = 0x00000B25 + GL_LINE_STIPPLE_REPEAT* = 0x00000B26 + GL_LIST_MODE* = 0x00000B30 + GL_MAX_LIST_NESTING* = 0x00000B31 + constGL_LIST_BASE* = 0x00000B32 + GL_LIST_INDEX* = 0x00000B33 + constGL_POLYGON_MODE* = 0x00000B40 + GL_POLYGON_SMOOTH* = 0x00000B41 + constGL_POLYGON_STIPPLE* = 0x00000B42 + constGL_EDGE_FLAG* = 0x00000B43 + constGL_CULL_FACE* = 0x00000B44 + GL_CULL_FACE_MODE* = 0x00000B45 + constGL_FRONT_FACE* = 0x00000B46 + GL_LIGHTING* = 0x00000B50 + GL_LIGHT_MODEL_LOCAL_VIEWER* = 0x00000B51 + GL_LIGHT_MODEL_TWO_SIDE* = 0x00000B52 + GL_LIGHT_MODEL_AMBIENT* = 0x00000B53 + constGL_SHADE_MODEL* = 0x00000B54 + GL_COLOR_MATERIAL_FACE* = 0x00000B55 + GL_COLOR_MATERIAL_PARAMETER* = 0x00000B56 + constGL_COLOR_MATERIAL* = 0x00000B57 + GL_FOG* = 0x00000B60 + GL_FOG_INDEX* = 0x00000B61 + GL_FOG_DENSITY* = 0x00000B62 + GL_FOG_START* = 0x00000B63 + GL_FOG_END* = 0x00000B64 + GL_FOG_MODE* = 0x00000B65 + GL_FOG_COLOR* = 0x00000B66 + constGL_DEPTH_RANGE* = 0x00000B70 + GL_DEPTH_TEST* = 0x00000B71 + GL_DEPTH_WRITEMASK* = 0x00000B72 + GL_DEPTH_CLEAR_VALUE* = 0x00000B73 + constGL_DEPTH_FUNC* = 0x00000B74 + GL_ACCUM_CLEAR_VALUE* = 0x00000B80 + GL_STENCIL_TEST* = 0x00000B90 + GL_STENCIL_CLEAR_VALUE* = 0x00000B91 + constGL_STENCIL_FUNC* = 0x00000B92 + GL_STENCIL_VALUE_MASK* = 0x00000B93 + GL_STENCIL_FAIL* = 0x00000B94 + GL_STENCIL_PASS_DEPTH_FAIL* = 0x00000B95 + GL_STENCIL_PASS_DEPTH_PASS* = 0x00000B96 + GL_STENCIL_REF* = 0x00000B97 + GL_STENCIL_WRITEMASK* = 0x00000B98 + constGL_MATRIX_MODE* = 0x00000BA0 + GL_NORMALIZE* = 0x00000BA1 + constGL_VIEWPORT* = 0x00000BA2 + GL_MODELVIEW_STACK_DEPTH* = 0x00000BA3 + GL_PROJECTION_STACK_DEPTH* = 0x00000BA4 + GL_TEXTURE_STACK_DEPTH* = 0x00000BA5 + GL_MODELVIEW_MATRIX* = 0x00000BA6 + GL_PROJECTION_MATRIX* = 0x00000BA7 + GL_TEXTURE_MATRIX* = 0x00000BA8 + GL_ATTRIB_STACK_DEPTH* = 0x00000BB0 + GL_CLIENT_ATTRIB_STACK_DEPTH* = 0x00000BB1 + GL_ALPHA_TEST* = 0x00000BC0 + GL_ALPHA_TEST_FUNC* = 0x00000BC1 + GL_ALPHA_TEST_REF* = 0x00000BC2 + GL_DITHER* = 0x00000BD0 + GL_BLEND_DST* = 0x00000BE0 + GL_BLEND_SRC* = 0x00000BE1 + GL_BLEND* = 0x00000BE2 + GL_LOGIC_OP_MODE* = 0x00000BF0 + GL_INDEX_LOGIC_OP* = 0x00000BF1 + GL_COLOR_LOGIC_OP* = 0x00000BF2 + GL_AUX_BUFFERS* = 0x00000C00 + constGL_DRAW_BUFFER* = 0x00000C01 + constGL_READ_BUFFER* = 0x00000C02 + GL_SCISSOR_BOX* = 0x00000C10 + GL_SCISSOR_TEST* = 0x00000C11 + GL_INDEX_CLEAR_VALUE* = 0x00000C20 + GL_INDEX_WRITEMASK* = 0x00000C21 + GL_COLOR_CLEAR_VALUE* = 0x00000C22 + GL_COLOR_WRITEMASK* = 0x00000C23 + GL_INDEX_MODE* = 0x00000C30 + GL_RGBA_MODE* = 0x00000C31 + GL_DOUBLEBUFFER* = 0x00000C32 + GL_STEREO* = 0x00000C33 + constGL_RENDER_MODE* = 0x00000C40 + GL_PERSPECTIVE_CORRECTION_HINT* = 0x00000C50 + GL_POINT_SMOOTH_HINT* = 0x00000C51 + GL_LINE_SMOOTH_HINT* = 0x00000C52 + GL_POLYGON_SMOOTH_HINT* = 0x00000C53 + GL_FOG_HINT* = 0x00000C54 + GL_TEXTURE_GEN_S* = 0x00000C60 + GL_TEXTURE_GEN_T* = 0x00000C61 + GL_TEXTURE_GEN_R* = 0x00000C62 + GL_TEXTURE_GEN_Q* = 0x00000C63 + GL_PIXEL_MAP_I_TO_I* = 0x00000C70 + GL_PIXEL_MAP_S_TO_S* = 0x00000C71 + GL_PIXEL_MAP_I_TO_R* = 0x00000C72 + GL_PIXEL_MAP_I_TO_G* = 0x00000C73 + GL_PIXEL_MAP_I_TO_B* = 0x00000C74 + GL_PIXEL_MAP_I_TO_A* = 0x00000C75 + GL_PIXEL_MAP_R_TO_R* = 0x00000C76 + GL_PIXEL_MAP_G_TO_G* = 0x00000C77 + GL_PIXEL_MAP_B_TO_B* = 0x00000C78 + GL_PIXEL_MAP_A_TO_A* = 0x00000C79 + GL_PIXEL_MAP_I_TO_I_SIZE* = 0x00000CB0 + GL_PIXEL_MAP_S_TO_S_SIZE* = 0x00000CB1 + GL_PIXEL_MAP_I_TO_R_SIZE* = 0x00000CB2 + GL_PIXEL_MAP_I_TO_G_SIZE* = 0x00000CB3 + GL_PIXEL_MAP_I_TO_B_SIZE* = 0x00000CB4 + GL_PIXEL_MAP_I_TO_A_SIZE* = 0x00000CB5 + GL_PIXEL_MAP_R_TO_R_SIZE* = 0x00000CB6 + GL_PIXEL_MAP_G_TO_G_SIZE* = 0x00000CB7 + GL_PIXEL_MAP_B_TO_B_SIZE* = 0x00000CB8 + GL_PIXEL_MAP_A_TO_A_SIZE* = 0x00000CB9 + GL_UNPACK_SWAP_BYTES* = 0x00000CF0 + GL_UNPACK_LSB_FIRST* = 0x00000CF1 + GL_UNPACK_ROW_LENGTH* = 0x00000CF2 + GL_UNPACK_SKIP_ROWS* = 0x00000CF3 + GL_UNPACK_SKIP_PIXELS* = 0x00000CF4 + GL_UNPACK_ALIGNMENT* = 0x00000CF5 + GL_PACK_SWAP_BYTES* = 0x00000D00 + GL_PACK_LSB_FIRST* = 0x00000D01 + GL_PACK_ROW_LENGTH* = 0x00000D02 + GL_PACK_SKIP_ROWS* = 0x00000D03 + GL_PACK_SKIP_PIXELS* = 0x00000D04 + GL_PACK_ALIGNMENT* = 0x00000D05 + GL_MAP_COLOR* = 0x00000D10 + GL_MAP_STENCIL* = 0x00000D11 + GL_INDEX_SHIFT* = 0x00000D12 + GL_INDEX_OFFSET* = 0x00000D13 + GL_RED_SCALE* = 0x00000D14 + GL_RED_BIAS* = 0x00000D15 + GL_ZOOM_X* = 0x00000D16 + GL_ZOOM_Y* = 0x00000D17 + GL_GREEN_SCALE* = 0x00000D18 + GL_GREEN_BIAS* = 0x00000D19 + GL_BLUE_SCALE* = 0x00000D1A + GL_BLUE_BIAS* = 0x00000D1B + GL_ALPHA_SCALE* = 0x00000D1C + GL_ALPHA_BIAS* = 0x00000D1D + GL_DEPTH_SCALE* = 0x00000D1E + GL_DEPTH_BIAS* = 0x00000D1F + GL_MAX_EVAL_ORDER* = 0x00000D30 + GL_MAX_LIGHTS* = 0x00000D31 + GL_MAX_CLIP_PLANES* = 0x00000D32 + GL_MAX_TEXTURE_SIZE* = 0x00000D33 + GL_MAX_PIXEL_MAP_TABLE* = 0x00000D34 + GL_MAX_ATTRIB_STACK_DEPTH* = 0x00000D35 + GL_MAX_MODELVIEW_STACK_DEPTH* = 0x00000D36 + GL_MAX_NAME_STACK_DEPTH* = 0x00000D37 + GL_MAX_PROJECTION_STACK_DEPTH* = 0x00000D38 + GL_MAX_TEXTURE_STACK_DEPTH* = 0x00000D39 + GL_MAX_VIEWPORT_DIMS* = 0x00000D3A + GL_MAX_CLIENT_ATTRIB_STACK_DEPTH* = 0x00000D3B + GL_SUBPIXEL_BITS* = 0x00000D50 + GL_INDEX_BITS* = 0x00000D51 + GL_RED_BITS* = 0x00000D52 + GL_GREEN_BITS* = 0x00000D53 + GL_BLUE_BITS* = 0x00000D54 + GL_ALPHA_BITS* = 0x00000D55 + GL_DEPTH_BITS* = 0x00000D56 + GL_STENCIL_BITS* = 0x00000D57 + GL_ACCUM_RED_BITS* = 0x00000D58 + GL_ACCUM_GREEN_BITS* = 0x00000D59 + GL_ACCUM_BLUE_BITS* = 0x00000D5A + GL_ACCUM_ALPHA_BITS* = 0x00000D5B + GL_NAME_STACK_DEPTH* = 0x00000D70 + GL_AUTO_NORMAL* = 0x00000D80 + GL_MAP1_COLOR_4* = 0x00000D90 + GL_MAP1_INDEX* = 0x00000D91 + GL_MAP1_NORMAL* = 0x00000D92 + GL_MAP1_TEXTURE_COORD_1* = 0x00000D93 + GL_MAP1_TEXTURE_COORD_2* = 0x00000D94 + GL_MAP1_TEXTURE_COORD_3* = 0x00000D95 + GL_MAP1_TEXTURE_COORD_4* = 0x00000D96 + GL_MAP1_VERTEX_3* = 0x00000D97 + GL_MAP1_VERTEX_4* = 0x00000D98 + GL_MAP2_COLOR_4* = 0x00000DB0 + GL_MAP2_INDEX* = 0x00000DB1 + GL_MAP2_NORMAL* = 0x00000DB2 + GL_MAP2_TEXTURE_COORD_1* = 0x00000DB3 + GL_MAP2_TEXTURE_COORD_2* = 0x00000DB4 + GL_MAP2_TEXTURE_COORD_3* = 0x00000DB5 + GL_MAP2_TEXTURE_COORD_4* = 0x00000DB6 + GL_MAP2_VERTEX_3* = 0x00000DB7 + GL_MAP2_VERTEX_4* = 0x00000DB8 + GL_MAP1_GRID_DOMAIN* = 0x00000DD0 + GL_MAP1_GRID_SEGMENTS* = 0x00000DD1 + GL_MAP2_GRID_DOMAIN* = 0x00000DD2 + GL_MAP2_GRID_SEGMENTS* = 0x00000DD3 + GL_TEXTURE_1D* = 0x00000DE0 + GL_TEXTURE_2D* = 0x00000DE1 + GL_FEEDBACK_BUFFER_POINTER* = 0x00000DF0 + GL_FEEDBACK_BUFFER_SIZE* = 0x00000DF1 + GL_FEEDBACK_BUFFER_TYPE* = 0x00000DF2 + GL_SELECTION_BUFFER_POINTER* = 0x00000DF3 + GL_SELECTION_BUFFER_SIZE* = 0x00000DF4 # GL_TEXTURE_BINDING_1D + # GL_TEXTURE_BINDING_2D + # GL_VERTEX_ARRAY + # GL_NORMAL_ARRAY + # GL_COLOR_ARRAY + # GL_INDEX_ARRAY + # GL_TEXTURE_COORD_ARRAY + # GL_EDGE_FLAG_ARRAY + # GL_VERTEX_ARRAY_SIZE + # GL_VERTEX_ARRAY_TYPE + # GL_VERTEX_ARRAY_STRIDE + # GL_NORMAL_ARRAY_TYPE + # GL_NORMAL_ARRAY_STRIDE + # GL_COLOR_ARRAY_SIZE + # GL_COLOR_ARRAY_TYPE + # GL_COLOR_ARRAY_STRIDE + # GL_INDEX_ARRAY_TYPE + # GL_INDEX_ARRAY_STRIDE + # GL_TEXTURE_COORD_ARRAY_SIZE + # GL_TEXTURE_COORD_ARRAY_TYPE + # GL_TEXTURE_COORD_ARRAY_STRIDE + # GL_EDGE_FLAG_ARRAY_STRIDE + # GL_POLYGON_OFFSET_FACTOR + # GL_POLYGON_OFFSET_UNITS + # GetTextureParameter + # GL_TEXTURE_MAG_FILTER + # GL_TEXTURE_MIN_FILTER + # GL_TEXTURE_WRAP_S + # GL_TEXTURE_WRAP_T + GL_TEXTURE_WIDTH* = 0x00001000 + GL_TEXTURE_HEIGHT* = 0x00001001 + GL_TEXTURE_INTERNAL_FORMAT* = 0x00001003 + GL_TEXTURE_BORDER_COLOR* = 0x00001004 + GL_TEXTURE_BORDER* = 0x00001005 # GL_TEXTURE_RED_SIZE + # GL_TEXTURE_GREEN_SIZE + # GL_TEXTURE_BLUE_SIZE + # GL_TEXTURE_ALPHA_SIZE + # GL_TEXTURE_LUMINANCE_SIZE + # GL_TEXTURE_INTENSITY_SIZE + # GL_TEXTURE_PRIORITY + # GL_TEXTURE_RESIDENT + # HintMode + GL_DONT_CARE* = 0x00001100 + GL_FASTEST* = 0x00001101 + GL_NICEST* = 0x00001102 # HintTarget + # GL_PERSPECTIVE_CORRECTION_HINT + # GL_POINT_SMOOTH_HINT + # GL_LINE_SMOOTH_HINT + # GL_POLYGON_SMOOTH_HINT + # GL_FOG_HINT + # IndexPointerType + # GL_SHORT + # GL_INT + # GL_FLOAT + # GL_DOUBLE + # LightModelParameter + # GL_LIGHT_MODEL_AMBIENT + # GL_LIGHT_MODEL_LOCAL_VIEWER + # GL_LIGHT_MODEL_TWO_SIDE + # LightName + GL_LIGHT0* = 0x00004000 + GL_LIGHT1* = 0x00004001 + GL_LIGHT2* = 0x00004002 + GL_LIGHT3* = 0x00004003 + GL_LIGHT4* = 0x00004004 + GL_LIGHT5* = 0x00004005 + GL_LIGHT6* = 0x00004006 + GL_LIGHT7* = 0x00004007 # LightParameter + GL_AMBIENT* = 0x00001200 + GL_DIFFUSE* = 0x00001201 + GL_SPECULAR* = 0x00001202 + GL_POSITION* = 0x00001203 + GL_SPOT_DIRECTION* = 0x00001204 + GL_SPOT_EXPONENT* = 0x00001205 + GL_SPOT_CUTOFF* = 0x00001206 + GL_CONSTANT_ATTENUATION* = 0x00001207 + GL_LINEAR_ATTENUATION* = 0x00001208 + GL_QUADRATIC_ATTENUATION* = 0x00001209 # InterleavedArrays + # GL_V2F + # GL_V3F + # GL_C4UB_V2F + # GL_C4UB_V3F + # GL_C3F_V3F + # GL_N3F_V3F + # GL_C4F_N3F_V3F + # GL_T2F_V3F + # GL_T4F_V4F + # GL_T2F_C4UB_V3F + # GL_T2F_C3F_V3F + # GL_T2F_N3F_V3F + # GL_T2F_C4F_N3F_V3F + # GL_T4F_C4F_N3F_V4F + # ListMode + GL_COMPILE* = 0x00001300 + GL_COMPILE_AND_EXECUTE* = 0x00001301 # ListNameType + # GL_BYTE + # GL_UNSIGNED_BYTE + # GL_SHORT + # GL_UNSIGNED_SHORT + # GL_INT + # GL_UNSIGNED_INT + # GL_FLOAT + # GL_2_BYTES + # GL_3_BYTES + # GL_4_BYTES + # LogicOp + constGL_CLEAR* = 0x00001500 + GL_AND* = 0x00001501 + GL_AND_REVERSE* = 0x00001502 + GL_COPY* = 0x00001503 + GL_AND_INVERTED* = 0x00001504 + GL_NOOP* = 0x00001505 + GL_XOR* = 0x00001506 + GL_OR* = 0x00001507 + GL_NOR* = 0x00001508 + GL_EQUIV* = 0x00001509 + GL_INVERT* = 0x0000150A + GL_OR_REVERSE* = 0x0000150B + GL_COPY_INVERTED* = 0x0000150C + GL_OR_INVERTED* = 0x0000150D + GL_NAND* = 0x0000150E + GL_SET* = 0x0000150F # MapTarget + # GL_MAP1_COLOR_4 + # GL_MAP1_INDEX + # GL_MAP1_NORMAL + # GL_MAP1_TEXTURE_COORD_1 + # GL_MAP1_TEXTURE_COORD_2 + # GL_MAP1_TEXTURE_COORD_3 + # GL_MAP1_TEXTURE_COORD_4 + # GL_MAP1_VERTEX_3 + # GL_MAP1_VERTEX_4 + # GL_MAP2_COLOR_4 + # GL_MAP2_INDEX + # GL_MAP2_NORMAL + # GL_MAP2_TEXTURE_COORD_1 + # GL_MAP2_TEXTURE_COORD_2 + # GL_MAP2_TEXTURE_COORD_3 + # GL_MAP2_TEXTURE_COORD_4 + # GL_MAP2_VERTEX_3 + # GL_MAP2_VERTEX_4 + # MaterialFace + # GL_FRONT + # GL_BACK + # GL_FRONT_AND_BACK + # MaterialParameter + GL_EMISSION* = 0x00001600 + GL_SHININESS* = 0x00001601 + GL_AMBIENT_AND_DIFFUSE* = 0x00001602 + GL_COLOR_INDEXES* = 0x00001603 # GL_AMBIENT + # GL_DIFFUSE + # GL_SPECULAR + # MatrixMode + GL_MODELVIEW* = 0x00001700 + GL_PROJECTION* = 0x00001701 + GL_TEXTURE* = 0x00001702 # MeshMode1 + # GL_POINT + # GL_LINE + # MeshMode2 + # GL_POINT + # GL_LINE + # GL_FILL + # NormalPointerType + # GL_BYTE + # GL_SHORT + # GL_INT + # GL_FLOAT + # GL_DOUBLE + # PixelCopyType + GL_COLOR* = 0x00001800 + GL_DEPTH* = 0x00001801 + GL_STENCIL* = 0x00001802 # PixelFormat + GL_COLOR_INDEX* = 0x00001900 + GL_STENCIL_INDEX* = 0x00001901 + GL_DEPTH_COMPONENT* = 0x00001902 + GL_RED* = 0x00001903 + GL_GREEN* = 0x00001904 + GL_BLUE* = 0x00001905 + GL_ALPHA* = 0x00001906 + GL_RGB* = 0x00001907 + GL_RGBA* = 0x00001908 + GL_LUMINANCE* = 0x00001909 + GL_LUMINANCE_ALPHA* = 0x0000190A # PixelMap + # GL_PIXEL_MAP_I_TO_I + # GL_PIXEL_MAP_S_TO_S + # GL_PIXEL_MAP_I_TO_R + # GL_PIXEL_MAP_I_TO_G + # GL_PIXEL_MAP_I_TO_B + # GL_PIXEL_MAP_I_TO_A + # GL_PIXEL_MAP_R_TO_R + # GL_PIXEL_MAP_G_TO_G + # GL_PIXEL_MAP_B_TO_B + # GL_PIXEL_MAP_A_TO_A + # PixelStore + # GL_UNPACK_SWAP_BYTES + # GL_UNPACK_LSB_FIRST + # GL_UNPACK_ROW_LENGTH + # GL_UNPACK_SKIP_ROWS + # GL_UNPACK_SKIP_PIXELS + # GL_UNPACK_ALIGNMENT + # GL_PACK_SWAP_BYTES + # GL_PACK_LSB_FIRST + # GL_PACK_ROW_LENGTH + # GL_PACK_SKIP_ROWS + # GL_PACK_SKIP_PIXELS + # GL_PACK_ALIGNMENT + # PixelTransfer + # GL_MAP_COLOR + # GL_MAP_STENCIL + # GL_INDEX_SHIFT + # GL_INDEX_OFFSET + # GL_RED_SCALE + # GL_RED_BIAS + # GL_GREEN_SCALE + # GL_GREEN_BIAS + # GL_BLUE_SCALE + # GL_BLUE_BIAS + # GL_ALPHA_SCALE + # GL_ALPHA_BIAS + # GL_DEPTH_SCALE + # GL_DEPTH_BIAS + # PixelType + constGL_BITMAP* = 0x00001A00 + GL_POINT* = 0x00001B00 + GL_LINE* = 0x00001B01 + GL_FILL* = 0x00001B02 # ReadBufferMode + # GL_FRONT_LEFT + # GL_FRONT_RIGHT + # GL_BACK_LEFT + # GL_BACK_RIGHT + # GL_FRONT + # GL_BACK + # GL_LEFT + # GL_RIGHT + # GL_AUX0 + # GL_AUX1 + # GL_AUX2 + # GL_AUX3 + # RenderingMode + GL_RENDER* = 0x00001C00 + GL_FEEDBACK* = 0x00001C01 + GL_SELECT* = 0x00001C02 # ShadingModel + GL_FLAT* = 0x00001D00 + GL_SMOOTH* = 0x00001D01 # StencilFunction + # GL_NEVER + # GL_LESS + # GL_EQUAL + # GL_LEQUAL + # GL_GREATER + # GL_NOTEQUAL + # GL_GEQUAL + # GL_ALWAYS + # StencilOp + # GL_ZERO + GL_KEEP* = 0x00001E00 + GL_REPLACE* = 0x00001E01 + GL_INCR* = 0x00001E02 + GL_DECR* = 0x00001E03 # GL_INVERT + # StringName + GL_VENDOR* = 0x00001F00 + GL_RENDERER* = 0x00001F01 + GL_VERSION* = 0x00001F02 + GL_EXTENSIONS* = 0x00001F03 # TextureCoordName + GL_S* = 0x00002000 + GL_T* = 0x00002001 + GL_R* = 0x00002002 + GL_Q* = 0x00002003 # TexCoordPointerType + # GL_SHORT + # GL_INT + # GL_FLOAT + # GL_DOUBLE + # TextureEnvMode + GL_MODULATE* = 0x00002100 + GL_DECAL* = 0x00002101 # GL_BLEND + # GL_REPLACE + # TextureEnvParameter + GL_TEXTURE_ENV_MODE* = 0x00002200 + GL_TEXTURE_ENV_COLOR* = 0x00002201 # TextureEnvTarget + GL_TEXTURE_ENV* = 0x00002300 # TextureGenMode + GL_EYE_LINEAR* = 0x00002400 + GL_OBJECT_LINEAR* = 0x00002401 + GL_SPHERE_MAP* = 0x00002402 # TextureGenParameter + GL_TEXTURE_GEN_MODE* = 0x00002500 + GL_OBJECT_PLANE* = 0x00002501 + GL_EYE_PLANE* = 0x00002502 # TextureMagFilter + GL_NEAREST* = 0x00002600 + GL_LINEAR* = 0x00002601 # TextureMinFilter + # GL_NEAREST + # GL_LINEAR + GL_NEAREST_MIPMAP_NEAREST* = 0x00002700 + GL_LINEAR_MIPMAP_NEAREST* = 0x00002701 + GL_NEAREST_MIPMAP_LINEAR* = 0x00002702 + GL_LINEAR_MIPMAP_LINEAR* = 0x00002703 # TextureParameterName + GL_TEXTURE_MAG_FILTER* = 0x00002800 + GL_TEXTURE_MIN_FILTER* = 0x00002801 + GL_TEXTURE_WRAP_S* = 0x00002802 + GL_TEXTURE_WRAP_T* = 0x00002803 # GL_TEXTURE_BORDER_COLOR + # GL_TEXTURE_PRIORITY + # TextureTarget + # GL_TEXTURE_1D + # GL_TEXTURE_2D + # GL_PROXY_TEXTURE_1D + # GL_PROXY_TEXTURE_2D + # TextureWrapMode + GL_CLAMP* = 0x00002900 + GL_REPEAT* = 0x00002901 # VertexPointerType + # GL_SHORT + # GL_INT + # GL_FLOAT + # GL_DOUBLE + # ClientAttribMask + GL_CLIENT_PIXEL_STORE_BIT* = 0x00000001 + GL_CLIENT_VERTEX_ARRAY_BIT* = 0x00000002 + GL_CLIENT_ALL_ATTRIB_BITS* = 0xFFFFFFFF # polygon_offset + GL_POLYGON_OFFSET_FACTOR* = 0x00008038 + GL_POLYGON_OFFSET_UNITS* = 0x00002A00 + GL_POLYGON_OFFSET_POINT* = 0x00002A01 + GL_POLYGON_OFFSET_LINE* = 0x00002A02 + GL_POLYGON_OFFSET_FILL* = 0x00008037 # texture + GL_ALPHA4* = 0x0000803B + GL_ALPHA8* = 0x0000803C + GL_ALPHA12* = 0x0000803D + GL_ALPHA16* = 0x0000803E + GL_LUMINANCE4* = 0x0000803F + GL_LUMINANCE8* = 0x00008040 + GL_LUMINANCE12* = 0x00008041 + GL_LUMINANCE16* = 0x00008042 + GL_LUMINANCE4_ALPHA4* = 0x00008043 + GL_LUMINANCE6_ALPHA2* = 0x00008044 + GL_LUMINANCE8_ALPHA8* = 0x00008045 + GL_LUMINANCE12_ALPHA4* = 0x00008046 + GL_LUMINANCE12_ALPHA12* = 0x00008047 + GL_LUMINANCE16_ALPHA16* = 0x00008048 + GL_INTENSITY* = 0x00008049 + GL_INTENSITY4* = 0x0000804A + GL_INTENSITY8* = 0x0000804B + GL_INTENSITY12* = 0x0000804C + GL_INTENSITY16* = 0x0000804D + GL_R3_G3_B2* = 0x00002A10 + GL_RGB4* = 0x0000804F + GL_RGB5* = 0x00008050 + GL_RGB8* = 0x00008051 + GL_RGB10* = 0x00008052 + GL_RGB12* = 0x00008053 + GL_RGB16* = 0x00008054 + GL_RGBA2* = 0x00008055 + GL_RGBA4* = 0x00008056 + GL_RGB5_A1* = 0x00008057 + GL_RGBA8* = 0x00008058 + GL_RGB10_A2* = 0x00008059 + GL_RGBA12* = 0x0000805A + GL_RGBA16* = 0x0000805B + GL_TEXTURE_RED_SIZE* = 0x0000805C + GL_TEXTURE_GREEN_SIZE* = 0x0000805D + GL_TEXTURE_BLUE_SIZE* = 0x0000805E + GL_TEXTURE_ALPHA_SIZE* = 0x0000805F + GL_TEXTURE_LUMINANCE_SIZE* = 0x00008060 + GL_TEXTURE_INTENSITY_SIZE* = 0x00008061 + GL_PROXY_TEXTURE_1D* = 0x00008063 + GL_PROXY_TEXTURE_2D* = 0x00008064 # texture_object + GL_TEXTURE_PRIORITY* = 0x00008066 + GL_TEXTURE_RESIDENT* = 0x00008067 + GL_TEXTURE_BINDING_1D* = 0x00008068 + GL_TEXTURE_BINDING_2D* = 0x00008069 # vertex_array + GL_VERTEX_ARRAY* = 0x00008074 + GL_NORMAL_ARRAY* = 0x00008075 + GL_COLOR_ARRAY* = 0x00008076 + GL_INDEX_ARRAY* = 0x00008077 + GL_TEXTURE_COORD_ARRAY* = 0x00008078 + GL_EDGE_FLAG_ARRAY* = 0x00008079 + GL_VERTEX_ARRAY_SIZE* = 0x0000807A + GL_VERTEX_ARRAY_TYPE* = 0x0000807B + GL_VERTEX_ARRAY_STRIDE* = 0x0000807C + GL_NORMAL_ARRAY_TYPE* = 0x0000807E + GL_NORMAL_ARRAY_STRIDE* = 0x0000807F + GL_COLOR_ARRAY_SIZE* = 0x00008081 + GL_COLOR_ARRAY_TYPE* = 0x00008082 + GL_COLOR_ARRAY_STRIDE* = 0x00008083 + GL_INDEX_ARRAY_TYPE* = 0x00008085 + GL_INDEX_ARRAY_STRIDE* = 0x00008086 + GL_TEXTURE_COORD_ARRAY_SIZE* = 0x00008088 + GL_TEXTURE_COORD_ARRAY_TYPE* = 0x00008089 + GL_TEXTURE_COORD_ARRAY_STRIDE* = 0x0000808A + GL_EDGE_FLAG_ARRAY_STRIDE* = 0x0000808C + GL_VERTEX_ARRAY_POINTER* = 0x0000808E + GL_NORMAL_ARRAY_POINTER* = 0x0000808F + GL_COLOR_ARRAY_POINTER* = 0x00008090 + GL_INDEX_ARRAY_POINTER* = 0x00008091 + GL_TEXTURE_COORD_ARRAY_POINTER* = 0x00008092 + GL_EDGE_FLAG_ARRAY_POINTER* = 0x00008093 + GL_V2F* = 0x00002A20 + GL_V3F* = 0x00002A21 + GL_C4UB_V2F* = 0x00002A22 + GL_C4UB_V3F* = 0x00002A23 + GL_C3F_V3F* = 0x00002A24 + GL_N3F_V3F* = 0x00002A25 + GL_C4F_N3F_V3F* = 0x00002A26 + GL_T2F_V3F* = 0x00002A27 + GL_T4F_V4F* = 0x00002A28 + GL_T2F_C4UB_V3F* = 0x00002A29 + GL_T2F_C3F_V3F* = 0x00002A2A + GL_T2F_N3F_V3F* = 0x00002A2B + GL_T2F_C4F_N3F_V3F* = 0x00002A2C + GL_T4F_C4F_N3F_V4F* = 0x00002A2D # Extensions + GL_EXT_vertex_array* = 1 + GL_WIN_swap_hint* = 1 + GL_EXT_bgra* = 1 + GL_EXT_paletted_texture* = 1 # EXT_vertex_array + GL_VERTEX_ARRAY_EXT* = 0x00008074 + GL_NORMAL_ARRAY_EXT* = 0x00008075 + GL_COLOR_ARRAY_EXT* = 0x00008076 + GL_INDEX_ARRAY_EXT* = 0x00008077 + GL_TEXTURE_COORD_ARRAY_EXT* = 0x00008078 + GL_EDGE_FLAG_ARRAY_EXT* = 0x00008079 + GL_VERTEX_ARRAY_SIZE_EXT* = 0x0000807A + GL_VERTEX_ARRAY_TYPE_EXT* = 0x0000807B + GL_VERTEX_ARRAY_STRIDE_EXT* = 0x0000807C + GL_VERTEX_ARRAY_COUNT_EXT* = 0x0000807D + GL_NORMAL_ARRAY_TYPE_EXT* = 0x0000807E + GL_NORMAL_ARRAY_STRIDE_EXT* = 0x0000807F + GL_NORMAL_ARRAY_COUNT_EXT* = 0x00008080 + GL_COLOR_ARRAY_SIZE_EXT* = 0x00008081 + GL_COLOR_ARRAY_TYPE_EXT* = 0x00008082 + GL_COLOR_ARRAY_STRIDE_EXT* = 0x00008083 + GL_COLOR_ARRAY_COUNT_EXT* = 0x00008084 + GL_INDEX_ARRAY_TYPE_EXT* = 0x00008085 + GL_INDEX_ARRAY_STRIDE_EXT* = 0x00008086 + GL_INDEX_ARRAY_COUNT_EXT* = 0x00008087 + GL_TEXTURE_COORD_ARRAY_SIZE_EXT* = 0x00008088 + GL_TEXTURE_COORD_ARRAY_TYPE_EXT* = 0x00008089 + GL_TEXTURE_COORD_ARRAY_STRIDE_EXT* = 0x0000808A + GL_TEXTURE_COORD_ARRAY_COUNT_EXT* = 0x0000808B + GL_EDGE_FLAG_ARRAY_STRIDE_EXT* = 0x0000808C + GL_EDGE_FLAG_ARRAY_COUNT_EXT* = 0x0000808D + GL_VERTEX_ARRAY_POINTER_EXT* = 0x0000808E + GL_NORMAL_ARRAY_POINTER_EXT* = 0x0000808F + GL_COLOR_ARRAY_POINTER_EXT* = 0x00008090 + GL_INDEX_ARRAY_POINTER_EXT* = 0x00008091 + GL_TEXTURE_COORD_ARRAY_POINTER_EXT* = 0x00008092 + GL_EDGE_FLAG_ARRAY_POINTER_EXT* = 0x00008093 + GL_DOUBLE_EXT* = GL_DOUBLE # EXT_bgra + GL_BGR_EXT* = 0x000080E0 + GL_BGRA_EXT* = 0x000080E1 # EXT_paletted_texture + # These must match the GL_COLOR_TABLE_*_SGI enumerants + GL_COLOR_TABLE_FORMAT_EXT* = 0x000080D8 + GL_COLOR_TABLE_WIDTH_EXT* = 0x000080D9 + GL_COLOR_TABLE_RED_SIZE_EXT* = 0x000080DA + GL_COLOR_TABLE_GREEN_SIZE_EXT* = 0x000080DB + GL_COLOR_TABLE_BLUE_SIZE_EXT* = 0x000080DC + GL_COLOR_TABLE_ALPHA_SIZE_EXT* = 0x000080DD + GL_COLOR_TABLE_LUMINANCE_SIZE_EXT* = 0x000080DE + GL_COLOR_TABLE_INTENSITY_SIZE_EXT* = 0x000080DF + GL_COLOR_INDEX1_EXT* = 0x000080E2 + GL_COLOR_INDEX2_EXT* = 0x000080E3 + GL_COLOR_INDEX4_EXT* = 0x000080E4 + GL_COLOR_INDEX8_EXT* = 0x000080E5 + GL_COLOR_INDEX12_EXT* = 0x000080E6 + GL_COLOR_INDEX16_EXT* = 0x000080E7 # For compatibility with OpenGL v1.0 + constGL_LOGIC_OP* = GL_INDEX_LOGIC_OP + GL_TEXTURE_COMPONENTS* = GL_TEXTURE_INTERNAL_FORMAT + +proc glAccum*(op: TGLenum, value: TGLfloat){.dynlib: dllname, importc: "glAccum".} +proc glAlphaFunc*(func: TGLenum, theref: TGLclampf){.dynlib: dllname, + importc: "glAlphaFunc".} +proc glAreTexturesResident*(n: TGLsizei, textures: PGLuint, + residences: PGLboolean): TGLboolean{. + dynlib: dllname, importc: "glAreTexturesResident".} +proc glArrayElement*(i: TGLint){.dynlib: dllname, importc: "glArrayElement".} +proc glBegin*(mode: TGLenum){.dynlib: dllname, importc: "glBegin".} +proc glBindTexture*(target: TGLenum, texture: TGLuint){.dynlib: dllname, + importc: "glBindTexture".} +proc glBitmap*(width, height: TGLsizei, xorig, yorig: TGLfloat, + xmove, ymove: TGLfloat, bitmap: PGLubyte){.dynlib: dllname, + importc: "glBitmap".} +proc glBlendFunc*(sfactor, dfactor: TGLenum){.dynlib: dllname, + importc: "glBlendFunc".} +proc glCallList*(list: TGLuint){.dynlib: dllname, importc: "glCallList".} +proc glCallLists*(n: TGLsizei, atype: TGLenum, lists: Pointer){.dynlib: dllname, + importc: "glCallLists".} +proc glClear*(mask: TGLbitfield){.dynlib: dllname, importc: "glClear".} +proc glClearAccum*(red, green, blue, alpha: TGLfloat){.dynlib: dllname, + importc: "glClearAccum".} +proc glClearColor*(red, green, blue, alpha: TGLclampf){.dynlib: dllname, + importc: "glClearColor".} +proc glClearDepth*(depth: TGLclampd){.dynlib: dllname, importc: "glClearDepth".} +proc glClearIndex*(c: TGLfloat){.dynlib: dllname, importc: "glClearIndex".} +proc glClearStencil*(s: TGLint){.dynlib: dllname, importc: "glClearStencil".} +proc glClipPlane*(plane: TGLenum, equation: PGLdouble){.dynlib: dllname, + importc: "glClipPlane".} +proc glColor3b*(red, green, blue: TGlbyte){.dynlib: dllname, + importc: "glColor3b".} +proc glColor3bv*(v: PGLbyte){.dynlib: dllname, importc: "glColor3bv".} +proc glColor3d*(red, green, blue: TGLdouble){.dynlib: dllname, + importc: "glColor3d".} +proc glColor3dv*(v: PGLdouble){.dynlib: dllname, importc: "glColor3dv".} +proc glColor3f*(red, green, blue: TGLfloat){.dynlib: dllname, + importc: "glColor3f".} +proc glColor3fv*(v: PGLfloat){.dynlib: dllname, importc: "glColor3fv".} +proc glColor3i*(red, green, blue: TGLint){.dynlib: dllname, importc: "glColor3i".} +proc glColor3iv*(v: PGLint){.dynlib: dllname, importc: "glColor3iv".} +proc glColor3s*(red, green, blue: TGLshort){.dynlib: dllname, + importc: "glColor3s".} +proc glColor3sv*(v: PGLshort){.dynlib: dllname, importc: "glColor3sv".} +proc glColor3ub*(red, green, blue: TGLubyte){.dynlib: dllname, + importc: "glColor3ub".} +proc glColor3ubv*(v: PGLubyte){.dynlib: dllname, importc: "glColor3ubv".} +proc glColor3ui*(red, green, blue: TGLuint){.dynlib: dllname, + importc: "glColor3ui".} +proc glColor3uiv*(v: PGLuint){.dynlib: dllname, importc: "glColor3uiv".} +proc glColor3us*(red, green, blue: TGLushort){.dynlib: dllname, + importc: "glColor3us".} +proc glColor3usv*(v: PGLushort){.dynlib: dllname, importc: "glColor3usv".} +proc glColor4b*(red, green, blue, alpha: TGlbyte){.dynlib: dllname, + importc: "glColor4b".} +proc glColor4bv*(v: PGLbyte){.dynlib: dllname, importc: "glColor4bv".} +proc glColor4d*(red, green, blue, alpha: TGLdouble){.dynlib: dllname, + importc: "glColor4d".} +proc glColor4dv*(v: PGLdouble){.dynlib: dllname, importc: "glColor4dv".} +proc glColor4f*(red, green, blue, alpha: TGLfloat){.dynlib: dllname, + importc: "glColor4f".} +proc glColor4fv*(v: PGLfloat){.dynlib: dllname, importc: "glColor4fv".} +proc glColor4i*(red, green, blue, alpha: TGLint){.dynlib: dllname, + importc: "glColor4i".} +proc glColor4iv*(v: PGLint){.dynlib: dllname, importc: "glColor4iv".} +proc glColor4s*(red, green, blue, alpha: TGLshort){.dynlib: dllname, + importc: "glColor4s".} +proc glColor4sv*(v: PGLshort){.dynlib: dllname, importc: "glColor4sv".} +proc glColor4ub*(red, green, blue, alpha: TGLubyte){.dynlib: dllname, + importc: "glColor4ub".} +proc glColor4ubv*(v: PGLubyte){.dynlib: dllname, importc: "glColor4ubv".} +proc glColor4ui*(red, green, blue, alpha: TGLuint){.dynlib: dllname, + importc: "glColor4ui".} +proc glColor4uiv*(v: PGLuint){.dynlib: dllname, importc: "glColor4uiv".} +proc glColor4us*(red, green, blue, alpha: TGLushort){.dynlib: dllname, + importc: "glColor4us".} +proc glColor4usv*(v: PGLushort){.dynlib: dllname, importc: "glColor4usv".} +proc glColorMask*(red, green, blue, alpha: TGLboolean){.dynlib: dllname, + importc: "glColorMask".} +proc glColorMaterial*(face, mode: TGLenum){.dynlib: dllname, + importc: "glColorMaterial".} +proc glColorPointer*(size: TGLint, atype: TGLenum, stride: TGLsizei, + pointer: Pointer){.dynlib: dllname, + importc: "glColorPointer".} +proc glCopyPixels*(x, y: TGLint, width, height: TGLsizei, atype: TGLenum){. + dynlib: dllname, importc: "glCopyPixels".} +proc glCopyTexImage1D*(target: TGLenum, level: TGLint, internalFormat: TGLenum, + x, y: TGLint, width: TGLsizei, border: TGLint){. + dynlib: dllname, importc: "glCopyTexImage1D".} +proc glCopyTexImage2D*(target: TGLenum, level: TGLint, internalFormat: TGLenum, + x, y: TGLint, width, height: TGLsizei, border: TGLint){. + dynlib: dllname, importc: "glCopyTexImage2D".} +proc glCopyTexSubImage1D*(target: TGLenum, level, xoffset, x, y: TGLint, + width: TGLsizei){.dynlib: dllname, + importc: "glCopyTexSubImage1D".} +proc glCopyTexSubImage2D*(target: TGLenum, + level, xoffset, yoffset, x, y: TGLint, + width, height: TGLsizei){.dynlib: dllname, + importc: "glCopyTexSubImage2D".} +proc glCullFace*(mode: TGLenum){.dynlib: dllname, importc: "glCullFace".} +proc glDeleteLists*(list: TGLuint, range: TGLsizei){.dynlib: dllname, + importc: "glDeleteLists".} +proc glDeleteTextures*(n: TGLsizei, textures: PGLuint){.dynlib: dllname, + importc: "glDeleteTextures".} +proc glDepthFunc*(func: TGLenum){.dynlib: dllname, importc: "glDepthFunc".} +proc glDepthMask*(flag: TGLboolean){.dynlib: dllname, importc: "glDepthMask".} +proc glDepthRange*(zNear, zFar: TGLclampd){.dynlib: dllname, + importc: "glDepthRange".} +proc glDisable*(cap: TGLenum){.dynlib: dllname, importc: "glDisable".} +proc glDisableClientState*(aarray: TGLenum){.dynlib: dllname, + importc: "glDisableClientState".} +proc glDrawArrays*(mode: TGLenum, first: TGLint, count: TGLsizei){. + dynlib: dllname, importc: "glDrawArrays".} +proc glDrawBuffer*(mode: TGLenum){.dynlib: dllname, importc: "glDrawBuffer".} +proc glDrawElements*(mode: TGLenum, count: TGLsizei, atype: TGLenum, + indices: Pointer){.dynlib: dllname, + importc: "glDrawElements".} +proc glDrawPixels*(width, height: TGLsizei, format, atype: TGLenum, + pixels: Pointer){.dynlib: dllname, importc: "glDrawPixels".} +proc glEdgeFlag*(flag: TGLboolean){.dynlib: dllname, importc: "glEdgeFlag".} +proc glEdgeFlagPointer*(stride: TGLsizei, pointer: Pointer){.dynlib: dllname, + importc: "glEdgeFlagPointer".} +proc glEdgeFlagv*(flag: PGLboolean){.dynlib: dllname, importc: "glEdgeFlagv".} +proc glEnable*(cap: TGLenum){.dynlib: dllname, importc: "glEnable".} +proc glEnableClientState*(aarray: TGLenum){.dynlib: dllname, + importc: "glEnableClientState".} +proc glEnd*(){.dynlib: dllname, importc: "glEnd".} +proc glEndList*(){.dynlib: dllname, importc: "glEndList".} +proc glEvalCoord1d*(u: TGLdouble){.dynlib: dllname, importc: "glEvalCoord1d".} +proc glEvalCoord1dv*(u: PGLdouble){.dynlib: dllname, importc: "glEvalCoord1dv".} +proc glEvalCoord1f*(u: TGLfloat){.dynlib: dllname, importc: "glEvalCoord1f".} +proc glEvalCoord1fv*(u: PGLfloat){.dynlib: dllname, importc: "glEvalCoord1fv".} +proc glEvalCoord2d*(u, v: TGLdouble){.dynlib: dllname, importc: "glEvalCoord2d".} +proc glEvalCoord2dv*(u: PGLdouble){.dynlib: dllname, importc: "glEvalCoord2dv".} +proc glEvalCoord2f*(u, v: TGLfloat){.dynlib: dllname, importc: "glEvalCoord2f".} +proc glEvalCoord2fv*(u: PGLfloat){.dynlib: dllname, importc: "glEvalCoord2fv".} +proc glEvalMesh1*(mode: TGLenum, i1, i2: TGLint){.dynlib: dllname, + importc: "glEvalMesh1".} +proc glEvalMesh2*(mode: TGLenum, i1, i2, j1, j2: TGLint){.dynlib: dllname, + importc: "glEvalMesh2".} +proc glEvalPoint1*(i: TGLint){.dynlib: dllname, importc: "glEvalPoint1".} +proc glEvalPoint2*(i, j: TGLint){.dynlib: dllname, importc: "glEvalPoint2".} +proc glFeedbackBuffer*(size: TGLsizei, atype: TGLenum, buffer: PGLfloat){. + dynlib: dllname, importc: "glFeedbackBuffer".} +proc glFinish*(){.dynlib: dllname, importc: "glFinish".} +proc glFlush*(){.dynlib: dllname, importc: "glFlush".} +proc glFogf*(pname: TGLenum, param: TGLfloat){.dynlib: dllname, + importc: "glFogf".} +proc glFogfv*(pname: TGLenum, params: PGLfloat){.dynlib: dllname, + importc: "glFogfv".} +proc glFogi*(pname: TGLenum, param: TGLint){.dynlib: dllname, importc: "glFogi".} +proc glFogiv*(pname: TGLenum, params: PGLint){.dynlib: dllname, + importc: "glFogiv".} +proc glFrontFace*(mode: TGLenum){.dynlib: dllname, importc: "glFrontFace".} +proc glFrustum*(left, right, bottom, top, zNear, zFar: TGLdouble){. + dynlib: dllname, importc: "glFrustum".} +proc glGenLists*(range: TGLsizei): TGLuint{.dynlib: dllname, + importc: "glGenLists".} +proc glGenTextures*(n: TGLsizei, textures: PGLuint){.dynlib: dllname, + importc: "glGenTextures".} +proc glGetBooleanv*(pname: TGLenum, params: PGLboolean){.dynlib: dllname, + importc: "glGetBooleanv".} +proc glGetClipPlane*(plane: TGLenum, equation: PGLdouble){.dynlib: dllname, + importc: "glGetClipPlane".} +proc glGetDoublev*(pname: TGLenum, params: PGLdouble){.dynlib: dllname, + importc: "glGetDoublev".} +proc glGetError*(): TGLenum{.dynlib: dllname, importc: "glGetError".} +proc glGetFloatv*(pname: TGLenum, params: PGLfloat){.dynlib: dllname, + importc: "glGetFloatv".} +proc glGetIntegerv*(pname: TGLenum, params: PGLint){.dynlib: dllname, + importc: "glGetIntegerv".} +proc glGetLightfv*(light, pname: TGLenum, params: PGLfloat){.dynlib: dllname, + importc: "glGetLightfv".} +proc glGetLightiv*(light, pname: TGLenum, params: PGLint){.dynlib: dllname, + importc: "glGetLightiv".} +proc glGetMapdv*(target, query: TGLenum, v: PGLdouble){.dynlib: dllname, + importc: "glGetMapdv".} +proc glGetMapfv*(target, query: TGLenum, v: PGLfloat){.dynlib: dllname, + importc: "glGetMapfv".} +proc glGetMapiv*(target, query: TGLenum, v: PGLint){.dynlib: dllname, + importc: "glGetMapiv".} +proc glGetMaterialfv*(face, pname: TGLenum, params: PGLfloat){.dynlib: dllname, + importc: "glGetMaterialfv".} +proc glGetMaterialiv*(face, pname: TGLenum, params: PGLint){.dynlib: dllname, + importc: "glGetMaterialiv".} +proc glGetPixelMapfv*(map: TGLenum, values: PGLfloat){.dynlib: dllname, + importc: "glGetPixelMapfv".} +proc glGetPixelMapuiv*(map: TGLenum, values: PGLuint){.dynlib: dllname, + importc: "glGetPixelMapuiv".} +proc glGetPixelMapusv*(map: TGLenum, values: PGLushort){.dynlib: dllname, + importc: "glGetPixelMapusv".} +proc glGetPointerv*(pname: TGLenum, params: Pointer){.dynlib: dllname, + importc: "glGetPointerv".} +proc glGetPolygonStipple*(mask: PGLubyte){.dynlib: dllname, + importc: "glGetPolygonStipple".} +proc glGetString*(name: TGLenum): cstring{.dynlib: dllname, + importc: "glGetString".} +proc glGetTexEnvfv*(target, pname: TGLenum, params: PGLfloat){.dynlib: dllname, + importc: "glGetTexEnvfv".} +proc glGetTexEnviv*(target, pname: TGLenum, params: PGLint){.dynlib: dllname, + importc: "glGetTexEnviv".} +proc glGetTexGendv*(coord, pname: TGLenum, params: PGLdouble){.dynlib: dllname, + importc: "glGetTexGendv".} +proc glGetTexGenfv*(coord, pname: TGLenum, params: PGLfloat){.dynlib: dllname, + importc: "glGetTexGenfv".} +proc glGetTexGeniv*(coord, pname: TGLenum, params: PGLint){.dynlib: dllname, + importc: "glGetTexGeniv".} +proc glGetTexImage*(target: TGLenum, level: TGLint, format: TGLenum, + atype: TGLenum, pixels: Pointer){.dynlib: dllname, + importc: "glGetTexImage".} +proc glGetTexLevelParameterfv*(target: TGLenum, level: TGLint, pname: TGLenum, + params: Pointer){.dynlib: dllname, + importc: "glGetTexLevelParameterfv".} +proc glGetTexLevelParameteriv*(target: TGLenum, level: TGLint, pname: TGLenum, + params: PGLint){.dynlib: dllname, + importc: "glGetTexLevelParameteriv".} +proc glGetTexParameterfv*(target, pname: TGLenum, params: PGLfloat){. + dynlib: dllname, importc: "glGetTexParameterfv".} +proc glGetTexParameteriv*(target, pname: TGLenum, params: PGLint){. + dynlib: dllname, importc: "glGetTexParameteriv".} +proc glHint*(target, mode: TGLenum){.dynlib: dllname, importc: "glHint".} +proc glIndexMask*(mask: TGLuint){.dynlib: dllname, importc: "glIndexMask".} +proc glIndexPointer*(atype: TGLenum, stride: TGLsizei, pointer: Pointer){. + dynlib: dllname, importc: "glIndexPointer".} +proc glIndexd*(c: TGLdouble){.dynlib: dllname, importc: "glIndexd".} +proc glIndexdv*(c: PGLdouble){.dynlib: dllname, importc: "glIndexdv".} +proc glIndexf*(c: TGLfloat){.dynlib: dllname, importc: "glIndexf".} +proc glIndexfv*(c: PGLfloat){.dynlib: dllname, importc: "glIndexfv".} +proc glIndexi*(c: TGLint){.dynlib: dllname, importc: "glIndexi".} +proc glIndexiv*(c: PGLint){.dynlib: dllname, importc: "glIndexiv".} +proc glIndexs*(c: TGLshort){.dynlib: dllname, importc: "glIndexs".} +proc glIndexsv*(c: PGLshort){.dynlib: dllname, importc: "glIndexsv".} +proc glIndexub*(c: TGLubyte){.dynlib: dllname, importc: "glIndexub".} +proc glIndexubv*(c: PGLubyte){.dynlib: dllname, importc: "glIndexubv".} +proc glInitNames*(){.dynlib: dllname, importc: "glInitNames".} +proc glInterleavedArrays*(format: TGLenum, stride: TGLsizei, pointer: Pointer){. + dynlib: dllname, importc: "glInterleavedArrays".} +proc glIsEnabled*(cap: TGLenum): TGLboolean{.dynlib: dllname, + importc: "glIsEnabled".} +proc glIsList*(list: TGLuint): TGLboolean{.dynlib: dllname, importc: "glIsList".} +proc glIsTexture*(texture: TGLuint): TGLboolean{.dynlib: dllname, + importc: "glIsTexture".} +proc glLightModelf*(pname: TGLenum, param: TGLfloat){.dynlib: dllname, + importc: "glLightModelf".} +proc glLightModelfv*(pname: TGLenum, params: PGLfloat){.dynlib: dllname, + importc: "glLightModelfv".} +proc glLightModeli*(pname: TGLenum, param: TGLint){.dynlib: dllname, + importc: "glLightModeli".} +proc glLightModeliv*(pname: TGLenum, params: PGLint){.dynlib: dllname, + importc: "glLightModeliv".} +proc glLightf*(light, pname: TGLenum, param: TGLfloat){.dynlib: dllname, + importc: "glLightf".} +proc glLightfv*(light, pname: TGLenum, params: PGLfloat){.dynlib: dllname, + importc: "glLightfv".} +proc glLighti*(light, pname: TGLenum, param: TGLint){.dynlib: dllname, + importc: "glLighti".} +proc glLightiv*(light, pname: TGLenum, params: PGLint){.dynlib: dllname, + importc: "glLightiv".} +proc glLineStipple*(factor: TGLint, pattern: TGLushort){.dynlib: dllname, + importc: "glLineStipple".} +proc glLineWidth*(width: TGLfloat){.dynlib: dllname, importc: "glLineWidth".} +proc glListBase*(base: TGLuint){.dynlib: dllname, importc: "glListBase".} +proc glLoadIdentity*(){.dynlib: dllname, importc: "glLoadIdentity".} +proc glLoadMatrixd*(m: PGLdouble){.dynlib: dllname, importc: "glLoadMatrixd".} +proc glLoadMatrixf*(m: PGLfloat){.dynlib: dllname, importc: "glLoadMatrixf".} +proc glLoadName*(name: TGLuint){.dynlib: dllname, importc: "glLoadName".} +proc glLogicOp*(opcode: TGLenum){.dynlib: dllname, importc: "glLogicOp".} +proc glMap1d*(target: TGLenum, u1, u2: TGLdouble, stride, order: TGLint, + points: PGLdouble){.dynlib: dllname, importc: "glMap1d".} +proc glMap1f*(target: TGLenum, u1, u2: TGLfloat, stride, order: TGLint, + points: PGLfloat){.dynlib: dllname, importc: "glMap1f".} +proc glMap2d*(target: TGLenum, u1, u2: TGLdouble, ustride, uorder: TGLint, + v1, v2: TGLdouble, vstride, vorder: TGLint, points: PGLdouble){. + dynlib: dllname, importc: "glMap2d".} +proc glMap2f*(target: TGLenum, u1, u2: TGLfloat, ustride, uorder: TGLint, + v1, v2: TGLfloat, vstride, vorder: TGLint, points: PGLfloat){. + dynlib: dllname, importc: "glMap2f".} +proc glMapGrid1d*(un: TGLint, u1, u2: TGLdouble){.dynlib: dllname, + importc: "glMapGrid1d".} +proc glMapGrid1f*(un: TGLint, u1, u2: TGLfloat){.dynlib: dllname, + importc: "glMapGrid1f".} +proc glMapGrid2d*(un: TGLint, u1, u2: TGLdouble, vn: TGLint, v1, v2: TGLdouble){. + dynlib: dllname, importc: "glMapGrid2d".} +proc glMapGrid2f*(un: TGLint, u1, u2: TGLfloat, vn: TGLint, v1, v2: TGLfloat){. + dynlib: dllname, importc: "glMapGrid2f".} +proc glMaterialf*(face, pname: TGLenum, param: TGLfloat){.dynlib: dllname, + importc: "glMaterialf".} +proc glMaterialfv*(face, pname: TGLenum, params: PGLfloat){.dynlib: dllname, + importc: "glMaterialfv".} +proc glMateriali*(face, pname: TGLenum, param: TGLint){.dynlib: dllname, + importc: "glMateriali".} +proc glMaterialiv*(face, pname: TGLenum, params: PGLint){.dynlib: dllname, + importc: "glMaterialiv".} +proc glMatrixMode*(mode: TGLenum){.dynlib: dllname, importc: "glMatrixMode".} +proc glMultMatrixd*(m: PGLdouble){.dynlib: dllname, importc: "glMultMatrixd".} +proc glMultMatrixf*(m: PGLfloat){.dynlib: dllname, importc: "glMultMatrixf".} +proc glNewList*(list: TGLuint, mode: TGLenum){.dynlib: dllname, + importc: "glNewList".} +proc glNormal3b*(nx, ny, nz: TGlbyte){.dynlib: dllname, importc: "glNormal3b".} +proc glNormal3bv*(v: PGLbyte){.dynlib: dllname, importc: "glNormal3bv".} +proc glNormal3d*(nx, ny, nz: TGLdouble){.dynlib: dllname, importc: "glNormal3d".} +proc glNormal3dv*(v: PGLdouble){.dynlib: dllname, importc: "glNormal3dv".} +proc glNormal3f*(nx, ny, nz: TGLfloat){.dynlib: dllname, importc: "glNormal3f".} +proc glNormal3fv*(v: PGLfloat){.dynlib: dllname, importc: "glNormal3fv".} +proc glNormal3i*(nx, ny, nz: TGLint){.dynlib: dllname, importc: "glNormal3i".} +proc glNormal3iv*(v: PGLint){.dynlib: dllname, importc: "glNormal3iv".} +proc glNormal3s*(nx, ny, nz: TGLshort){.dynlib: dllname, importc: "glNormal3s".} +proc glNormal3sv*(v: PGLshort){.dynlib: dllname, importc: "glNormal3sv".} +proc glNormalPointer*(atype: TGLenum, stride: TGLsizei, pointer: Pointer){. + dynlib: dllname, importc: "glNormalPointer".} +proc glOrtho*(left, right, bottom, top, zNear, zFar: TGLdouble){. + dynlib: dllname, importc: "glOrtho".} +proc glPassThrough*(token: TGLfloat){.dynlib: dllname, importc: "glPassThrough".} +proc glPixelMapfv*(map: TGLenum, mapsize: TGLsizei, values: PGLfloat){. + dynlib: dllname, importc: "glPixelMapfv".} +proc glPixelMapuiv*(map: TGLenum, mapsize: TGLsizei, values: PGLuint){. + dynlib: dllname, importc: "glPixelMapuiv".} +proc glPixelMapusv*(map: TGLenum, mapsize: TGLsizei, values: PGLushort){. + dynlib: dllname, importc: "glPixelMapusv".} +proc glPixelStoref*(pname: TGLenum, param: TGLfloat){.dynlib: dllname, + importc: "glPixelStoref".} +proc glPixelStorei*(pname: TGLenum, param: TGLint){.dynlib: dllname, + importc: "glPixelStorei".} +proc glPixelTransferf*(pname: TGLenum, param: TGLfloat){.dynlib: dllname, + importc: "glPixelTransferf".} +proc glPixelTransferi*(pname: TGLenum, param: TGLint){.dynlib: dllname, + importc: "glPixelTransferi".} +proc glPixelZoom*(xfactor, yfactor: TGLfloat){.dynlib: dllname, + importc: "glPixelZoom".} +proc glPointSize*(size: TGLfloat){.dynlib: dllname, importc: "glPointSize".} +proc glPolygonMode*(face, mode: TGLenum){.dynlib: dllname, + importc: "glPolygonMode".} +proc glPolygonOffset*(factor, units: TGLfloat){.dynlib: dllname, + importc: "glPolygonOffset".} +proc glPolygonStipple*(mask: PGLubyte){.dynlib: dllname, + importc: "glPolygonStipple".} +proc glPopAttrib*(){.dynlib: dllname, importc: "glPopAttrib".} +proc glPopClientAttrib*(){.dynlib: dllname, importc: "glPopClientAttrib".} +proc glPopMatrix*(){.dynlib: dllname, importc: "glPopMatrix".} +proc glPopName*(){.dynlib: dllname, importc: "glPopName".} +proc glPrioritizeTextures*(n: TGLsizei, textures: PGLuint, priorities: PGLclampf){. + dynlib: dllname, importc: "glPrioritizeTextures".} +proc glPushAttrib*(mask: TGLbitfield){.dynlib: dllname, importc: "glPushAttrib".} +proc glPushClientAttrib*(mask: TGLbitfield){.dynlib: dllname, + importc: "glPushClientAttrib".} +proc glPushMatrix*(){.dynlib: dllname, importc: "glPushMatrix".} +proc glPushName*(name: TGLuint){.dynlib: dllname, importc: "glPushName".} +proc glRasterPos2d*(x, y: TGLdouble){.dynlib: dllname, importc: "glRasterPos2d".} +proc glRasterPos2dv*(v: PGLdouble){.dynlib: dllname, importc: "glRasterPos2dv".} +proc glRasterPos2f*(x, y: TGLfloat){.dynlib: dllname, importc: "glRasterPos2f".} +proc glRasterPos2fv*(v: PGLfloat){.dynlib: dllname, importc: "glRasterPos2fv".} +proc glRasterPos2i*(x, y: TGLint){.dynlib: dllname, importc: "glRasterPos2i".} +proc glRasterPos2iv*(v: PGLint){.dynlib: dllname, importc: "glRasterPos2iv".} +proc glRasterPos2s*(x, y: TGLshort){.dynlib: dllname, importc: "glRasterPos2s".} +proc glRasterPos2sv*(v: PGLshort){.dynlib: dllname, importc: "glRasterPos2sv".} +proc glRasterPos3d*(x, y, z: TGLdouble){.dynlib: dllname, + importc: "glRasterPos3d".} +proc glRasterPos3dv*(v: PGLdouble){.dynlib: dllname, importc: "glRasterPos3dv".} +proc glRasterPos3f*(x, y, z: TGLfloat){.dynlib: dllname, + importc: "glRasterPos3f".} +proc glRasterPos3fv*(v: PGLfloat){.dynlib: dllname, importc: "glRasterPos3fv".} +proc glRasterPos3i*(x, y, z: TGLint){.dynlib: dllname, importc: "glRasterPos3i".} +proc glRasterPos3iv*(v: PGLint){.dynlib: dllname, importc: "glRasterPos3iv".} +proc glRasterPos3s*(x, y, z: TGLshort){.dynlib: dllname, + importc: "glRasterPos3s".} +proc glRasterPos3sv*(v: PGLshort){.dynlib: dllname, importc: "glRasterPos3sv".} +proc glRasterPos4d*(x, y, z, w: TGLdouble){.dynlib: dllname, + importc: "glRasterPos4d".} +proc glRasterPos4dv*(v: PGLdouble){.dynlib: dllname, importc: "glRasterPos4dv".} +proc glRasterPos4f*(x, y, z, w: TGLfloat){.dynlib: dllname, + importc: "glRasterPos4f".} +proc glRasterPos4fv*(v: PGLfloat){.dynlib: dllname, importc: "glRasterPos4fv".} +proc glRasterPos4i*(x, y, z, w: TGLint){.dynlib: dllname, + importc: "glRasterPos4i".} +proc glRasterPos4iv*(v: PGLint){.dynlib: dllname, importc: "glRasterPos4iv".} +proc glRasterPos4s*(x, y, z, w: TGLshort){.dynlib: dllname, + importc: "glRasterPos4s".} +proc glRasterPos4sv*(v: PGLshort){.dynlib: dllname, importc: "glRasterPos4sv".} +proc glReadBuffer*(mode: TGLenum){.dynlib: dllname, importc: "glReadBuffer".} +proc glReadPixels*(x, y: TGLint, width, height: TGLsizei, + format, atype: TGLenum, pixels: Pointer){.dynlib: dllname, + importc: "glReadPixels".} +proc glRectd*(x1, y1, x2, y2: TGLdouble){.dynlib: dllname, importc: "glRectd".} +proc glRectdv*(v1: PGLdouble, v2: PGLdouble){.dynlib: dllname, + importc: "glRectdv".} +proc glRectf*(x1, y1, x2, y2: TGLfloat){.dynlib: dllname, importc: "glRectf".} +proc glRectfv*(v1: PGLfloat, v2: PGLfloat){.dynlib: dllname, importc: "glRectfv".} +proc glRecti*(x1, y1, x2, y2: TGLint){.dynlib: dllname, importc: "glRecti".} +proc glRectiv*(v1: PGLint, v2: PGLint){.dynlib: dllname, importc: "glRectiv".} +proc glRects*(x1, y1, x2, y2: TGLshort){.dynlib: dllname, importc: "glRects".} +proc glRectsv*(v1: PGLshort, v2: PGLshort){.dynlib: dllname, importc: "glRectsv".} +proc glRenderMode*(mode: TGLint): TGLint{.dynlib: dllname, + importc: "glRenderMode".} +proc glRotated*(angle, x, y, z: TGLdouble){.dynlib: dllname, + importc: "glRotated".} +proc glRotatef*(angle, x, y, z: TGLfloat){.dynlib: dllname, importc: "glRotatef".} +proc glScaled*(x, y, z: TGLdouble){.dynlib: dllname, importc: "glScaled".} +proc glScalef*(x, y, z: TGLfloat){.dynlib: dllname, importc: "glScalef".} +proc glScissor*(x, y: TGLint, width, height: TGLsizei){.dynlib: dllname, + importc: "glScissor".} +proc glSelectBuffer*(size: TGLsizei, buffer: PGLuint){.dynlib: dllname, + importc: "glSelectBuffer".} +proc glShadeModel*(mode: TGLenum){.dynlib: dllname, importc: "glShadeModel".} +proc glStencilFunc*(func: TGLenum, theref: TGLint, mask: TGLuint){. + dynlib: dllname, importc: "glStencilFunc".} +proc glStencilMask*(mask: TGLuint){.dynlib: dllname, importc: "glStencilMask".} +proc glStencilOp*(fail, zfail, zpass: TGLenum){.dynlib: dllname, + importc: "glStencilOp".} +proc glTexCoord1d*(s: TGLdouble){.dynlib: dllname, importc: "glTexCoord1d".} +proc glTexCoord1dv*(v: PGLdouble){.dynlib: dllname, importc: "glTexCoord1dv".} +proc glTexCoord1f*(s: TGLfloat){.dynlib: dllname, importc: "glTexCoord1f".} +proc glTexCoord1fv*(v: PGLfloat){.dynlib: dllname, importc: "glTexCoord1fv".} +proc glTexCoord1i*(s: TGLint){.dynlib: dllname, importc: "glTexCoord1i".} +proc glTexCoord1iv*(v: PGLint){.dynlib: dllname, importc: "glTexCoord1iv".} +proc glTexCoord1s*(s: TGLshort){.dynlib: dllname, importc: "glTexCoord1s".} +proc glTexCoord1sv*(v: PGLshort){.dynlib: dllname, importc: "glTexCoord1sv".} +proc glTexCoord2d*(s, t: TGLdouble){.dynlib: dllname, importc: "glTexCoord2d".} +proc glTexCoord2dv*(v: PGLdouble){.dynlib: dllname, importc: "glTexCoord2dv".} +proc glTexCoord2f*(s, t: TGLfloat){.dynlib: dllname, importc: "glTexCoord2f".} +proc glTexCoord2fv*(v: PGLfloat){.dynlib: dllname, importc: "glTexCoord2fv".} +proc glTexCoord2i*(s, t: TGLint){.dynlib: dllname, importc: "glTexCoord2i".} +proc glTexCoord2iv*(v: PGLint){.dynlib: dllname, importc: "glTexCoord2iv".} +proc glTexCoord2s*(s, t: TGLshort){.dynlib: dllname, importc: "glTexCoord2s".} +proc glTexCoord2sv*(v: PGLshort){.dynlib: dllname, importc: "glTexCoord2sv".} +proc glTexCoord3d*(s, t, r: TGLdouble){.dynlib: dllname, importc: "glTexCoord3d".} +proc glTexCoord3dv*(v: PGLdouble){.dynlib: dllname, importc: "glTexCoord3dv".} +proc glTexCoord3f*(s, t, r: TGLfloat){.dynlib: dllname, importc: "glTexCoord3f".} +proc glTexCoord3fv*(v: PGLfloat){.dynlib: dllname, importc: "glTexCoord3fv".} +proc glTexCoord3i*(s, t, r: TGLint){.dynlib: dllname, importc: "glTexCoord3i".} +proc glTexCoord3iv*(v: PGLint){.dynlib: dllname, importc: "glTexCoord3iv".} +proc glTexCoord3s*(s, t, r: TGLshort){.dynlib: dllname, importc: "glTexCoord3s".} +proc glTexCoord3sv*(v: PGLshort){.dynlib: dllname, importc: "glTexCoord3sv".} +proc glTexCoord4d*(s, t, r, q: TGLdouble){.dynlib: dllname, + importc: "glTexCoord4d".} +proc glTexCoord4dv*(v: PGLdouble){.dynlib: dllname, importc: "glTexCoord4dv".} +proc glTexCoord4f*(s, t, r, q: TGLfloat){.dynlib: dllname, + importc: "glTexCoord4f".} +proc glTexCoord4fv*(v: PGLfloat){.dynlib: dllname, importc: "glTexCoord4fv".} +proc glTexCoord4i*(s, t, r, q: TGLint){.dynlib: dllname, importc: "glTexCoord4i".} +proc glTexCoord4iv*(v: PGLint){.dynlib: dllname, importc: "glTexCoord4iv".} +proc glTexCoord4s*(s, t, r, q: TGLshort){.dynlib: dllname, + importc: "glTexCoord4s".} +proc glTexCoord4sv*(v: PGLshort){.dynlib: dllname, importc: "glTexCoord4sv".} +proc glTexCoordPointer*(size: TGLint, atype: TGLenum, stride: TGLsizei, + pointer: Pointer){.dynlib: dllname, + importc: "glTexCoordPointer".} +proc glTexEnvf*(target: TGLenum, pname: TGLenum, param: TGLfloat){. + dynlib: dllname, importc: "glTexEnvf".} +proc glTexEnvfv*(target: TGLenum, pname: TGLenum, params: PGLfloat){. + dynlib: dllname, importc: "glTexEnvfv".} +proc glTexEnvi*(target: TGLenum, pname: TGLenum, param: TGLint){. + dynlib: dllname, importc: "glTexEnvi".} +proc glTexEnviv*(target: TGLenum, pname: TGLenum, params: PGLint){. + dynlib: dllname, importc: "glTexEnviv".} +proc glTexGend*(coord: TGLenum, pname: TGLenum, param: TGLdouble){. + dynlib: dllname, importc: "glTexGend".} +proc glTexGendv*(coord: TGLenum, pname: TGLenum, params: PGLdouble){. + dynlib: dllname, importc: "glTexGendv".} +proc glTexGenf*(coord: TGLenum, pname: TGLenum, param: TGLfloat){. + dynlib: dllname, importc: "glTexGenf".} +proc glTexGenfv*(coord: TGLenum, pname: TGLenum, params: PGLfloat){. + dynlib: dllname, importc: "glTexGenfv".} +proc glTexGeni*(coord: TGLenum, pname: TGLenum, param: TGLint){.dynlib: dllname, + importc: "glTexGeni".} +proc glTexGeniv*(coord: TGLenum, pname: TGLenum, params: PGLint){. + dynlib: dllname, importc: "glTexGeniv".} +proc glTexImage1D*(target: TGLenum, level, internalformat: TGLint, + width: TGLsizei, border: TGLint, format, atype: TGLenum, + pixels: Pointer){.dynlib: dllname, importc: "glTexImage1D".} +proc glTexImage2D*(target: TGLenum, level, internalformat: TGLint, + width, height: TGLsizei, border: TGLint, + format, atype: TGLenum, pixels: Pointer){.dynlib: dllname, + importc: "glTexImage2D".} +proc glTexParameterf*(target: TGLenum, pname: TGLenum, param: TGLfloat){. + dynlib: dllname, importc: "glTexParameterf".} +proc glTexParameterfv*(target: TGLenum, pname: TGLenum, params: PGLfloat){. + dynlib: dllname, importc: "glTexParameterfv".} +proc glTexParameteri*(target: TGLenum, pname: TGLenum, param: TGLint){. + dynlib: dllname, importc: "glTexParameteri".} +proc glTexParameteriv*(target: TGLenum, pname: TGLenum, params: PGLint){. + dynlib: dllname, importc: "glTexParameteriv".} +proc glTexSubImage1D*(target: TGLenum, level, xoffset: TGLint, width: TGLsizei, + format, atype: TGLenum, pixels: Pointer){.dynlib: dllname, + importc: "glTexSubImage1D".} +proc glTexSubImage2D*(target: TGLenum, level, xoffset, yoffset: TGLint, + width, height: TGLsizei, format, atype: TGLenum, + pixels: Pointer){.dynlib: dllname, + importc: "glTexSubImage2D".} +proc glTranslated*(x, y, z: TGLdouble){.dynlib: dllname, importc: "glTranslated".} +proc glTranslatef*(x, y, z: TGLfloat){.dynlib: dllname, importc: "glTranslatef".} +proc glVertex2d*(x, y: TGLdouble){.dynlib: dllname, importc: "glVertex2d".} +proc glVertex2dv*(v: PGLdouble){.dynlib: dllname, importc: "glVertex2dv".} +proc glVertex2f*(x, y: TGLfloat){.dynlib: dllname, importc: "glVertex2f".} +proc glVertex2fv*(v: PGLfloat){.dynlib: dllname, importc: "glVertex2fv".} +proc glVertex2i*(x, y: TGLint){.dynlib: dllname, importc: "glVertex2i".} +proc glVertex2iv*(v: PGLint){.dynlib: dllname, importc: "glVertex2iv".} +proc glVertex2s*(x, y: TGLshort){.dynlib: dllname, importc: "glVertex2s".} +proc glVertex2sv*(v: PGLshort){.dynlib: dllname, importc: "glVertex2sv".} +proc glVertex3d*(x, y, z: TGLdouble){.dynlib: dllname, importc: "glVertex3d".} +proc glVertex3dv*(v: PGLdouble){.dynlib: dllname, importc: "glVertex3dv".} +proc glVertex3f*(x, y, z: TGLfloat){.dynlib: dllname, importc: "glVertex3f".} +proc glVertex3fv*(v: PGLfloat){.dynlib: dllname, importc: "glVertex3fv".} +proc glVertex3i*(x, y, z: TGLint){.dynlib: dllname, importc: "glVertex3i".} +proc glVertex3iv*(v: PGLint){.dynlib: dllname, importc: "glVertex3iv".} +proc glVertex3s*(x, y, z: TGLshort){.dynlib: dllname, importc: "glVertex3s".} +proc glVertex3sv*(v: PGLshort){.dynlib: dllname, importc: "glVertex3sv".} +proc glVertex4d*(x, y, z, w: TGLdouble){.dynlib: dllname, importc: "glVertex4d".} +proc glVertex4dv*(v: PGLdouble){.dynlib: dllname, importc: "glVertex4dv".} +proc glVertex4f*(x, y, z, w: TGLfloat){.dynlib: dllname, importc: "glVertex4f".} +proc glVertex4fv*(v: PGLfloat){.dynlib: dllname, importc: "glVertex4fv".} +proc glVertex4i*(x, y, z, w: TGLint){.dynlib: dllname, importc: "glVertex4i".} +proc glVertex4iv*(v: PGLint){.dynlib: dllname, importc: "glVertex4iv".} +proc glVertex4s*(x, y, z, w: TGLshort){.dynlib: dllname, importc: "glVertex4s".} +proc glVertex4sv*(v: PGLshort){.dynlib: dllname, importc: "glVertex4sv".} +proc glVertexPointer*(size: TGLint, atype: TGLenum, stride: TGLsizei, + pointer: Pointer){.dynlib: dllname, + importc: "glVertexPointer".} +proc glViewport*(x, y: TGLint, width, height: TGLsizei){.dynlib: dllname, + importc: "glViewport".} +type + PFN_GLARRAY_ELEMENT_EXTPROC* = proc (i: TGLint) + PFN_GLDRAW_ARRAYS_EXTPROC* = proc (mode: TGLenum, first: TGLint, + count: TGLsizei) + PFN_GLVERTEX_POINTER_EXTPROC* = proc (size: TGLint, atype: TGLenum, + stride, count: TGLsizei, + pointer: Pointer) + PFN_GLNORMAL_POINTER_EXTPROC* = proc (atype: TGLenum, stride, count: TGLsizei, + pointer: Pointer) + PFN_GLCOLOR_POINTER_EXTPROC* = proc (size: TGLint, atype: TGLenum, + stride, count: TGLsizei, pointer: Pointer) + PFN_GLINDEX_POINTER_EXTPROC* = proc (atype: TGLenum, stride, count: TGLsizei, + pointer: Pointer) + PFN_GLTEXCOORD_POINTER_EXTPROC* = proc (size: TGLint, atype: TGLenum, + stride, count: TGLsizei, pointer: Pointer) + PFN_GLEDGEFLAG_POINTER_EXTPROC* = proc (stride, count: TGLsizei, + pointer: PGLboolean) + PFN_GLGET_POINTER_VEXT_PROC* = proc (pname: TGLenum, params: Pointer) + PFN_GLARRAY_ELEMENT_ARRAY_EXTPROC* = proc (mode: TGLenum, count: TGLsizei, + pi: Pointer) # WIN_swap_hint + PFN_GLADDSWAPHINT_RECT_WINPROC* = proc (x, y: TGLint, width, height: TGLsizei) + PFN_GLCOLOR_TABLE_EXTPROC* = proc (target, internalFormat: TGLenum, + width: TGLsizei, format, atype: TGLenum, + data: Pointer) + PFN_GLCOLOR_SUBTABLE_EXTPROC* = proc (target: TGLenum, start, count: TGLsizei, + format, atype: TGLenum, data: Pointer) + PFN_GLGETCOLOR_TABLE_EXTPROC* = proc (target, format, atype: TGLenum, + data: Pointer) + PFN_GLGETCOLOR_TABLE_PARAMETER_IVEXTPROC* = proc (target, pname: TGLenum, + params: PGLint) + PFN_GLGETCOLOR_TABLE_PARAMETER_FVEXTPROC* = proc (target, pname: TGLenum, + params: PGLfloat) + +{.pop.} +# implementation diff --git a/tests/manyloc/keineschweine/lib/glext.nim b/tests/manyloc/keineschweine/lib/glext.nim new file mode 100644 index 0000000000..32871df0e4 --- /dev/null +++ b/tests/manyloc/keineschweine/lib/glext.nim @@ -0,0 +1,4673 @@ +# +# +# Adaption of the delphi3d.net OpenGL units to FreePascal +# Sebastian Guenther (sg@freepascal.org) in 2002 +# These units are free to use +# +# + +#************************************************* +# * OpenGL extension loading library * +# * Generated by MetaGLext, written by Tom Nuydens * +# * (tom@delphi3d.net -- http://www.delphi3d.net * +# ************************************************* +#*** Generated on 10/11/2002 + +when defined(windows): + {.push, callconv: stdcall.} +else: + {.push, callconv: cdecl.} +import + gl + +type + GLcharARB* = Char + TGLcharARB* = GLcharARB + PGLcharARB* = ptr GLcharARB + GLhandleARB* = int + TGLhandleARB* = GLhandleARB + PGLhandleARB* = ptr GLhandleARB + GLintptr* = int + TGLintptr* = GLintptr + PGLintptr* = ptr GLintptr + GLsizeiptr* = int + TGLsizeiptr* = GLsizeiptr + PGLsizeiptr* = ptr GLsizeiptr + GLchar* = Char + TGLchar* = GLchar + PGLchar* = cstring #***** GL_version_1_2 *****// + +const + GL_UNSIGNED_BYTE_3_3_2* = 0x00008032 + GL_UNSIGNED_SHORT_4_4_4_4* = 0x00008033 + GL_UNSIGNED_SHORT_5_5_5_1* = 0x00008034 + GL_UNSIGNED_INT_8_8_8_8* = 0x00008035 + GL_UNSIGNED_INT_10_10_10_2* = 0x00008036 + GL_RESCALE_NORMAL* = 0x0000803A + GL_UNSIGNED_BYTE_2_3_3_REV* = 0x00008362 + GL_UNSIGNED_SHORT_5_6_5* = 0x00008363 + GL_UNSIGNED_SHORT_5_6_5_REV* = 0x00008364 + GL_UNSIGNED_SHORT_4_4_4_4_REV* = 0x00008365 + GL_UNSIGNED_SHORT_1_5_5_5_REV* = 0x00008366 + GL_UNSIGNED_INT_8_8_8_8_REV* = 0x00008367 + GL_UNSIGNED_INT_2_10_10_10_REV* = 0x00008368 + GL_BGR* = 0x000080E0 + GL_BGRA* = 0x000080E1 + GL_MAX_ELEMENTS_VERTICES* = 0x000080E8 + GL_MAX_ELEMENTS_INDICES* = 0x000080E9 + GL_CLAMP_TO_EDGE* = 0x0000812F + GL_TEXTURE_MIN_LOD* = 0x0000813A + GL_TEXTURE_MAX_LOD* = 0x0000813B + GL_TEXTURE_BASE_LEVEL* = 0x0000813C + GL_TEXTURE_MAX_LEVEL* = 0x0000813D + GL_LIGHT_MODEL_COLOR_CONTROL* = 0x000081F8 + GL_SINGLE_COLOR* = 0x000081F9 + GL_SEPARATE_SPECULAR_COLOR* = 0x000081FA + GL_SMOOTH_POINT_SIZE_RANGE* = 0x00000B12 + GL_SMOOTH_POINT_SIZE_GRANULARITY* = 0x00000B13 + GL_SMOOTH_LINE_WIDTH_RANGE* = 0x00000B22 + GL_SMOOTH_LINE_WIDTH_GRANULARITY* = 0x00000B23 + GL_ALIASED_POINT_SIZE_RANGE* = 0x0000846D + GL_ALIASED_LINE_WIDTH_RANGE* = 0x0000846E + GL_PACK_SKIP_IMAGES* = 0x0000806B + GL_PACK_IMAGE_HEIGHT* = 0x0000806C + GL_UNPACK_SKIP_IMAGES* = 0x0000806D + GL_UNPACK_IMAGE_HEIGHT* = 0x0000806E + GL_TEXTURE_3D* = 0x0000806F + GL_PROXY_TEXTURE_3D* = 0x00008070 + GL_TEXTURE_DEPTH* = 0x00008071 + GL_TEXTURE_WRAP_R* = 0x00008072 + GL_MAX_3D_TEXTURE_SIZE* = 0x00008073 + +proc glBlendColor*(red: TGLclampf, green: TGLclampf, blue: TGLclampf, + alpha: TGLclampf){.dynlib: dllname, importc: "glBlendColor".} +proc glBlendEquation*(mode: TGLenum){.dynlib: dllname, + importc: "glBlendEquation".} +proc glDrawRangeElements*(mode: TGLenum, start: TGLuint, theend: TGLuint, + count: TGLsizei, thetype: TGLenum, indices: PGLvoid){. + dynlib: dllname, importc: "glDrawRangeElements".} +proc glColorTable*(target: TGLenum, internalformat: TGLenum, width: TGLsizei, + format: TGLenum, thetype: TGLenum, table: PGLvoid){. + dynlib: dllname, importc: "glColorTable".} +proc glColorTableParameterfv*(target: TGLenum, pname: TGLenum, params: PGLfloat){. + dynlib: dllname, importc: "glColorTableParameterfv".} +proc glColorTableParameteriv*(target: TGLenum, pname: TGLenum, params: PGLint){. + dynlib: dllname, importc: "glColorTableParameteriv".} +proc glCopyColorTable*(target: TGLenum, internalformat: TGLenum, x: TGLint, + y: TGLint, width: TGLsizei){.dynlib: dllname, + importc: "glCopyColorTable".} +proc glGetColorTable*(target: TGLenum, format: TGLenum, thetype: TGLenum, + table: PGLvoid){.dynlib: dllname, + importc: "glGetColorTable".} +proc glGetColorTableParameterfv*(target: TGLenum, pname: TGLenum, + params: PGLfloat){.dynlib: dllname, + importc: "glGetColorTableParameterfv".} +proc glGetColorTableParameteriv*(target: TGLenum, pname: TGLenum, params: PGLint){. + dynlib: dllname, importc: "glGetColorTableParameteriv".} +proc glColorSubTable*(target: TGLenum, start: TGLsizei, count: TGLsizei, + format: TGLenum, thetype: TGLenum, data: PGLvoid){. + dynlib: dllname, importc: "glColorSubTable".} +proc glCopyColorSubTable*(target: TGLenum, start: TGLsizei, x: TGLint, + y: TGLint, width: TGLsizei){.dynlib: dllname, + importc: "glCopyColorSubTable".} +proc glConvolutionFilter1D*(target: TGLenum, internalformat: TGLenum, + width: TGLsizei, format: TGLenum, thetype: TGLenum, + image: PGLvoid){.dynlib: dllname, + importc: "glConvolutionFilter1D".} +proc glConvolutionFilter2D*(target: TGLenum, internalformat: TGLenum, + width: TGLsizei, height: TGLsizei, format: TGLenum, + thetype: TGLenum, image: PGLvoid){.dynlib: dllname, + importc: "glConvolutionFilter2D".} +proc glConvolutionParameterf*(target: TGLenum, pname: TGLenum, params: TGLfloat){. + dynlib: dllname, importc: "glConvolutionParameterf".} +proc glConvolutionParameterfv*(target: TGLenum, pname: TGLenum, params: PGLfloat){. + dynlib: dllname, importc: "glConvolutionParameterfv".} +proc glConvolutionParameteri*(target: TGLenum, pname: TGLenum, params: TGLint){. + dynlib: dllname, importc: "glConvolutionParameteri".} +proc glConvolutionParameteriv*(target: TGLenum, pname: TGLenum, params: PGLint){. + dynlib: dllname, importc: "glConvolutionParameteriv".} +proc glCopyConvolutionFilter1D*(target: TGLenum, internalformat: TGLenum, + x: TGLint, y: TGLint, width: TGLsizei){. + dynlib: dllname, importc: "glCopyConvolutionFilter1D".} +proc glCopyConvolutionFilter2D*(target: TGLenum, internalformat: TGLenum, + x: TGLint, y: TGLint, width: TGLsizei, + height: TGLsizei){.dynlib: dllname, + importc: "glCopyConvolutionFilter2D".} +proc glGetConvolutionFilter*(target: TGLenum, format: TGLenum, thetype: TGLenum, + image: PGLvoid){.dynlib: dllname, + importc: "glGetConvolutionFilter".} +proc glGetConvolutionParameterfv*(target: TGLenum, pname: TGLenum, + params: PGLfloat){.dynlib: dllname, + importc: "glGetConvolutionParameterfv".} +proc glGetConvolutionParameteriv*(target: TGLenum, pname: TGLenum, + params: PGLint){.dynlib: dllname, + importc: "glGetConvolutionParameteriv".} +proc glGetSeparableFilter*(target: TGLenum, format: TGLenum, thetype: TGLenum, + row: PGLvoid, column: PGLvoid, span: PGLvoid){. + dynlib: dllname, importc: "glGetSeparableFilter".} +proc glSeparableFilter2D*(target: TGLenum, internalformat: TGLenum, + width: TGLsizei, height: TGLsizei, format: TGLenum, + thetype: TGLenum, row: PGLvoid, column: PGLvoid){. + dynlib: dllname, importc: "glSeparableFilter2D".} +proc glGetHistogram*(target: TGLenum, reset: TGLboolean, format: TGLenum, + thetype: TGLenum, values: PGLvoid){.dynlib: dllname, + importc: "glGetHistogram".} +proc glGetHistogramParameterfv*(target: TGLenum, pname: TGLenum, + params: PGLfloat){.dynlib: dllname, + importc: "glGetHistogramParameterfv".} +proc glGetHistogramParameteriv*(target: TGLenum, pname: TGLenum, params: PGLint){. + dynlib: dllname, importc: "glGetHistogramParameteriv".} +proc glGetMinmax*(target: TGLenum, reset: TGLboolean, format: TGLenum, + thetype: TGLenum, values: PGLvoid){.dynlib: dllname, + importc: "glGetMinmax".} +proc glGetMinmaxParameterfv*(target: TGLenum, pname: TGLenum, params: PGLfloat){. + dynlib: dllname, importc: "glGetMinmaxParameterfv".} +proc glGetMinmaxParameteriv*(target: TGLenum, pname: TGLenum, params: PGLint){. + dynlib: dllname, importc: "glGetMinmaxParameteriv".} +proc glHistogram*(target: TGLenum, width: TGLsizei, internalformat: TGLenum, + sink: TGLboolean){.dynlib: dllname, importc: "glHistogram".} +proc glMinmax*(target: TGLenum, internalformat: TGLenum, sink: TGLboolean){. + dynlib: dllname, importc: "glMinmax".} +proc glResetHistogram*(target: TGLenum){.dynlib: dllname, + importc: "glResetHistogram".} +proc glResetMinmax*(target: TGLenum){.dynlib: dllname, importc: "glResetMinmax".} +proc glTexImage3D*(target: TGLenum, level: TGLint, internalformat: TGLint, + width: TGLsizei, height: TGLsizei, depth: TGLsizei, + border: TGLint, format: TGLenum, thetype: TGLenum, + pixels: PGLvoid){.dynlib: dllname, importc: "glTexImage3D".} +proc glTexSubImage3D*(target: TGLenum, level: TGLint, xoffset: TGLint, + yoffset: TGLint, zoffset: TGLint, width: TGLsizei, + height: TGLsizei, depth: TGLsizei, format: TGLenum, + thetype: TGLenum, pixels: PGLvoid){.dynlib: dllname, + importc: "glTexSubImage3D".} +proc glCopyTexSubImage3D*(target: TGLenum, level: TGLint, xoffset: TGLint, + yoffset: TGLint, zoffset: TGLint, x: TGLint, + y: TGLint, width: TGLsizei, height: TGLsizei){. + dynlib: dllname, importc: "glCopyTexSubImage3D".} +proc glActiveTextureARB*(texture: TGLenum){.dynlib: dllname, + importc: "glActiveTextureARB".} +proc glClientActiveTextureARB*(texture: TGLenum){.dynlib: dllname, + importc: "glClientActiveTextureARB".} +proc glMultiTexCoord1dARB*(target: TGLenum, s: TGLdouble){.dynlib: dllname, + importc: "glMultiTexCoord1dARB".} +proc glMultiTexCoord1dvARB*(target: TGLenum, v: PGLdouble){.dynlib: dllname, + importc: "glMultiTexCoord1dvARB".} +proc glMultiTexCoord1fARB*(target: TGLenum, s: TGLfloat){.dynlib: dllname, + importc: "glMultiTexCoord1fARB".} +proc glMultiTexCoord1fvARB*(target: TGLenum, v: PGLfloat){.dynlib: dllname, + importc: "glMultiTexCoord1fvARB".} +proc glMultiTexCoord1iARB*(target: TGLenum, s: TGLint){.dynlib: dllname, + importc: "glMultiTexCoord1iARB".} +proc glMultiTexCoord1ivARB*(target: TGLenum, v: PGLint){.dynlib: dllname, + importc: "glMultiTexCoord1ivARB".} +proc glMultiTexCoord1sARB*(target: TGLenum, s: TGLshort){.dynlib: dllname, + importc: "glMultiTexCoord1sARB".} +proc glMultiTexCoord1svARB*(target: TGLenum, v: PGLshort){.dynlib: dllname, + importc: "glMultiTexCoord1svARB".} +proc glMultiTexCoord2dARB*(target: TGLenum, s: TGLdouble, t: TGLdouble){. + dynlib: dllname, importc: "glMultiTexCoord2dARB".} +proc glMultiTexCoord2dvARB*(target: TGLenum, v: PGLdouble){.dynlib: dllname, + importc: "glMultiTexCoord2dvARB".} +proc glMultiTexCoord2fARB*(target: TGLenum, s: TGLfloat, t: TGLfloat){. + dynlib: dllname, importc: "glMultiTexCoord2fARB".} +proc glMultiTexCoord2fvARB*(target: TGLenum, v: PGLfloat){.dynlib: dllname, + importc: "glMultiTexCoord2fvARB".} +proc glMultiTexCoord2iARB*(target: TGLenum, s: TGLint, t: TGLint){. + dynlib: dllname, importc: "glMultiTexCoord2iARB".} +proc glMultiTexCoord2ivARB*(target: TGLenum, v: PGLint){.dynlib: dllname, + importc: "glMultiTexCoord2ivARB".} +proc glMultiTexCoord2sARB*(target: TGLenum, s: TGLshort, t: TGLshort){. + dynlib: dllname, importc: "glMultiTexCoord2sARB".} +proc glMultiTexCoord2svARB*(target: TGLenum, v: PGLshort){.dynlib: dllname, + importc: "glMultiTexCoord2svARB".} +proc glMultiTexCoord3dARB*(target: TGLenum, s: TGLdouble, t: TGLdouble, + r: TGLdouble){.dynlib: dllname, + importc: "glMultiTexCoord3dARB".} +proc glMultiTexCoord3dvARB*(target: TGLenum, v: PGLdouble){.dynlib: dllname, + importc: "glMultiTexCoord3dvARB".} +proc glMultiTexCoord3fARB*(target: TGLenum, s: TGLfloat, t: TGLfloat, + r: TGLfloat){.dynlib: dllname, + importc: "glMultiTexCoord3fARB".} +proc glMultiTexCoord3fvARB*(target: TGLenum, v: PGLfloat){.dynlib: dllname, + importc: "glMultiTexCoord3fvARB".} +proc glMultiTexCoord3iARB*(target: TGLenum, s: TGLint, t: TGLint, r: TGLint){. + dynlib: dllname, importc: "glMultiTexCoord3iARB".} +proc glMultiTexCoord3ivARB*(target: TGLenum, v: PGLint){.dynlib: dllname, + importc: "glMultiTexCoord3ivARB".} +proc glMultiTexCoord3sARB*(target: TGLenum, s: TGLshort, t: TGLshort, + r: TGLshort){.dynlib: dllname, + importc: "glMultiTexCoord3sARB".} +proc glMultiTexCoord3svARB*(target: TGLenum, v: PGLshort){.dynlib: dllname, + importc: "glMultiTexCoord3svARB".} +proc glMultiTexCoord4dARB*(target: TGLenum, s: TGLdouble, t: TGLdouble, + r: TGLdouble, q: TGLdouble){.dynlib: dllname, + importc: "glMultiTexCoord4dARB".} +proc glMultiTexCoord4dvARB*(target: TGLenum, v: PGLdouble){.dynlib: dllname, + importc: "glMultiTexCoord4dvARB".} +proc glMultiTexCoord4fARB*(target: TGLenum, s: TGLfloat, t: TGLfloat, + r: TGLfloat, q: TGLfloat){.dynlib: dllname, + importc: "glMultiTexCoord4fARB".} +proc glMultiTexCoord4fvARB*(target: TGLenum, v: PGLfloat){.dynlib: dllname, + importc: "glMultiTexCoord4fvARB".} +proc glMultiTexCoord4iARB*(target: TGLenum, s: TGLint, t: TGLint, r: TGLint, + q: TGLint){.dynlib: dllname, + importc: "glMultiTexCoord4iARB".} +proc glMultiTexCoord4ivARB*(target: TGLenum, v: PGLint){.dynlib: dllname, + importc: "glMultiTexCoord4ivARB".} +proc glMultiTexCoord4sARB*(target: TGLenum, s: TGLshort, t: TGLshort, + r: TGLshort, q: TGLshort){.dynlib: dllname, + importc: "glMultiTexCoord4sARB".} +proc glMultiTexCoord4svARB*(target: TGLenum, v: PGLshort){.dynlib: dllname, + importc: "glMultiTexCoord4svARB".} +proc glSampleCoverageARB*(value: TGLclampf, invert: TGLboolean){. + dynlib: dllname, importc: "glSampleCoverageARB".} + #***** GL_ARB_texture_env_add *****// +proc glWeightbvARB*(size: TGLint, weights: PGLbyte){.dynlib: dllname, + importc: "glWeightbvARB".} +proc glWeightsvARB*(size: TGLint, weights: PGLshort){.dynlib: dllname, + importc: "glWeightsvARB".} +proc glWeightivARB*(size: TGLint, weights: PGLint){.dynlib: dllname, + importc: "glWeightivARB".} +proc glWeightfvARB*(size: TGLint, weights: PGLfloat){.dynlib: dllname, + importc: "glWeightfvARB".} +proc glWeightdvARB*(size: TGLint, weights: PGLdouble){.dynlib: dllname, + importc: "glWeightdvARB".} +proc glWeightvARB*(size: TGLint, weights: PGLdouble){.dynlib: dllname, + importc: "glWeightvARB".} +proc glWeightubvARB*(size: TGLint, weights: PGLubyte){.dynlib: dllname, + importc: "glWeightubvARB".} +proc glWeightusvARB*(size: TGLint, weights: PGLushort){.dynlib: dllname, + importc: "glWeightusvARB".} +proc glWeightuivARB*(size: TGLint, weights: PGLuint){.dynlib: dllname, + importc: "glWeightuivARB".} +proc glWeightPointerARB*(size: TGLint, thetype: TGLenum, stride: TGLsizei, + pointer: PGLvoid){.dynlib: dllname, + importc: "glWeightPointerARB".} +proc glVertexBlendARB*(count: TGLint){.dynlib: dllname, + importc: "glVertexBlendARB".} +proc glVertexAttrib1sARB*(index: TGLuint, x: TGLshort){.dynlib: dllname, + importc: "glVertexAttrib1sARB".} +proc glVertexAttrib1fARB*(index: TGLuint, x: TGLfloat){.dynlib: dllname, + importc: "glVertexAttrib1fARB".} +proc glVertexAttrib1dARB*(index: TGLuint, x: TGLdouble){.dynlib: dllname, + importc: "glVertexAttrib1dARB".} +proc glVertexAttrib2sARB*(index: TGLuint, x: TGLshort, y: TGLshort){. + dynlib: dllname, importc: "glVertexAttrib2sARB".} +proc glVertexAttrib2fARB*(index: TGLuint, x: TGLfloat, y: TGLfloat){. + dynlib: dllname, importc: "glVertexAttrib2fARB".} +proc glVertexAttrib2dARB*(index: TGLuint, x: TGLdouble, y: TGLdouble){. + dynlib: dllname, importc: "glVertexAttrib2dARB".} +proc glVertexAttrib3sARB*(index: TGLuint, x: TGLshort, y: TGLshort, z: TGLshort){. + dynlib: dllname, importc: "glVertexAttrib3sARB".} +proc glVertexAttrib3fARB*(index: TGLuint, x: TGLfloat, y: TGLfloat, z: TGLfloat){. + dynlib: dllname, importc: "glVertexAttrib3fARB".} +proc glVertexAttrib3dARB*(index: TGLuint, x: TGLdouble, y: TGLdouble, + z: TGLdouble){.dynlib: dllname, + importc: "glVertexAttrib3dARB".} +proc glVertexAttrib4sARB*(index: TGLuint, x: TGLshort, y: TGLshort, z: TGLshort, + w: TGLshort){.dynlib: dllname, + importc: "glVertexAttrib4sARB".} +proc glVertexAttrib4fARB*(index: TGLuint, x: TGLfloat, y: TGLfloat, z: TGLfloat, + w: TGLfloat){.dynlib: dllname, + importc: "glVertexAttrib4fARB".} +proc glVertexAttrib4dARB*(index: TGLuint, x: TGLdouble, y: TGLdouble, + z: TGLdouble, w: TGLdouble){.dynlib: dllname, + importc: "glVertexAttrib4dARB".} +proc glVertexAttrib4NubARB*(index: TGLuint, x: TGLubyte, y: TGLubyte, + z: TGLubyte, w: TGLubyte){.dynlib: dllname, + importc: "glVertexAttrib4NubARB".} +proc glVertexAttrib1svARB*(index: TGLuint, v: PGLshort){.dynlib: dllname, + importc: "glVertexAttrib1svARB".} +proc glVertexAttrib1fvARB*(index: TGLuint, v: PGLfloat){.dynlib: dllname, + importc: "glVertexAttrib1fvARB".} +proc glVertexAttrib1dvARB*(index: TGLuint, v: PGLdouble){.dynlib: dllname, + importc: "glVertexAttrib1dvARB".} +proc glVertexAttrib2svARB*(index: TGLuint, v: PGLshort){.dynlib: dllname, + importc: "glVertexAttrib2svARB".} +proc glVertexAttrib2fvARB*(index: TGLuint, v: PGLfloat){.dynlib: dllname, + importc: "glVertexAttrib2fvARB".} +proc glVertexAttrib2dvARB*(index: TGLuint, v: PGLdouble){.dynlib: dllname, + importc: "glVertexAttrib2dvARB".} +proc glVertexAttrib3svARB*(index: TGLuint, v: PGLshort){.dynlib: dllname, + importc: "glVertexAttrib3svARB".} +proc glVertexAttrib3fvARB*(index: TGLuint, v: PGLfloat){.dynlib: dllname, + importc: "glVertexAttrib3fvARB".} +proc glVertexAttrib3dvARB*(index: TGLuint, v: PGLdouble){.dynlib: dllname, + importc: "glVertexAttrib3dvARB".} +proc glVertexAttrib4bvARB*(index: TGLuint, v: PGLbyte){.dynlib: dllname, + importc: "glVertexAttrib4bvARB".} +proc glVertexAttrib4svARB*(index: TGLuint, v: PGLshort){.dynlib: dllname, + importc: "glVertexAttrib4svARB".} +proc glVertexAttrib4ivARB*(index: TGLuint, v: PGLint){.dynlib: dllname, + importc: "glVertexAttrib4ivARB".} +proc glVertexAttrib4ubvARB*(index: TGLuint, v: PGLubyte){.dynlib: dllname, + importc: "glVertexAttrib4ubvARB".} +proc glVertexAttrib4usvARB*(index: TGLuint, v: PGLushort){.dynlib: dllname, + importc: "glVertexAttrib4usvARB".} +proc glVertexAttrib4uivARB*(index: TGLuint, v: PGLuint){.dynlib: dllname, + importc: "glVertexAttrib4uivARB".} +proc glVertexAttrib4fvARB*(index: TGLuint, v: PGLfloat){.dynlib: dllname, + importc: "glVertexAttrib4fvARB".} +proc glVertexAttrib4dvARB*(index: TGLuint, v: PGLdouble){.dynlib: dllname, + importc: "glVertexAttrib4dvARB".} +proc glVertexAttrib4NbvARB*(index: TGLuint, v: PGLbyte){.dynlib: dllname, + importc: "glVertexAttrib4NbvARB".} +proc glVertexAttrib4NsvARB*(index: TGLuint, v: PGLshort){.dynlib: dllname, + importc: "glVertexAttrib4NsvARB".} +proc glVertexAttrib4NivARB*(index: TGLuint, v: PGLint){.dynlib: dllname, + importc: "glVertexAttrib4NivARB".} +proc glVertexAttrib4NubvARB*(index: TGLuint, v: PGLubyte){.dynlib: dllname, + importc: "glVertexAttrib4NubvARB".} +proc glVertexAttrib4NusvARB*(index: TGLuint, v: PGLushort){.dynlib: dllname, + importc: "glVertexAttrib4NusvARB".} +proc glVertexAttrib4NuivARB*(index: TGLuint, v: PGLuint){.dynlib: dllname, + importc: "glVertexAttrib4NuivARB".} +proc glVertexAttribPointerARB*(index: TGLuint, size: TGLint, thetype: TGLenum, + normalized: TGLboolean, stride: TGLsizei, + pointer: PGLvoid){.dynlib: dllname, + importc: "glVertexAttribPointerARB".} +proc glEnableVertexAttribArrayARB*(index: TGLuint){.dynlib: dllname, + importc: "glEnableVertexAttribArrayARB".} +proc glDisableVertexAttribArrayARB*(index: TGLuint){.dynlib: dllname, + importc: "glDisableVertexAttribArrayARB".} +proc glProgramStringARB*(target: TGLenum, format: TGLenum, length: TGLsizei, + str: PGLvoid){.dynlib: dllname, + importc: "glProgramStringARB".} +proc glBindProgramARB*(target: TGLenum, theProgram: TGLuint){.dynlib: dllname, + importc: "glBindProgramARB".} +proc glDeleteProgramsARB*(n: TGLsizei, programs: PGLuint){.dynlib: dllname, + importc: "glDeleteProgramsARB".} +proc glGenProgramsARB*(n: TGLsizei, programs: PGLuint){.dynlib: dllname, + importc: "glGenProgramsARB".} +proc glProgramEnvParameter4dARB*(target: TGLenum, index: TGLuint, x: TGLdouble, + y: TGLdouble, z: TGLdouble, w: TGLdouble){. + dynlib: dllname, importc: "glProgramEnvParameter4dARB".} +proc glProgramEnvParameter4dvARB*(target: TGLenum, index: TGLuint, + params: PGLdouble){.dynlib: dllname, + importc: "glProgramEnvParameter4dvARB".} +proc glProgramEnvParameter4fARB*(target: TGLenum, index: TGLuint, x: TGLfloat, + y: TGLfloat, z: TGLfloat, w: TGLfloat){. + dynlib: dllname, importc: "glProgramEnvParameter4fARB".} +proc glProgramEnvParameter4fvARB*(target: TGLenum, index: TGLuint, + params: PGLfloat){.dynlib: dllname, + importc: "glProgramEnvParameter4fvARB".} +proc glProgramLocalParameter4dARB*(target: TGLenum, index: TGLuint, + x: TGLdouble, y: TGLdouble, z: TGLdouble, + w: TGLdouble){.dynlib: dllname, + importc: "glProgramLocalParameter4dARB".} +proc glProgramLocalParameter4dvARB*(target: TGLenum, index: TGLuint, + params: PGLdouble){.dynlib: dllname, + importc: "glProgramLocalParameter4dvARB".} +proc glProgramLocalParameter4fARB*(target: TGLenum, index: TGLuint, x: TGLfloat, + y: TGLfloat, z: TGLfloat, w: TGLfloat){. + dynlib: dllname, importc: "glProgramLocalParameter4fARB".} +proc glProgramLocalParameter4fvARB*(target: TGLenum, index: TGLuint, + params: PGLfloat){.dynlib: dllname, + importc: "glProgramLocalParameter4fvARB".} +proc glGetProgramEnvParameterdvARB*(target: TGLenum, index: TGLuint, + params: PGLdouble){.dynlib: dllname, + importc: "glGetProgramEnvParameterdvARB".} +proc glGetProgramEnvParameterfvARB*(target: TGLenum, index: TGLuint, + params: PGLfloat){.dynlib: dllname, + importc: "glGetProgramEnvParameterfvARB".} +proc glGetProgramLocalParameterdvARB*(target: TGLenum, index: TGLuint, + params: PGLdouble){.dynlib: dllname, + importc: "glGetProgramLocalParameterdvARB".} +proc glGetProgramLocalParameterfvARB*(target: TGLenum, index: TGLuint, + params: PGLfloat){.dynlib: dllname, + importc: "glGetProgramLocalParameterfvARB".} +proc glGetProgramivARB*(target: TGLenum, pname: TGLenum, params: PGLint){. + dynlib: dllname, importc: "glGetProgramivARB".} +proc glGetProgramStringARB*(target: TGLenum, pname: TGLenum, str: PGLvoid){. + dynlib: dllname, importc: "glGetProgramStringARB".} +proc glGetVertexAttribdvARB*(index: TGLuint, pname: TGLenum, params: PGLdouble){. + dynlib: dllname, importc: "glGetVertexAttribdvARB".} +proc glGetVertexAttribfvARB*(index: TGLuint, pname: TGLenum, params: PGLfloat){. + dynlib: dllname, importc: "glGetVertexAttribfvARB".} +proc glGetVertexAttribivARB*(index: TGLuint, pname: TGLenum, params: PGLint){. + dynlib: dllname, importc: "glGetVertexAttribivARB".} +proc glGetVertexAttribPointervARB*(index: TGLuint, pname: TGLenum, + pointer: PGLvoid){.dynlib: dllname, + importc: "glGetVertexAttribPointervARB".} +proc glIsProgramARB*(theProgram: TGLuint): TGLboolean{.dynlib: dllname, + importc: "glIsProgramARB".} + #***** GL_ARB_window_pos *****// +proc glWindowPos2dARB*(x: TGLdouble, y: TGLdouble){.dynlib: dllname, + importc: "glWindowPos2dARB".} +proc glWindowPos2fARB*(x: TGLfloat, y: TGLfloat){.dynlib: dllname, + importc: "glWindowPos2fARB".} +proc glWindowPos2iARB*(x: TGLint, y: TGLint){.dynlib: dllname, + importc: "glWindowPos2iARB".} +proc glWindowPos2sARB*(x: TGLshort, y: TGLshort){.dynlib: dllname, + importc: "glWindowPos2sARB".} +proc glWindowPos2dvARB*(p: PGLdouble){.dynlib: dllname, + importc: "glWindowPos2dvARB".} +proc glWindowPos2fvARB*(p: PGLfloat){.dynlib: dllname, + importc: "glWindowPos2fvARB".} +proc glWindowPos2ivARB*(p: PGLint){.dynlib: dllname, + importc: "glWindowPos2ivARB".} +proc glWindowPos2svARB*(p: PGLshort){.dynlib: dllname, + importc: "glWindowPos2svARB".} +proc glWindowPos3dARB*(x: TGLdouble, y: TGLdouble, z: TGLdouble){. + dynlib: dllname, importc: "glWindowPos3dARB".} +proc glWindowPos3fARB*(x: TGLfloat, y: TGLfloat, z: TGLfloat){.dynlib: dllname, + importc: "glWindowPos3fARB".} +proc glWindowPos3iARB*(x: TGLint, y: TGLint, z: TGLint){.dynlib: dllname, + importc: "glWindowPos3iARB".} +proc glWindowPos3sARB*(x: TGLshort, y: TGLshort, z: TGLshort){.dynlib: dllname, + importc: "glWindowPos3sARB".} +proc glWindowPos3dvARB*(p: PGLdouble){.dynlib: dllname, + importc: "glWindowPos3dvARB".} +proc glWindowPos3fvARB*(p: PGLfloat){.dynlib: dllname, + importc: "glWindowPos3fvARB".} +proc glWindowPos3ivARB*(p: PGLint){.dynlib: dllname, + importc: "glWindowPos3ivARB".} +proc glWindowPos3svARB*(p: PGLshort){.dynlib: dllname, + importc: "glWindowPos3svARB".} +proc glBlendEquationSeparate*(modeRGB: TGLenum, modeAlpha: TGLenum){. + dynlib: dllname, importc: "glBlendEquationSeparate".} +proc glDrawBuffers*(n: TGLsizei, bufs: PGLenum){.dynlib: dllname, + importc: "glDrawBuffers".} +proc glStencilOpSeparate*(face: TGLenum, sfail: TGLenum, dpfail: TGLenum, + dppass: TGLenum){.dynlib: dllname, + importc: "glStencilOpSeparate".} +proc glStencilFuncSeparate*(frontfunc: TGLenum, backfunc: TGLenum, + theRef: TGLint, mask: TGLuint){.dynlib: dllname, + importc: "glStencilFuncSeparate".} +proc glStencilMaskSeparate*(face: TGLenum, mask: TGLuint){.dynlib: dllname, + importc: "glStencilMaskSeparate".} +proc glAttachShader*(theProgram: TGLuint, shader: TGLuint){.dynlib: dllname, + importc: "glAttachShader".} +proc glBindAttribLocation*(theProgram: TGLuint, index: TGLuint, name: PGLchar){. + dynlib: dllname, importc: "glBindAttribLocation".} +proc glCompileShader*(shader: TGLuint){.dynlib: dllname, + importc: "glCompileShader".} +proc glCreateProgram*(): TGLuint{.dynlib: dllname, importc: "glCreateProgram".} +proc glCreateShader*(thetype: TGLenum): TGLuint{.dynlib: dllname, + importc: "glCreateShader".} +proc glDeleteProgram*(theProgram: TGLuint){.dynlib: dllname, + importc: "glDeleteProgram".} +proc glDeleteShader*(shader: TGLuint){.dynlib: dllname, + importc: "glDeleteShader".} +proc glDetachShader*(theProgram: TGLuint, shader: TGLuint){.dynlib: dllname, + importc: "glDetachShader".} +proc glDisableVertexAttribArray*(index: TGLuint){.dynlib: dllname, + importc: "glDisableVertexAttribArray".} +proc glEnableVertexAttribArray*(index: TGLuint){.dynlib: dllname, + importc: "glEnableVertexAttribArray".} +proc glGetActiveAttrib*(theProgram: TGLuint, index: TGLuint, bufSize: TGLsizei, + len: PGLsizei, size: PGLint, thetype: PGLenum, + name: PGLchar){.dynlib: dllname, + importc: "glGetActiveAttrib".} +proc glGetActiveUniform*(theProgram: TGLuint, index: TGLuint, bufSize: TGLsizei, + len: PGLsizei, size: PGLint, thetype: PGLenum, + name: PGLchar){.dynlib: dllname, + importc: "glGetActiveUniform".} +proc glGetAttachedShaders*(theProgram: TGLuint, maxCount: TGLsizei, + count: PGLsizei, obj: PGLuint){.dynlib: dllname, + importc: "glGetAttachedShaders".} +proc glGetAttribLocation*(theProgram: TGLuint, name: PGLchar): TGLint{. + dynlib: dllname, importc: "glGetAttribLocation".} +proc glGetProgramiv*(theProgram: TGLuint, pname: TGLenum, params: PGLint){. + dynlib: dllname, importc: "glGetProgramiv".} +proc glGetProgramInfoLog*(theProgram: TGLuint, bufSize: TGLsizei, len: PGLsizei, + infoLog: PGLchar){.dynlib: dllname, + importc: "glGetProgramInfoLog".} +proc glGetShaderiv*(shader: TGLuint, pname: TGLenum, params: PGLint){. + dynlib: dllname, importc: "glGetShaderiv".} +proc glGetShaderInfoLog*(shader: TGLuint, bufSize: TGLsizei, len: PGLsizei, + infoLog: PGLchar){.dynlib: dllname, + importc: "glGetShaderInfoLog".} +proc glGetShaderSource*(shader: TGLuint, bufSize: TGLsizei, len: PGLsizei, + source: PGLchar){.dynlib: dllname, + importc: "glGetShaderSource".} +proc glGetUniformLocation*(theProgram: TGLuint, name: PGLchar): TGLint{. + dynlib: dllname, importc: "glGetUniformLocation".} +proc glGetUniformfv*(theProgram: TGLuint, location: TGLint, params: PGLfloat){. + dynlib: dllname, importc: "glGetUniformfv".} +proc glGetUniformiv*(theProgram: TGLuint, location: TGLint, params: PGLint){. + dynlib: dllname, importc: "glGetUniformiv".} +proc glGetVertexAttribdv*(index: TGLuint, pname: TGLenum, params: PGLdouble){. + dynlib: dllname, importc: "glGetVertexAttribdv".} +proc glGetVertexAttribfv*(index: TGLuint, pname: TGLenum, params: PGLfloat){. + dynlib: dllname, importc: "glGetVertexAttribfv".} +proc glGetVertexAttribiv*(index: TGLuint, pname: TGLenum, params: PGLint){. + dynlib: dllname, importc: "glGetVertexAttribiv".} +proc glGetVertexAttribPointerv*(index: TGLuint, pname: TGLenum, pointer: PGLvoid){. + dynlib: dllname, importc: "glGetVertexAttribPointerv".} +proc glIsProgram*(theProgram: TGLuint): TGLboolean{.dynlib: dllname, + importc: "glIsProgram".} +proc glIsShader*(shader: TGLuint): TGLboolean{.dynlib: dllname, + importc: "glIsShader".} +proc glLinkProgram*(theProgram: TGLuint){.dynlib: dllname, + importc: "glLinkProgram".} +proc glShaderSource*(shader: TGLuint, count: TGLsizei, str: PGLchar, len: PGLint){. + dynlib: dllname, importc: "glShaderSource".} +proc glUseProgram*(theProgram: TGLuint){.dynlib: dllname, + importc: "glUseProgram".} +proc glUniform1f*(location: TGLint, v0: TGLfloat){.dynlib: dllname, + importc: "glUniform1f".} +proc glUniform2f*(location: TGLint, v0: TGLfloat, v1: TGLfloat){. + dynlib: dllname, importc: "glUniform2f".} +proc glUniform3f*(location: TGLint, v0: TGLfloat, v1: TGLfloat, v2: TGLfloat){. + dynlib: dllname, importc: "glUniform3f".} +proc glUniform4f*(location: TGLint, v0: TGLfloat, v1: TGLfloat, v2: TGLfloat, + v3: TGLfloat){.dynlib: dllname, importc: "glUniform4f".} +proc glUniform1i*(location: TGLint, v0: TGLint){.dynlib: dllname, + importc: "glUniform1i".} +proc glUniform2i*(location: TGLint, v0: TGLint, v1: TGLint){.dynlib: dllname, + importc: "glUniform2i".} +proc glUniform3i*(location: TGLint, v0: TGLint, v1: TGLint, v2: TGLint){. + dynlib: dllname, importc: "glUniform3i".} +proc glUniform4i*(location: TGLint, v0: TGLint, v1: TGLint, v2: TGLint, + v3: TGLint){.dynlib: dllname, importc: "glUniform4i".} +proc glUniform1fv*(location: TGLint, count: TGLsizei, value: PGLfloat){. + dynlib: dllname, importc: "glUniform1fv".} +proc glUniform2fv*(location: TGLint, count: TGLsizei, value: PGLfloat){. + dynlib: dllname, importc: "glUniform2fv".} +proc glUniform3fv*(location: TGLint, count: TGLsizei, value: PGLfloat){. + dynlib: dllname, importc: "glUniform3fv".} +proc glUniform4fv*(location: TGLint, count: TGLsizei, value: PGLfloat){. + dynlib: dllname, importc: "glUniform4fv".} +proc glUniform1iv*(location: TGLint, count: TGLsizei, value: PGLint){. + dynlib: dllname, importc: "glUniform1iv".} +proc glUniform2iv*(location: TGLint, count: TGLsizei, value: PGLint){. + dynlib: dllname, importc: "glUniform2iv".} +proc glUniform3iv*(location: TGLint, count: TGLsizei, value: PGLint){. + dynlib: dllname, importc: "glUniform3iv".} +proc glUniform4iv*(location: TGLint, count: TGLsizei, value: PGLint){. + dynlib: dllname, importc: "glUniform4iv".} +proc glUniformMatrix2fv*(location: TGLint, count: TGLsizei, + transpose: TGLboolean, value: PGLfloat){. + dynlib: dllname, importc: "glUniformMatrix2fv".} +proc glUniformMatrix3fv*(location: TGLint, count: TGLsizei, + transpose: TGLboolean, value: PGLfloat){. + dynlib: dllname, importc: "glUniformMatrix3fv".} +proc glUniformMatrix4fv*(location: TGLint, count: TGLsizei, + transpose: TGLboolean, value: PGLfloat){. + dynlib: dllname, importc: "glUniformMatrix4fv".} +proc glValidateProgram*(theProgram: TGLuint){.dynlib: dllname, + importc: "glValidateProgram".} +proc glVertexAttrib1d*(index: TGLuint, x: TGLdouble){.dynlib: dllname, + importc: "glVertexAttrib1d".} +proc glVertexAttrib1dv*(index: TGLuint, v: PGLdouble){.dynlib: dllname, + importc: "glVertexAttrib1dv".} +proc glVertexAttrib1f*(index: TGLuint, x: TGLfloat){.dynlib: dllname, + importc: "glVertexAttrib1f".} +proc glVertexAttrib1fv*(index: TGLuint, v: PGLfloat){.dynlib: dllname, + importc: "glVertexAttrib1fv".} +proc glVertexAttrib1s*(index: TGLuint, x: TGLshort){.dynlib: dllname, + importc: "glVertexAttrib1s".} +proc glVertexAttrib1sv*(index: TGLuint, v: PGLshort){.dynlib: dllname, + importc: "glVertexAttrib1sv".} +proc glVertexAttrib2d*(index: TGLuint, x: TGLdouble, y: TGLdouble){. + dynlib: dllname, importc: "glVertexAttrib2d".} +proc glVertexAttrib2dv*(index: TGLuint, v: PGLdouble){.dynlib: dllname, + importc: "glVertexAttrib2dv".} +proc glVertexAttrib2f*(index: TGLuint, x: TGLfloat, y: TGLfloat){. + dynlib: dllname, importc: "glVertexAttrib2f".} +proc glVertexAttrib2fv*(index: TGLuint, v: PGLfloat){.dynlib: dllname, + importc: "glVertexAttrib2fv".} +proc glVertexAttrib2s*(index: TGLuint, x: TGLshort, y: TGLshort){. + dynlib: dllname, importc: "glVertexAttrib2s".} +proc glVertexAttrib2sv*(index: TGLuint, v: PGLshort){.dynlib: dllname, + importc: "glVertexAttrib2sv".} +proc glVertexAttrib3d*(index: TGLuint, x: TGLdouble, y: TGLdouble, z: TGLdouble){. + dynlib: dllname, importc: "glVertexAttrib3d".} +proc glVertexAttrib3dv*(index: TGLuint, v: PGLdouble){.dynlib: dllname, + importc: "glVertexAttrib3dv".} +proc glVertexAttrib3f*(index: TGLuint, x: TGLfloat, y: TGLfloat, z: TGLfloat){. + dynlib: dllname, importc: "glVertexAttrib3f".} +proc glVertexAttrib3fv*(index: TGLuint, v: PGLfloat){.dynlib: dllname, + importc: "glVertexAttrib3fv".} +proc glVertexAttrib3s*(index: TGLuint, x: TGLshort, y: TGLshort, z: TGLshort){. + dynlib: dllname, importc: "glVertexAttrib3s".} +proc glVertexAttrib3sv*(index: TGLuint, v: PGLshort){.dynlib: dllname, + importc: "glVertexAttrib3sv".} +proc glVertexAttrib4Nbv*(index: TGLuint, v: PGLbyte){.dynlib: dllname, + importc: "glVertexAttrib4Nbv".} +proc glVertexAttrib4Niv*(index: TGLuint, v: PGLint){.dynlib: dllname, + importc: "glVertexAttrib4Niv".} +proc glVertexAttrib4Nsv*(index: TGLuint, v: PGLshort){.dynlib: dllname, + importc: "glVertexAttrib4Nsv".} +proc glVertexAttrib4Nub*(index: TGLuint, x: TGLubyte, y: TGLubyte, z: TGLubyte, + w: TGLubyte){.dynlib: dllname, + importc: "glVertexAttrib4Nub".} +proc glVertexAttrib4Nubv*(index: TGLuint, v: PGLubyte){.dynlib: dllname, + importc: "glVertexAttrib4Nubv".} +proc glVertexAttrib4Nuiv*(index: TGLuint, v: PGLuint){.dynlib: dllname, + importc: "glVertexAttrib4Nuiv".} +proc glVertexAttrib4Nusv*(index: TGLuint, v: PGLushort){.dynlib: dllname, + importc: "glVertexAttrib4Nusv".} +proc glVertexAttrib4bv*(index: TGLuint, v: PGLbyte){.dynlib: dllname, + importc: "glVertexAttrib4bv".} +proc glVertexAttrib4d*(index: TGLuint, x: TGLdouble, y: TGLdouble, z: TGLdouble, + w: TGLdouble){.dynlib: dllname, + importc: "glVertexAttrib4d".} +proc glVertexAttrib4dv*(index: TGLuint, v: PGLdouble){.dynlib: dllname, + importc: "glVertexAttrib4dv".} +proc glVertexAttrib4f*(index: TGLuint, x: TGLfloat, y: TGLfloat, z: TGLfloat, + w: TGLfloat){.dynlib: dllname, + importc: "glVertexAttrib4f".} +proc glVertexAttrib4fv*(index: TGLuint, v: PGLfloat){.dynlib: dllname, + importc: "glVertexAttrib4fv".} +proc glVertexAttrib4iv*(index: TGLuint, v: PGLint){.dynlib: dllname, + importc: "glVertexAttrib4iv".} +proc glVertexAttrib4s*(index: TGLuint, x: TGLshort, y: TGLshort, z: TGLshort, + w: TGLshort){.dynlib: dllname, + importc: "glVertexAttrib4s".} +proc glVertexAttrib4sv*(index: TGLuint, v: PGLshort){.dynlib: dllname, + importc: "glVertexAttrib4sv".} +proc glVertexAttrib4ubv*(index: TGLuint, v: PGLubyte){.dynlib: dllname, + importc: "glVertexAttrib4ubv".} +proc glVertexAttrib4uiv*(index: TGLuint, v: PGLuint){.dynlib: dllname, + importc: "glVertexAttrib4uiv".} +proc glVertexAttrib4usv*(index: TGLuint, v: PGLushort){.dynlib: dllname, + importc: "glVertexAttrib4usv".} +proc glVertexAttribPointer*(index: TGLuint, size: TGLint, thetype: TGLenum, + normalized: TGLboolean, stride: TGLsizei, + pointer: PGLvoid){.dynlib: dllname, + importc: "glVertexAttribPointer".} +const + GL_CONSTANT_COLOR* = 0x00008001 + GL_ONE_MINUS_CONSTANT_COLOR* = 0x00008002 + GL_CONSTANT_ALPHA* = 0x00008003 + GL_ONE_MINUS_CONSTANT_ALPHA* = 0x00008004 + constGL_BLEND_COLOR* = 0x00008005 + GL_FUNC_ADD* = 0x00008006 + GL_MIN* = 0x00008007 + GL_MAX* = 0x00008008 + constGL_BLEND_EQUATION* = 0x00008009 + GL_FUNC_SUBTRACT* = 0x0000800A + GL_FUNC_REVERSE_SUBTRACT* = 0x0000800B + GL_CONVOLUTION_1D* = 0x00008010 + GL_CONVOLUTION_2D* = 0x00008011 + GL_SEPARABLE_2D* = 0x00008012 + GL_CONVOLUTION_BORDER_MODE* = 0x00008013 + GL_CONVOLUTION_FILTER_SCALE* = 0x00008014 + GL_CONVOLUTION_FILTER_BIAS* = 0x00008015 + GL_REDUCE* = 0x00008016 + GL_CONVOLUTION_FORMAT* = 0x00008017 + GL_CONVOLUTION_WIDTH* = 0x00008018 + GL_CONVOLUTION_HEIGHT* = 0x00008019 + GL_MAX_CONVOLUTION_WIDTH* = 0x0000801A + GL_MAX_CONVOLUTION_HEIGHT* = 0x0000801B + GL_POST_CONVOLUTION_RED_SCALE* = 0x0000801C + GL_POST_CONVOLUTION_GREEN_SCALE* = 0x0000801D + GL_POST_CONVOLUTION_BLUE_SCALE* = 0x0000801E + GL_POST_CONVOLUTION_ALPHA_SCALE* = 0x0000801F + GL_POST_CONVOLUTION_RED_BIAS* = 0x00008020 + GL_POST_CONVOLUTION_GREEN_BIAS* = 0x00008021 + GL_POST_CONVOLUTION_BLUE_BIAS* = 0x00008022 + GL_POST_CONVOLUTION_ALPHA_BIAS* = 0x00008023 + constGL_HISTOGRAM* = 0x00008024 + GL_PROXY_HISTOGRAM* = 0x00008025 + GL_HISTOGRAM_WIDTH* = 0x00008026 + GL_HISTOGRAM_FORMAT* = 0x00008027 + GL_HISTOGRAM_RED_SIZE* = 0x00008028 + GL_HISTOGRAM_GREEN_SIZE* = 0x00008029 + GL_HISTOGRAM_BLUE_SIZE* = 0x0000802A + GL_HISTOGRAM_ALPHA_SIZE* = 0x0000802B + GL_HISTOGRAM_LUMINANCE_SIZE* = 0x0000802C + GL_HISTOGRAM_SINK* = 0x0000802D + constGL_MINMAX* = 0x0000802E + GL_MINMAX_FORMAT* = 0x0000802F + GL_MINMAX_SINK* = 0x00008030 + GL_TABLE_TOO_LARGE* = 0x00008031 + GL_COLOR_MATRIX* = 0x000080B1 + GL_COLOR_MATRIX_STACK_DEPTH* = 0x000080B2 + GL_MAX_COLOR_MATRIX_STACK_DEPTH* = 0x000080B3 + GL_POST_COLOR_MATRIX_RED_SCALE* = 0x000080B4 + GL_POST_COLOR_MATRIX_GREEN_SCALE* = 0x000080B5 + GL_POST_COLOR_MATRIX_BLUE_SCALE* = 0x000080B6 + GL_POST_COLOR_MATRIX_ALPHA_SCALE* = 0x000080B7 + GL_POST_COLOR_MATRIX_RED_BIAS* = 0x000080B8 + GL_POST_COLOR_MATRIX_GREEN_BIAS* = 0x000080B9 + GL_POST_COLOR_MATRIX_BLUE_BIAS* = 0x000080BA + GL_POST_COLOR_MATIX_ALPHA_BIAS* = 0x000080BB + constGL_COLOR_TABLE* = 0x000080D0 + GL_POST_CONVOLUTION_COLOR_TABLE* = 0x000080D1 + GL_POST_COLOR_MATRIX_COLOR_TABLE* = 0x000080D2 + GL_PROXY_COLOR_TABLE* = 0x000080D3 + GL_PROXY_POST_CONVOLUTION_COLOR_TABLE* = 0x000080D4 + GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE* = 0x000080D5 + GL_COLOR_TABLE_SCALE* = 0x000080D6 + GL_COLOR_TABLE_BIAS* = 0x000080D7 + GL_COLOR_TABLE_FORMAT* = 0x000080D8 + GL_COLOR_TABLE_WIDTH* = 0x000080D9 + GL_COLOR_TABLE_RED_SIZE* = 0x000080DA + GL_COLOR_TABLE_GREEN_SIZE* = 0x000080DB + GL_COLOR_TABLE_BLUE_SIZE* = 0x000080DC + GL_COLOR_TABLE_ALPHA_SIZE* = 0x000080DD + GL_COLOR_TABLE_LUMINANCE_SIZE* = 0x000080DE + GL_COLOR_TABLE_INTENSITY_SIZE* = 0x000080DF + GL_IGNORE_BORDER* = 0x00008150 + GL_CONSTANT_BORDER* = 0x00008151 + GL_WRAP_BORDER* = 0x00008152 + GL_REPLICATE_BORDER* = 0x00008153 + GL_CONVOLUTION_BORDER_COLOR* = 0x00008154 + +proc glActiveTexture*(texture: TGLenum){.dynlib: dllname, + importc: "glActiveTexture".} +proc glClientActiveTexture*(texture: TGLenum){.dynlib: dllname, + importc: "glClientActiveTexture".} +proc glMultiTexCoord1d*(target: TGLenum, s: TGLdouble){.dynlib: dllname, + importc: "glMultiTexCoord1d".} +proc glMultiTexCoord1dv*(target: TGLenum, v: PGLdouble){.dynlib: dllname, + importc: "glMultiTexCoord1dv".} +proc glMultiTexCoord1f*(target: TGLenum, s: TGLfloat){.dynlib: dllname, + importc: "glMultiTexCoord1f".} +proc glMultiTexCoord1fv*(target: TGLenum, v: PGLfloat){.dynlib: dllname, + importc: "glMultiTexCoord1fv".} +proc glMultiTexCoord1i*(target: TGLenum, s: TGLint){.dynlib: dllname, + importc: "glMultiTexCoord1i".} +proc glMultiTexCoord1iv*(target: TGLenum, v: PGLint){.dynlib: dllname, + importc: "glMultiTexCoord1iv".} +proc glMultiTexCoord1s*(target: TGLenum, s: TGLshort){.dynlib: dllname, + importc: "glMultiTexCoord1s".} +proc glMultiTexCoord1sv*(target: TGLenum, v: PGLshort){.dynlib: dllname, + importc: "glMultiTexCoord1sv".} +proc glMultiTexCoord2d*(target: TGLenum, s: TGLdouble, t: TGLdouble){. + dynlib: dllname, importc: "glMultiTexCoord2d".} +proc glMultiTexCoord2dv*(target: TGLenum, v: PGLdouble){.dynlib: dllname, + importc: "glMultiTexCoord2dv".} +proc glMultiTexCoord2f*(target: TGLenum, s: TGLfloat, t: TGLfloat){. + dynlib: dllname, importc: "glMultiTexCoord2f".} +proc glMultiTexCoord2fv*(target: TGLenum, v: PGLfloat){.dynlib: dllname, + importc: "glMultiTexCoord2fv".} +proc glMultiTexCoord2i*(target: TGLenum, s: TGLint, t: TGLint){.dynlib: dllname, + importc: "glMultiTexCoord2i".} +proc glMultiTexCoord2iv*(target: TGLenum, v: PGLint){.dynlib: dllname, + importc: "glMultiTexCoord2iv".} +proc glMultiTexCoord2s*(target: TGLenum, s: TGLshort, t: TGLshort){. + dynlib: dllname, importc: "glMultiTexCoord2s".} +proc glMultiTexCoord2sv*(target: TGLenum, v: PGLshort){.dynlib: dllname, + importc: "glMultiTexCoord2sv".} +proc glMultiTexCoord3d*(target: TGLenum, s: TGLdouble, t: TGLdouble, + r: TGLdouble){.dynlib: dllname, + importc: "glMultiTexCoord3d".} +proc glMultiTexCoord3dv*(target: TGLenum, v: PGLdouble){.dynlib: dllname, + importc: "glMultiTexCoord3dv".} +proc glMultiTexCoord3f*(target: TGLenum, s: TGLfloat, t: TGLfloat, r: TGLfloat){. + dynlib: dllname, importc: "glMultiTexCoord3f".} +proc glMultiTexCoord3fv*(target: TGLenum, v: PGLfloat){.dynlib: dllname, + importc: "glMultiTexCoord3fv".} +proc glMultiTexCoord3i*(target: TGLenum, s: TGLint, t: TGLint, r: TGLint){. + dynlib: dllname, importc: "glMultiTexCoord3i".} +proc glMultiTexCoord3iv*(target: TGLenum, v: PGLint){.dynlib: dllname, + importc: "glMultiTexCoord3iv".} +proc glMultiTexCoord3s*(target: TGLenum, s: TGLshort, t: TGLshort, r: TGLshort){. + dynlib: dllname, importc: "glMultiTexCoord3s".} +proc glMultiTexCoord3sv*(target: TGLenum, v: PGLshort){.dynlib: dllname, + importc: "glMultiTexCoord3sv".} +proc glMultiTexCoord4d*(target: TGLenum, s: TGLdouble, t: TGLdouble, + r: TGLdouble, q: TGLdouble){.dynlib: dllname, + importc: "glMultiTexCoord4d".} +proc glMultiTexCoord4dv*(target: TGLenum, v: PGLdouble){.dynlib: dllname, + importc: "glMultiTexCoord4dv".} +proc glMultiTexCoord4f*(target: TGLenum, s: TGLfloat, t: TGLfloat, r: TGLfloat, + q: TGLfloat){.dynlib: dllname, + importc: "glMultiTexCoord4f".} +proc glMultiTexCoord4fv*(target: TGLenum, v: PGLfloat){.dynlib: dllname, + importc: "glMultiTexCoord4fv".} +proc glMultiTexCoord4i*(target: TGLenum, s: TGLint, t: TGLint, r: TGLint, + q: TGLint){.dynlib: dllname, + importc: "glMultiTexCoord4i".} +proc glMultiTexCoord4iv*(target: TGLenum, v: PGLint){.dynlib: dllname, + importc: "glMultiTexCoord4iv".} +proc glMultiTexCoord4s*(target: TGLenum, s: TGLshort, t: TGLshort, r: TGLshort, + q: TGLshort){.dynlib: dllname, + importc: "glMultiTexCoord4s".} +proc glMultiTexCoord4sv*(target: TGLenum, v: PGLshort){.dynlib: dllname, + importc: "glMultiTexCoord4sv".} +proc glLoadTransposeMatrixf*(m: PGLfloat){.dynlib: dllname, + importc: "glLoadTransposeMatrixf".} +proc glLoadTransposeMatrixd*(m: PGLdouble){.dynlib: dllname, + importc: "glLoadTransposeMatrixd".} +proc glMultTransposeMatrixf*(m: PGLfloat){.dynlib: dllname, + importc: "glMultTransposeMatrixf".} +proc glMultTransposeMatrixd*(m: PGLdouble){.dynlib: dllname, + importc: "glMultTransposeMatrixd".} +proc glSampleCoverage*(value: TGLclampf, invert: TGLboolean){.dynlib: dllname, + importc: "glSampleCoverage".} +proc glCompressedTexImage3D*(target: TGLenum, level: TGLint, + internalformat: TGLenum, width: TGLsizei, + height: TGLsizei, depth: TGLsizei, border: TGLint, + imageSize: TGLsizei, data: PGLvoid){. + dynlib: dllname, importc: "glCompressedTexImage3D".} +proc glCompressedTexImage2D*(target: TGLenum, level: TGLint, + internalformat: TGLenum, width: TGLsizei, + height: TGLsizei, border: TGLint, + imageSize: TGLsizei, data: PGLvoid){. + dynlib: dllname, importc: "glCompressedTexImage2D".} +proc glCompressedTexImage1D*(target: TGLenum, level: TGLint, + internalformat: TGLenum, width: TGLsizei, + border: TGLint, imageSize: TGLsizei, data: PGLvoid){. + dynlib: dllname, importc: "glCompressedTexImage1D".} +proc glCompressedTexSubImage3D*(target: TGLenum, level: TGLint, xoffset: TGLint, + yoffset: TGLint, zoffset: TGLint, + width: TGLsizei, height: TGLsizei, + depth: TGLsizei, format: TGLenum, + imageSize: TGLsizei, data: PGLvoid){. + dynlib: dllname, importc: "glCompressedTexSubImage3D".} +proc glCompressedTexSubImage2D*(target: TGLenum, level: TGLint, xoffset: TGLint, + yoffset: TGLint, width: TGLsizei, + height: TGLsizei, format: TGLenum, + imageSize: TGLsizei, data: PGLvoid){. + dynlib: dllname, importc: "glCompressedTexSubImage2D".} +proc glCompressedTexSubImage1D*(target: TGLenum, level: TGLint, xoffset: TGLint, + width: TGLsizei, format: TGLenum, + imageSize: TGLsizei, data: PGLvoid){. + dynlib: dllname, importc: "glCompressedTexSubImage1D".} +proc glGetCompressedTexImage*(target: TGLenum, level: TGLint, img: PGLvoid){. + dynlib: dllname, importc: "glGetCompressedTexImage".} + #***** GL_version_1_3 *****// +const + GL_TEXTURE0* = 0x000084C0 + GL_TEXTURE1* = 0x000084C1 + GL_TEXTURE2* = 0x000084C2 + GL_TEXTURE3* = 0x000084C3 + GL_TEXTURE4* = 0x000084C4 + GL_TEXTURE5* = 0x000084C5 + GL_TEXTURE6* = 0x000084C6 + GL_TEXTURE7* = 0x000084C7 + GL_TEXTURE8* = 0x000084C8 + GL_TEXTURE9* = 0x000084C9 + GL_TEXTURE10* = 0x000084CA + GL_TEXTURE11* = 0x000084CB + GL_TEXTURE12* = 0x000084CC + GL_TEXTURE13* = 0x000084CD + GL_TEXTURE14* = 0x000084CE + GL_TEXTURE15* = 0x000084CF + GL_TEXTURE16* = 0x000084D0 + GL_TEXTURE17* = 0x000084D1 + GL_TEXTURE18* = 0x000084D2 + GL_TEXTURE19* = 0x000084D3 + GL_TEXTURE20* = 0x000084D4 + GL_TEXTURE21* = 0x000084D5 + GL_TEXTURE22* = 0x000084D6 + GL_TEXTURE23* = 0x000084D7 + GL_TEXTURE24* = 0x000084D8 + GL_TEXTURE25* = 0x000084D9 + GL_TEXTURE26* = 0x000084DA + GL_TEXTURE27* = 0x000084DB + GL_TEXTURE28* = 0x000084DC + GL_TEXTURE29* = 0x000084DD + GL_TEXTURE30* = 0x000084DE + GL_TEXTURE31* = 0x000084DF + constGL_ACTIVE_TEXTURE* = 0x000084E0 + constGL_CLIENT_ACTIVE_TEXTURE* = 0x000084E1 + GL_MAX_TEXTURE_UNITS* = 0x000084E2 + GL_TRANSPOSE_MODELVIEW_MATRIX* = 0x000084E3 + GL_TRANSPOSE_PROJECTION_MATRIX* = 0x000084E4 + GL_TRANSPOSE_TEXTURE_MATRIX* = 0x000084E5 + GL_TRANSPOSE_COLOR_MATRIX* = 0x000084E6 + GL_MULTISAMPLE* = 0x0000809D + GL_SAMPLE_ALPHA_TO_COVERAGE* = 0x0000809E + GL_SAMPLE_ALPHA_TO_ONE* = 0x0000809F + constGL_SAMPLE_COVERAGE* = 0x000080A0 + GL_SAMPLE_BUFFERS* = 0x000080A8 + GL_SAMPLES* = 0x000080A9 + GL_SAMPLE_COVERAGE_VALUE* = 0x000080AA + GL_SAMPLE_COVERAGE_INVERT* = 0x000080AB + GL_MULTISAMPLE_BIT* = 0x20000000 + GL_NORMAL_MAP* = 0x00008511 + GL_REFLECTION_MAP* = 0x00008512 + GL_TEXTURE_CUBE_MAP* = 0x00008513 + GL_TEXTURE_BINDING_CUBE_MAP* = 0x00008514 + GL_TEXTURE_CUBE_MAP_POSITIVE_X* = 0x00008515 + GL_TEXTURE_CUBE_MAP_NEGATIVE_X* = 0x00008516 + GL_TEXTURE_CUBE_MAP_POSITIVE_Y* = 0x00008517 + GL_TEXTURE_CUBE_MAP_NEGATIVE_Y* = 0x00008518 + GL_TEXTURE_CUBE_MAP_POSITIVE_Z* = 0x00008519 + GL_TEXTURE_CUBE_MAP_NEGATIVE_Z* = 0x0000851A + GL_PROXY_TEXTURE_CUBE_MAP* = 0x0000851B + GL_MAX_CUBE_MAP_TEXTURE_SIZE* = 0x0000851C + GL_COMPRESSED_ALPHA* = 0x000084E9 + GL_COMPRESSED_LUMINANCE* = 0x000084EA + GL_COMPRESSED_LUMINANCE_ALPHA* = 0x000084EB + GL_COMPRESSED_INTENSITY* = 0x000084EC + GL_COMPRESSED_RGB* = 0x000084ED + GL_COMPRESSED_RGBA* = 0x000084EE + GL_TEXTURE_COMPRESSION_HINT* = 0x000084EF + GL_TEXTURE_COMPRESSED_IMAGE_SIZE* = 0x000086A0 + GL_TEXTURE_COMPRESSED* = 0x000086A1 + GL_NUM_COMPRESSED_TEXTURE_FORMATS* = 0x000086A2 + GL_COMPRESSED_TEXTURE_FORMATS* = 0x000086A3 + GL_CLAMP_TO_BORDER* = 0x0000812D + GL_CLAMP_TO_BORDER_SGIS* = 0x0000812D + GL_COMBINE* = 0x00008570 + GL_COMBINE_RGB* = 0x00008571 + GL_COMBINE_ALPHA* = 0x00008572 + GL_SOURCE0_RGB* = 0x00008580 + GL_SOURCE1_RGB* = 0x00008581 + GL_SOURCE2_RGB* = 0x00008582 + GL_SOURCE0_ALPHA* = 0x00008588 + GL_SOURCE1_ALPHA* = 0x00008589 + GL_SOURCE2_ALPHA* = 0x0000858A + GL_OPERAND0_RGB* = 0x00008590 + GL_OPERAND1_RGB* = 0x00008591 + GL_OPERAND2_RGB* = 0x00008592 + GL_OPERAND0_ALPHA* = 0x00008598 + GL_OPERAND1_ALPHA* = 0x00008599 + GL_OPERAND2_ALPHA* = 0x0000859A + GL_RGB_SCALE* = 0x00008573 + GL_ADD_SIGNED* = 0x00008574 + GL_INTERPOLATE* = 0x00008575 + GL_SUBTRACT* = 0x000084E7 + GL_CONSTANT* = 0x00008576 + GL_PRIMARY_COLOR* = 0x00008577 + GL_PREVIOUS* = 0x00008578 + GL_DOT3_RGB* = 0x000086AE + GL_DOT3_RGBA* = 0x000086AF + +const + GL_TEXTURE0_ARB* = 0x000084C0 + GL_TEXTURE1_ARB* = 0x000084C1 + GL_TEXTURE2_ARB* = 0x000084C2 + GL_TEXTURE3_ARB* = 0x000084C3 + GL_TEXTURE4_ARB* = 0x000084C4 + GL_TEXTURE5_ARB* = 0x000084C5 + GL_TEXTURE6_ARB* = 0x000084C6 + GL_TEXTURE7_ARB* = 0x000084C7 + GL_TEXTURE8_ARB* = 0x000084C8 + GL_TEXTURE9_ARB* = 0x000084C9 + GL_TEXTURE10_ARB* = 0x000084CA + GL_TEXTURE11_ARB* = 0x000084CB + GL_TEXTURE12_ARB* = 0x000084CC + GL_TEXTURE13_ARB* = 0x000084CD + GL_TEXTURE14_ARB* = 0x000084CE + GL_TEXTURE15_ARB* = 0x000084CF + GL_TEXTURE16_ARB* = 0x000084D0 + GL_TEXTURE17_ARB* = 0x000084D1 + GL_TEXTURE18_ARB* = 0x000084D2 + GL_TEXTURE19_ARB* = 0x000084D3 + GL_TEXTURE20_ARB* = 0x000084D4 + GL_TEXTURE21_ARB* = 0x000084D5 + GL_TEXTURE22_ARB* = 0x000084D6 + GL_TEXTURE23_ARB* = 0x000084D7 + GL_TEXTURE24_ARB* = 0x000084D8 + GL_TEXTURE25_ARB* = 0x000084D9 + GL_TEXTURE26_ARB* = 0x000084DA + GL_TEXTURE27_ARB* = 0x000084DB + GL_TEXTURE28_ARB* = 0x000084DC + GL_TEXTURE29_ARB* = 0x000084DD + GL_TEXTURE30_ARB* = 0x000084DE + GL_TEXTURE31_ARB* = 0x000084DF + constGL_ACTIVE_TEXTURE_ARB* = 0x000084E0 + constGL_CLIENT_ACTIVE_TEXTURE_ARB* = 0x000084E1 + GL_MAX_TEXTURE_UNITS_ARB* = 0x000084E2 + #***** GL_ARB_transpose_matrix *****// + +const + GL_TRANSPOSE_MODELVIEW_MATRIX_ARB* = 0x000084E3 + GL_TRANSPOSE_PROJECTION_MATRIX_ARB* = 0x000084E4 + GL_TRANSPOSE_TEXTURE_MATRIX_ARB* = 0x000084E5 + GL_TRANSPOSE_COLOR_MATRIX_ARB* = 0x000084E6 + +proc glLoadTransposeMatrixfARB*(m: PGLfloat){.dynlib: dllname, + importc: "glLoadTransposeMatrixfARB".} +proc glLoadTransposeMatrixdARB*(m: PGLdouble){.dynlib: dllname, + importc: "glLoadTransposeMatrixdARB".} +proc glMultTransposeMatrixfARB*(m: PGLfloat){.dynlib: dllname, + importc: "glMultTransposeMatrixfARB".} +proc glMultTransposeMatrixdARB*(m: PGLdouble){.dynlib: dllname, + importc: "glMultTransposeMatrixdARB".} +const + WGL_SAMPLE_BUFFERS_ARB* = 0x00002041 + WGL_SAMPLES_ARB* = 0x00002042 + GL_MULTISAMPLE_ARB* = 0x0000809D + GL_SAMPLE_ALPHA_TO_COVERAGE_ARB* = 0x0000809E + GL_SAMPLE_ALPHA_TO_ONE_ARB* = 0x0000809F + constGL_SAMPLE_COVERAGE_ARB* = 0x000080A0 + GL_MULTISAMPLE_BIT_ARB* = 0x20000000 + GL_SAMPLE_BUFFERS_ARB* = 0x000080A8 + GL_SAMPLES_ARB* = 0x000080A9 + GL_SAMPLE_COVERAGE_VALUE_ARB* = 0x000080AA + GL_SAMPLE_COVERAGE_INVERT_ARB* = 0x000080AB + +const + GL_NORMAL_MAP_ARB* = 0x00008511 + GL_REFLECTION_MAP_ARB* = 0x00008512 + GL_TEXTURE_CUBE_MAP_ARB* = 0x00008513 + GL_TEXTURE_BINDING_CUBE_MAP_ARB* = 0x00008514 + GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB* = 0x00008515 + GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB* = 0x00008516 + GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB* = 0x00008517 + GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB* = 0x00008518 + GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB* = 0x00008519 + GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB* = 0x0000851A + GL_PROXY_TEXTURE_CUBE_MAP_ARB* = 0x0000851B + GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB* = 0x0000851C + +const + GL_DEPTH_COMPONENT16_ARB* = 0x000081A5 + GL_DEPTH_COMPONENT24_ARB* = 0x000081A6 + GL_DEPTH_COMPONENT32_ARB* = 0x000081A7 + GL_TEXTURE_DEPTH_SIZE_ARB* = 0x0000884A + GL_DEPTH_TEXTURE_MODE_ARB* = 0x0000884B + #***** GL_ARB_point_parameters *****// + +const + GL_POINT_SIZE_MIN_ARB* = 0x00008126 + GL_POINT_SIZE_MAX_ARB* = 0x00008127 + GL_POINT_FADE_THRESHOLD_SIZE_ARB* = 0x00008128 + GL_POINT_DISTANCE_ATTENUATION_ARB* = 0x00008129 + +proc glPointParameterfARB*(pname: TGLenum, param: TGLfloat){.dynlib: dllname, + importc: "glPointParameterfARB".} +proc glPointParameterfvARB*(pname: TGLenum, params: PGLfloat){.dynlib: dllname, + importc: "glPointParameterfvARB".} +const + GL_TEXTURE_COMPARE_MODE_ARB* = 0x0000884C + GL_TEXTURE_COMPARE_FUNC_ARB* = 0x0000884D + GL_COMPARE_R_TO_TEXTURE_ARB* = 0x0000884E + +const + GL_TEXTURE_COMPARE_FAIL_VALUE_ARB* = 0x000080BF + GL_CLAMP_TO_BORDER_ARB* = 0x0000812D + +const + GL_COMPRESSED_ALPHA_ARB* = 0x000084E9 + GL_COMPRESSED_LUMINANCE_ARB* = 0x000084EA + GL_COMPRESSED_LUMINANCE_ALPHA_ARB* = 0x000084EB + GL_COMPRESSED_INTENSITY_ARB* = 0x000084EC + GL_COMPRESSED_RGB_ARB* = 0x000084ED + GL_COMPRESSED_RGBA_ARB* = 0x000084EE + GL_TEXTURE_COMPRESSION_HINT_ARB* = 0x000084EF + GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB* = 0x000086A0 + GL_TEXTURE_COMPRESSED_ARB* = 0x000086A1 + GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB* = 0x000086A2 + GL_COMPRESSED_TEXTURE_FORMATS_ARB* = 0x000086A3 + +proc glCompressedTexImage3DARB*(target: TGLenum, level: TGLint, + internalformat: TGLenum, width: TGLsizei, + height: TGLsizei, depth: TGLsizei, + border: TGLint, imageSize: TGLsizei, + data: PGLvoid){.dynlib: dllname, + importc: "glCompressedTexImage3DARB".} +proc glCompressedTexImage2DARB*(target: TGLenum, level: TGLint, + internalformat: TGLenum, width: TGLsizei, + height: TGLsizei, border: TGLint, + imageSize: TGLsizei, data: PGLvoid){. + dynlib: dllname, importc: "glCompressedTexImage2DARB".} +proc glCompressedTexImage1DARB*(target: TGLenum, level: TGLint, + internalformat: TGLenum, width: TGLsizei, + border: TGLint, imageSize: TGLsizei, + data: PGLvoid){.dynlib: dllname, + importc: "glCompressedTexImage1DARB".} +proc glCompressedTexSubImage3DARB*(target: TGLenum, level: TGLint, + xoffset: TGLint, yoffset: TGLint, + zoffset: TGLint, width: TGLsizei, + height: TGLsizei, depth: TGLsizei, + format: TGLenum, imageSize: TGLsizei, + data: PGLvoid){.dynlib: dllname, + importc: "glCompressedTexSubImage3DARB".} +proc glCompressedTexSubImage2DARB*(target: TGLenum, level: TGLint, + xoffset: TGLint, yoffset: TGLint, + width: TGLsizei, height: TGLsizei, + format: TGLenum, imageSize: TGLsizei, + data: PGLvoid){.dynlib: dllname, + importc: "glCompressedTexSubImage2DARB".} +proc glCompressedTexSubImage1DARB*(target: TGLenum, level: TGLint, + xoffset: TGLint, width: TGLsizei, + format: TGLenum, imageSize: TGLsizei, + data: PGLvoid){.dynlib: dllname, + importc: "glCompressedTexSubImage1DARB".} +proc glGetCompressedTexImageARB*(target: TGLenum, lod: TGLint, img: PGLvoid){. + dynlib: dllname, importc: "glGetCompressedTexImageARB".} + #***** GL_ARB_texture_env_combine *****// +const + GL_COMBINE_ARB* = 0x00008570 + GL_COMBINE_RGB_ARB* = 0x00008571 + GL_COMBINE_ALPHA_ARB* = 0x00008572 + GL_SOURCE0_RGB_ARB* = 0x00008580 + GL_SOURCE1_RGB_ARB* = 0x00008581 + GL_SOURCE2_RGB_ARB* = 0x00008582 + GL_SOURCE0_ALPHA_ARB* = 0x00008588 + GL_SOURCE1_ALPHA_ARB* = 0x00008589 + GL_SOURCE2_ALPHA_ARB* = 0x0000858A + GL_OPERAND0_RGB_ARB* = 0x00008590 + GL_OPERAND1_RGB_ARB* = 0x00008591 + GL_OPERAND2_RGB_ARB* = 0x00008592 + GL_OPERAND0_ALPHA_ARB* = 0x00008598 + GL_OPERAND1_ALPHA_ARB* = 0x00008599 + GL_OPERAND2_ALPHA_ARB* = 0x0000859A + GL_RGB_SCALE_ARB* = 0x00008573 + GL_ADD_SIGNED_ARB* = 0x00008574 + GL_INTERPOLATE_ARB* = 0x00008575 + GL_SUBTRACT_ARB* = 0x000084E7 + GL_CONSTANT_ARB* = 0x00008576 + GL_PRIMARY_COLOR_ARB* = 0x00008577 + GL_PREVIOUS_ARB* = 0x00008578 + #***** GL_ARB_texture_env_crossbar *****// + #***** GL_ARB_texture_env_dot3 *****// + +const + GL_DOT3_RGB_ARB* = 0x000086AE + GL_DOT3_RGBA_ARB* = 0x000086AF + #***** GL_ARB_texture_mirrored_repeat *****// + +const + GL_MIRRORED_REPEAT_ARB* = 0x00008370 + #***** GL_ARB_vertex_blend *****// + +const + GL_MAX_VERTEX_UNITS_ARB* = 0x000086A4 + GL_ACTIVE_VERTEX_UNITS_ARB* = 0x000086A5 + GL_WEIGHT_SUM_UNITY_ARB* = 0x000086A6 + constGL_VERTEX_BLEND_ARB* = 0x000086A7 + GL_MODELVIEW0_ARB* = 0x00001700 + GL_MODELVIEW1_ARB* = 0x0000850A + GL_MODELVIEW2_ARB* = 0x00008722 + GL_MODELVIEW3_ARB* = 0x00008723 + GL_MODELVIEW4_ARB* = 0x00008724 + GL_MODELVIEW5_ARB* = 0x00008725 + GL_MODELVIEW6_ARB* = 0x00008726 + GL_MODELVIEW7_ARB* = 0x00008727 + GL_MODELVIEW8_ARB* = 0x00008728 + GL_MODELVIEW9_ARB* = 0x00008729 + GL_MODELVIEW10_ARB* = 0x0000872A + GL_MODELVIEW11_ARB* = 0x0000872B + GL_MODELVIEW12_ARB* = 0x0000872C + GL_MODELVIEW13_ARB* = 0x0000872D + GL_MODELVIEW14_ARB* = 0x0000872E + GL_MODELVIEW15_ARB* = 0x0000872F + GL_MODELVIEW16_ARB* = 0x00008730 + GL_MODELVIEW17_ARB* = 0x00008731 + GL_MODELVIEW18_ARB* = 0x00008732 + GL_MODELVIEW19_ARB* = 0x00008733 + GL_MODELVIEW20_ARB* = 0x00008734 + GL_MODELVIEW21_ARB* = 0x00008735 + GL_MODELVIEW22_ARB* = 0x00008736 + GL_MODELVIEW23_ARB* = 0x00008737 + GL_MODELVIEW24_ARB* = 0x00008738 + GL_MODELVIEW25_ARB* = 0x00008739 + GL_MODELVIEW26_ARB* = 0x0000873A + GL_MODELVIEW27_ARB* = 0x0000873B + GL_MODELVIEW28_ARB* = 0x0000873C + GL_MODELVIEW29_ARB* = 0x0000873D + GL_MODELVIEW30_ARB* = 0x0000873E + GL_MODELVIEW31_ARB* = 0x0000873F + GL_CURRENT_WEIGHT_ARB* = 0x000086A8 + GL_WEIGHT_ARRAY_TYPE_ARB* = 0x000086A9 + GL_WEIGHT_ARRAY_STRIDE_ARB* = 0x000086AA + GL_WEIGHT_ARRAY_SIZE_ARB* = 0x000086AB + GL_WEIGHT_ARRAY_POINTER_ARB* = 0x000086AC + GL_WEIGHT_ARRAY_ARB* = 0x000086AD + +const + GL_VERTEX_PROGRAM_ARB* = 0x00008620 + GL_VERTEX_PROGRAM_POINT_SIZE_ARB* = 0x00008642 + GL_VERTEX_PROGRAM_TWO_SIDE_ARB* = 0x00008643 + GL_COLOR_SUM_ARB* = 0x00008458 + GL_PROGRAM_FORMAT_ASCII_ARB* = 0x00008875 + GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB* = 0x00008622 + GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB* = 0x00008623 + GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB* = 0x00008624 + GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB* = 0x00008625 + GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB* = 0x0000886A + GL_CURRENT_VERTEX_ATTRIB_ARB* = 0x00008626 + GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB* = 0x00008645 + GL_PROGRAM_LENGTH_ARB* = 0x00008627 + GL_PROGRAM_FORMAT_ARB* = 0x00008876 + GL_PROGRAM_BINDING_ARB* = 0x00008677 + GL_PROGRAM_INSTRUCTIONS_ARB* = 0x000088A0 + GL_MAX_PROGRAM_INSTRUCTIONS_ARB* = 0x000088A1 + GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB* = 0x000088A2 + GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB* = 0x000088A3 + GL_PROGRAM_TEMPORARIES_ARB* = 0x000088A4 + GL_MAX_PROGRAM_TEMPORARIES_ARB* = 0x000088A5 + GL_PROGRAM_NATIVE_TEMPORARIES_ARB* = 0x000088A6 + GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB* = 0x000088A7 + GL_PROGRAM_PARAMETERS_ARB* = 0x000088A8 + GL_MAX_PROGRAM_PARAMETERS_ARB* = 0x000088A9 + GL_PROGRAM_NATIVE_PARAMETERS_ARB* = 0x000088AA + GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB* = 0x000088AB + GL_PROGRAM_ATTRIBS_ARB* = 0x000088AC + GL_MAX_PROGRAM_ATTRIBS_ARB* = 0x000088AD + GL_PROGRAM_NATIVE_ATTRIBS_ARB* = 0x000088AE + GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB* = 0x000088AF + GL_PROGRAM_ADDRESS_REGISTERS_ARB* = 0x000088B0 + GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB* = 0x000088B1 + GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB* = 0x000088B2 + GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB* = 0x000088B3 + GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB* = 0x000088B4 + GL_MAX_PROGRAM_ENV_PARAMETERS_ARB* = 0x000088B5 + GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB* = 0x000088B6 + constGL_PROGRAM_STRING_ARB* = 0x00008628 + GL_PROGRAM_ERROR_POSITION_ARB* = 0x0000864B + GL_CURRENT_MATRIX_ARB* = 0x00008641 + GL_TRANSPOSE_CURRENT_MATRIX_ARB* = 0x000088B7 + GL_CURRENT_MATRIX_STACK_DEPTH_ARB* = 0x00008640 + GL_MAX_VERTEX_ATTRIBS_ARB* = 0x00008869 + GL_MAX_PROGRAM_MATRICES_ARB* = 0x0000862F + GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB* = 0x0000862E + GL_PROGRAM_ERROR_STRING_ARB* = 0x00008874 + GL_MATRIX0_ARB* = 0x000088C0 + GL_MATRIX1_ARB* = 0x000088C1 + GL_MATRIX2_ARB* = 0x000088C2 + GL_MATRIX3_ARB* = 0x000088C3 + GL_MATRIX4_ARB* = 0x000088C4 + GL_MATRIX5_ARB* = 0x000088C5 + GL_MATRIX6_ARB* = 0x000088C6 + GL_MATRIX7_ARB* = 0x000088C7 + GL_MATRIX8_ARB* = 0x000088C8 + GL_MATRIX9_ARB* = 0x000088C9 + GL_MATRIX10_ARB* = 0x000088CA + GL_MATRIX11_ARB* = 0x000088CB + GL_MATRIX12_ARB* = 0x000088CC + GL_MATRIX13_ARB* = 0x000088CD + GL_MATRIX14_ARB* = 0x000088CE + GL_MATRIX15_ARB* = 0x000088CF + GL_MATRIX16_ARB* = 0x000088D0 + GL_MATRIX17_ARB* = 0x000088D1 + GL_MATRIX18_ARB* = 0x000088D2 + GL_MATRIX19_ARB* = 0x000088D3 + GL_MATRIX20_ARB* = 0x000088D4 + GL_MATRIX21_ARB* = 0x000088D5 + GL_MATRIX22_ARB* = 0x000088D6 + GL_MATRIX23_ARB* = 0x000088D7 + GL_MATRIX24_ARB* = 0x000088D8 + GL_MATRIX25_ARB* = 0x000088D9 + GL_MATRIX26_ARB* = 0x000088DA + GL_MATRIX27_ARB* = 0x000088DB + GL_MATRIX28_ARB* = 0x000088DC + GL_MATRIX29_ARB* = 0x000088DD + GL_MATRIX30_ARB* = 0x000088DE + GL_MATRIX31_ARB* = 0x000088DF + +const + GL_422_EXT* = 0x000080CC + GL_422_REV_EXT* = 0x000080CD + GL_422_AVERAGE_EXT* = 0x000080CE + GL_422_REV_AVERAGE_EXT* = 0x000080CF + #***** GL_EXT_abgr *****// + +const + GL_ABGR_EXT* = 0x00008000 + #***** GL_EXT_bgra *****// + +const + GL_BGR_EXT* = 0x000080E0 + GL_BGRA_EXT* = 0x000080E1 + #***** GL_EXT_blend_color *****// + +const + GL_CONSTANT_COLOR_EXT* = 0x00008001 + GL_ONE_MINUS_CONSTANT_COLOR_EXT* = 0x00008002 + GL_CONSTANT_ALPHA_EXT* = 0x00008003 + GL_ONE_MINUS_CONSTANT_ALPHA_EXT* = 0x00008004 + constGL_BLEND_COLOR_EXT* = 0x00008005 + +proc glBlendColorEXT*(red: TGLclampf, green: TGLclampf, blue: TGLclampf, + alpha: TGLclampf){.dynlib: dllname, + importc: "glBlendColorEXT".} + #***** GL_EXT_blend_func_separate *****// +const + GL_BLEND_DST_RGB_EXT* = 0x000080C8 + GL_BLEND_SRC_RGB_EXT* = 0x000080C9 + GL_BLEND_DST_ALPHA_EXT* = 0x000080CA + GL_BLEND_SRC_ALPHA_EXT* = 0x000080CB + +proc glBlendFuncSeparateEXT*(sfactorRGB: TGLenum, dfactorRGB: TGLenum, + sfactorAlpha: TGLenum, dfactorAlpha: TGLenum){. + dynlib: dllname, importc: "glBlendFuncSeparateEXT".} + #***** GL_EXT_blend_logic_op *****// + #***** GL_EXT_blend_minmax *****// +const + GL_FUNC_ADD_EXT* = 0x00008006 + GL_MIN_EXT* = 0x00008007 + GL_MAX_EXT* = 0x00008008 + constGL_BLEND_EQUATION_EXT* = 0x00008009 + +proc glBlendEquationEXT*(mode: TGLenum){.dynlib: dllname, + importc: "glBlendEquationEXT".} + #***** GL_EXT_blend_subtract *****// +const + GL_FUNC_SUBTRACT_EXT* = 0x0000800A + GL_FUNC_REVERSE_SUBTRACT_EXT* = 0x0000800B + #***** GL_EXT_clip_volume_hint *****// + +const + GL_CLIP_VOLUME_CLIPPING_HINT_EXT* = 0x000080F0 + #***** GL_EXT_color_subtable *****// + +proc glColorSubTableEXT*(target: TGLenum, start: TGLsizei, count: TGLsizei, + format: TGLenum, thetype: TGLenum, data: PGLvoid){. + dynlib: dllname, importc: "glColorSubTableEXT".} +proc glCopyColorSubTableEXT*(target: TGLenum, start: TGLsizei, x: TGLint, + y: TGLint, width: TGLsizei){.dynlib: dllname, + importc: "glCopyColorSubTableEXT".} + #***** GL_EXT_compiled_vertex_array *****// +const + GL_ARRAY_ELEMENT_LOCK_FIRST_EXT* = 0x000081A8 + GL_ARRAY_ELEMENT_LOCK_COUNT_EXT* = 0x000081A9 + +proc glLockArraysEXT*(first: TGLint, count: TGLsizei){.dynlib: dllname, + importc: "glLockArraysEXT".} +proc glUnlockArraysEXT*(){.dynlib: dllname, importc: "glUnlockArraysEXT".} + #***** GL_EXT_convolution *****// +const + GL_CONVOLUTION_1D_EXT* = 0x00008010 + GL_CONVOLUTION_2D_EXT* = 0x00008011 + GL_SEPARABLE_2D_EXT* = 0x00008012 + GL_CONVOLUTION_BORDER_MODE_EXT* = 0x00008013 + GL_CONVOLUTION_FILTER_SCALE_EXT* = 0x00008014 + GL_CONVOLUTION_FILTER_BIAS_EXT* = 0x00008015 + GL_REDUCE_EXT* = 0x00008016 + GL_CONVOLUTION_FORMAT_EXT* = 0x00008017 + GL_CONVOLUTION_WIDTH_EXT* = 0x00008018 + GL_CONVOLUTION_HEIGHT_EXT* = 0x00008019 + GL_MAX_CONVOLUTION_WIDTH_EXT* = 0x0000801A + GL_MAX_CONVOLUTION_HEIGHT_EXT* = 0x0000801B + GL_POST_CONVOLUTION_RED_SCALE_EXT* = 0x0000801C + GL_POST_CONVOLUTION_GREEN_SCALE_EXT* = 0x0000801D + GL_POST_CONVOLUTION_BLUE_SCALE_EXT* = 0x0000801E + GL_POST_CONVOLUTION_ALPHA_SCALE_EXT* = 0x0000801F + GL_POST_CONVOLUTION_RED_BIAS_EXT* = 0x00008020 + GL_POST_CONVOLUTION_GREEN_BIAS_EXT* = 0x00008021 + GL_POST_CONVOLUTION_BLUE_BIAS_EXT* = 0x00008022 + GL_POST_CONVOLUTION_ALPHA_BIAS_EXT* = 0x00008023 + +proc glConvolutionFilter1DEXT*(target: TGLenum, internalformat: TGLenum, + width: TGLsizei, format: TGLenum, + thetype: TGLenum, image: PGLvoid){. + dynlib: dllname, importc: "glConvolutionFilter1DEXT".} +proc glConvolutionFilter2DEXT*(target: TGLenum, internalformat: TGLenum, + width: TGLsizei, height: TGLsizei, + format: TGLenum, thetype: TGLenum, image: PGLvoid){. + dynlib: dllname, importc: "glConvolutionFilter2DEXT".} +proc glCopyConvolutionFilter1DEXT*(target: TGLenum, internalformat: TGLenum, + x: TGLint, y: TGLint, width: TGLsizei){. + dynlib: dllname, importc: "glCopyConvolutionFilter1DEXT".} +proc glCopyConvolutionFilter2DEXT*(target: TGLenum, internalformat: TGLenum, + x: TGLint, y: TGLint, width: TGLsizei, + height: TGLsizei){.dynlib: dllname, + importc: "glCopyConvolutionFilter2DEXT".} +proc glGetConvolutionFilterEXT*(target: TGLenum, format: TGLenum, + thetype: TGLenum, image: PGLvoid){. + dynlib: dllname, importc: "glGetConvolutionFilterEXT".} +proc glSeparableFilter2DEXT*(target: TGLenum, internalformat: TGLenum, + width: TGLsizei, height: TGLsizei, format: TGLenum, + thetype: TGLenum, row: PGLvoid, column: PGLvoid){. + dynlib: dllname, importc: "glSeparableFilter2DEXT".} +proc glGetSeparableFilterEXT*(target: TGLenum, format: TGLenum, + thetype: TGLenum, row: PGLvoid, column: PGLvoid, + span: PGLvoid){.dynlib: dllname, + importc: "glGetSeparableFilterEXT".} +proc glConvolutionParameteriEXT*(target: TGLenum, pname: TGLenum, param: TGLint){. + dynlib: dllname, importc: "glConvolutionParameteriEXT".} +proc glConvolutionParameterivEXT*(target: TGLenum, pname: TGLenum, + params: PGLint){.dynlib: dllname, + importc: "glConvolutionParameterivEXT".} +proc glConvolutionParameterfEXT*(target: TGLenum, pname: TGLenum, + param: TGLfloat){.dynlib: dllname, + importc: "glConvolutionParameterfEXT".} +proc glConvolutionParameterfvEXT*(target: TGLenum, pname: TGLenum, + params: PGLfloat){.dynlib: dllname, + importc: "glConvolutionParameterfvEXT".} +proc glGetConvolutionParameterivEXT*(target: TGLenum, pname: TGLenum, + params: PGLint){.dynlib: dllname, + importc: "glGetConvolutionParameterivEXT".} +proc glGetConvolutionParameterfvEXT*(target: TGLenum, pname: TGLenum, + params: PGLfloat){.dynlib: dllname, + importc: "glGetConvolutionParameterfvEXT".} + #***** GL_EXT_fog_coord *****// +const + GL_FOG_COORDINATE_SOURCE_EXT* = 0x00008450 + GL_FOG_COORDINATE_EXT* = 0x00008451 + GL_FRAGMENT_DEPTH_EXT* = 0x00008452 + GL_CURRENT_FOG_COORDINATE_EXT* = 0x00008453 + GL_FOG_COORDINATE_ARRAY_TYPE_EXT* = 0x00008454 + GL_FOG_COORDINATE_ARRAY_STRIDE_EXT* = 0x00008455 + GL_FOG_COORDINATE_ARRAY_POINTER_EXT* = 0x00008456 + GL_FOG_COORDINATE_ARRAY_EXT* = 0x00008457 + +proc glFogCoordfEXfloat*(coord: TGLfloat){.dynlib: dllname, + importc: "glFogCoordfEXfloat".} +proc glFogCoorddEXdouble*(coord: TGLdouble){.dynlib: dllname, + importc: "glFogCoorddEXdouble".} +proc glFogCoordfvEXfloat*(coord: TGLfloat){.dynlib: dllname, + importc: "glFogCoordfvEXfloat".} +proc glFogCoorddvEXdouble*(coord: TGLdouble){.dynlib: dllname, + importc: "glFogCoorddvEXdouble".} +proc glFogCoordPointerEXT*(thetype: TGLenum, stride: TGLsizei, pointer: PGLvoid){. + dynlib: dllname, importc: "glFogCoordPointerEXT".} + #***** GL_EXT_histogram *****// +const + constGL_HISTOGRAM_EXT* = 0x00008024 + GL_PROXY_HISTOGRAM_EXT* = 0x00008025 + GL_HISTOGRAM_WIDTH_EXT* = 0x00008026 + GL_HISTOGRAM_FORMAT_EXT* = 0x00008027 + GL_HISTOGRAM_RED_SIZE_EXT* = 0x00008028 + GL_HISTOGRAM_GREEN_SIZE_EXT* = 0x00008029 + GL_HISTOGRAM_BLUE_SIZE_EXT* = 0x0000802A + GL_HISTOGRAM_ALPHA_SIZE_EXT* = 0x0000802B + GL_HISTOGRAM_LUMINANCE_SIZE_EXT* = 0x0000802C + GL_HISTOGRAM_SINK_EXT* = 0x0000802D + constGL_MINMAX_EXT* = 0x0000802E + GL_MINMAX_FORMAT_EXT* = 0x0000802F + GL_MINMAX_SINK_EXT* = 0x00008030 + +proc glHistogramEXT*(target: TGLenum, width: TGLsizei, internalformat: TGLenum, + sink: TGLboolean){.dynlib: dllname, + importc: "glHistogramEXT".} +proc glResetHistogramEXT*(target: TGLenum){.dynlib: dllname, + importc: "glResetHistogramEXT".} +proc glGetHistogramEXT*(target: TGLenum, reset: TGLboolean, format: TGLenum, + thetype: TGLenum, values: PGLvoid){.dynlib: dllname, + importc: "glGetHistogramEXT".} +proc glGetHistogramParameterivEXT*(target: TGLenum, pname: TGLenum, + params: PGLint){.dynlib: dllname, + importc: "glGetHistogramParameterivEXT".} +proc glGetHistogramParameterfvEXT*(target: TGLenum, pname: TGLenum, + params: PGLfloat){.dynlib: dllname, + importc: "glGetHistogramParameterfvEXT".} +proc glMinmaxEXT*(target: TGLenum, internalformat: TGLenum, sink: TGLboolean){. + dynlib: dllname, importc: "glMinmaxEXT".} +proc glResetMinmaxEXT*(target: TGLenum){.dynlib: dllname, + importc: "glResetMinmaxEXT".} +proc glGetMinmaxEXT*(target: TGLenum, reset: TGLboolean, format: TGLenum, + thetype: TGLenum, values: PGLvoid){.dynlib: dllname, + importc: "glGetMinmaxEXT".} +proc glGetMinmaxParameterivEXT*(target: TGLenum, pname: TGLenum, params: PGLint){. + dynlib: dllname, importc: "glGetMinmaxParameterivEXT".} +proc glGetMinmaxParameterfvEXT*(target: TGLenum, pname: TGLenum, + params: PGLfloat){.dynlib: dllname, + importc: "glGetMinmaxParameterfvEXT".} + #***** GL_EXT_multi_draw_arrays *****// +proc glMultiDrawArraysEXT*(mode: TGLenum, first: PGLint, count: PGLsizei, + primcount: TGLsizei){.dynlib: dllname, + importc: "glMultiDrawArraysEXT".} +proc glMultiDrawElementsEXT*(mode: TGLenum, count: PGLsizei, thetype: TGLenum, + indices: PGLvoid, primcount: TGLsizei){. + dynlib: dllname, importc: "glMultiDrawElementsEXT".} + #***** GL_EXT_packed_pixels *****// +const + GL_UNSIGNED_BYTE_3_3_2_EXT* = 0x00008032 + GL_UNSIGNED_SHORT_4_4_4_4_EXT* = 0x00008033 + GL_UNSIGNED_SHORT_5_5_5_1_EXT* = 0x00008034 + GL_UNSIGNED_INT_8_8_8_8_EXT* = 0x00008035 + GL_UNSIGNED_INT_10_10_10_2_EXT* = 0x00008036 + #***** GL_EXT_paletted_texture *****// + +const + GL_COLOR_INDEX1_EXT* = 0x000080E2 + GL_COLOR_INDEX2_EXT* = 0x000080E3 + GL_COLOR_INDEX4_EXT* = 0x000080E4 + GL_COLOR_INDEX8_EXT* = 0x000080E5 + GL_COLOR_INDEX12_EXT* = 0x000080E6 + GL_COLOR_INDEX16_EXT* = 0x000080E7 + GL_COLOR_TABLE_FORMAT_EXT* = 0x000080D8 + GL_COLOR_TABLE_WIDTH_EXT* = 0x000080D9 + GL_COLOR_TABLE_RED_SIZE_EXT* = 0x000080DA + GL_COLOR_TABLE_GREEN_SIZE_EXT* = 0x000080DB + GL_COLOR_TABLE_BLUE_SIZE_EXT* = 0x000080DC + GL_COLOR_TABLE_ALPHA_SIZE_EXT* = 0x000080DD + GL_COLOR_TABLE_LUMINANCE_SIZE_EXT* = 0x000080DE + GL_COLOR_TABLE_INTENSITY_SIZE_EXT* = 0x000080DF + GL_TEXTURE_INDEX_SIZE_EXT* = 0x000080ED + GL_TEXTURE_1D* = 0x00000DE0 + GL_TEXTURE_2D* = 0x00000DE1 + GL_TEXTURE_3D_EXT* = 0x0000806F # GL_TEXTURE_CUBE_MAP_ARB { already defined } + GL_PROXY_TEXTURE_1D* = 0x00008063 + GL_PROXY_TEXTURE_2D* = 0x00008064 + GL_PROXY_TEXTURE_3D_EXT* = 0x00008070 # GL_PROXY_TEXTURE_CUBE_MAP_ARB { already defined } + # GL_TEXTURE_1D { already defined } + # GL_TEXTURE_2D { already defined } + # GL_TEXTURE_3D_EXT { already defined } + # GL_TEXTURE_CUBE_MAP_ARB { already defined } + +proc glColorTableEXT*(target: TGLenum, internalFormat: TGLenum, width: TGLsizei, + format: TGLenum, thetype: TGLenum, data: PGLvoid){. + dynlib: dllname, importc: "glColorTableEXT".} + # glColorSubTableEXT { already defined } +proc glGetColorTableEXT*(target: TGLenum, format: TGLenum, thetype: TGLenum, + data: PGLvoid){.dynlib: dllname, + importc: "glGetColorTableEXT".} +proc glGetColorTableParameterivEXT*(target: TGLenum, pname: TGLenum, + params: PGLint){.dynlib: dllname, + importc: "glGetColorTableParameterivEXT".} +proc glGetColorTableParameterfvEXT*(target: TGLenum, pname: TGLenum, + params: PGLfloat){.dynlib: dllname, + importc: "glGetColorTableParameterfvEXT".} + #***** GL_EXT_point_parameters *****// +const + GL_POINT_SIZE_MIN_EXT* = 0x00008126 + GL_POINT_SIZE_MAX_EXT* = 0x00008127 + GL_POINT_FADE_THRESHOLD_SIZE_EXT* = 0x00008128 + GL_DISTANCE_ATTENUATION_EXT* = 0x00008129 + +proc glPointParameterfEXT*(pname: TGLenum, param: TGLfloat){.dynlib: dllname, + importc: "glPointParameterfEXT".} +proc glPointParameterfvEXT*(pname: TGLenum, params: PGLfloat){.dynlib: dllname, + importc: "glPointParameterfvEXT".} + #***** GL_EXT_polygon_offset *****// +const + constGL_POLYGON_OFFSET_EXT* = 0x00008037 + GL_POLYGON_OFFSET_FACTOR_EXT* = 0x00008038 + GL_POLYGON_OFFSET_BIAS_EXT* = 0x00008039 + +proc glPolygonOffsetEXT*(factor: TGLfloat, bias: TGLfloat){.dynlib: dllname, + importc: "glPolygonOffsetEXT".} + #***** GL_EXT_secondary_color *****// +const + GL_COLOR_SUM_EXT* = 0x00008458 + GL_CURRENT_SECONDARY_COLOR_EXT* = 0x00008459 + GL_SECONDARY_COLOR_ARRAY_SIZE_EXT* = 0x0000845A + GL_SECONDARY_COLOR_ARRAY_TYPE_EXT* = 0x0000845B + GL_SECONDARY_COLOR_ARRAY_STRIDE_EXT* = 0x0000845C + GL_SECONDARY_COLOR_ARRAY_POINTER_EXT* = 0x0000845D + GL_SECONDARY_COLOR_ARRAY_EXT* = 0x0000845E + +proc glSecondaryColor3bEXT*(components: TGLbyte){.dynlib: dllname, + importc: "glSecondaryColor3bEXT".} +proc glSecondaryColor3sEXT*(components: TGLshort){.dynlib: dllname, + importc: "glSecondaryColor3sEXT".} +proc glSecondaryColor3iEXT*(components: TGLint){.dynlib: dllname, + importc: "glSecondaryColor3iEXT".} +proc glSecondaryColor3fEXT*(components: TGLfloat){.dynlib: dllname, + importc: "glSecondaryColor3fEXT".} +proc glSecondaryColor3dEXT*(components: TGLdouble){.dynlib: dllname, + importc: "glSecondaryColor3dEXT".} +proc glSecondaryColor3ubEXT*(components: TGLubyte){.dynlib: dllname, + importc: "glSecondaryColor3ubEXT".} +proc glSecondaryColor3usEXT*(components: TGLushort){.dynlib: dllname, + importc: "glSecondaryColor3usEXT".} +proc glSecondaryColor3uiEXT*(components: TGLuint){.dynlib: dllname, + importc: "glSecondaryColor3uiEXT".} +proc glSecondaryColor3bvEXT*(components: TGLbyte){.dynlib: dllname, + importc: "glSecondaryColor3bvEXT".} +proc glSecondaryColor3svEXT*(components: TGLshort){.dynlib: dllname, + importc: "glSecondaryColor3svEXT".} +proc glSecondaryColor3ivEXT*(components: TGLint){.dynlib: dllname, + importc: "glSecondaryColor3ivEXT".} +proc glSecondaryColor3fvEXT*(components: TGLfloat){.dynlib: dllname, + importc: "glSecondaryColor3fvEXT".} +proc glSecondaryColor3dvEXT*(components: TGLdouble){.dynlib: dllname, + importc: "glSecondaryColor3dvEXT".} +proc glSecondaryColor3ubvEXT*(components: TGLubyte){.dynlib: dllname, + importc: "glSecondaryColor3ubvEXT".} +proc glSecondaryColor3usvEXT*(components: TGLushort){.dynlib: dllname, + importc: "glSecondaryColor3usvEXT".} +proc glSecondaryColor3uivEXT*(components: TGLuint){.dynlib: dllname, + importc: "glSecondaryColor3uivEXT".} +proc glSecondaryColorPointerEXT*(size: TGLint, thetype: TGLenum, + stride: TGLsizei, pointer: PGLvoid){. + dynlib: dllname, importc: "glSecondaryColorPointerEXT".} + #***** GL_EXT_separate_specular_color *****// +const + GL_LIGHT_MODEL_COLOR_CONTROL_EXT* = 0x000081F8 + GL_SINGLE_COLOR_EXT* = 0x000081F9 + GL_SEPARATE_SPECULAR_COLOR_EXT* = 0x000081FA + #***** GL_EXT_shadow_funcs *****// + #***** GL_EXT_shared_texture_palette *****// + +const + GL_SHARED_TEXTURE_PALETTE_EXT* = 0x000081FB + #***** GL_EXT_stencil_two_side *****// + +const + GL_STENCIL_TEST_TWO_SIDE_EXT* = 0x00008910 + constGL_ACTIVE_STENCIL_FACE_EXT* = 0x00008911 + +proc glActiveStencilFaceEXT*(face: TGLenum){.dynlib: dllname, + importc: "glActiveStencilFaceEXT".} + #***** GL_EXT_stencil_wrap *****// +const + GL_INCR_WRAP_EXT* = 0x00008507 + GL_DECR_WRAP_EXT* = 0x00008508 + #***** GL_EXT_subtexture *****// + +proc glTexSubImage1DEXT*(target: TGLenum, level: TGLint, xoffset: TGLint, + width: TGLsizei, format: TGLenum, thetype: TGLenum, + pixels: PGLvoid){.dynlib: dllname, + importc: "glTexSubImage1DEXT".} +proc glTexSubImage2DEXT*(target: TGLenum, level: TGLint, xoffset: TGLint, + yoffset: TGLint, width: TGLsizei, height: TGLsizei, + format: TGLenum, thetype: TGLenum, pixels: PGLvoid){. + dynlib: dllname, importc: "glTexSubImage2DEXT".} +proc glTexSubImage3DEXT*(target: TGLenum, level: TGLint, xoffset: TGLint, + yoffset: TGLint, zoffset: TGLint, width: TGLsizei, + height: TGLsizei, depth: TGLsizei, format: TGLenum, + thetype: TGLenum, pixels: PGLvoid){.dynlib: dllname, + importc: "glTexSubImage3DEXT".} + #***** GL_EXT_texture3D *****// +const + GL_PACK_SKIP_IMAGES_EXT* = 0x0000806B + GL_PACK_IMAGE_HEIGHT_EXT* = 0x0000806C + GL_UNPACK_SKIP_IMAGES_EXT* = 0x0000806D + GL_UNPACK_IMAGE_HEIGHT_EXT* = 0x0000806E # GL_TEXTURE_3D_EXT { already defined } + # GL_PROXY_TEXTURE_3D_EXT { already defined } + GL_TEXTURE_DEPTH_EXT* = 0x00008071 + GL_TEXTURE_WRAP_R_EXT* = 0x00008072 + GL_MAX_3D_TEXTURE_SIZE_EXT* = 0x00008073 + +proc glTexImage3DEXT*(target: TGLenum, level: TGLint, internalformat: TGLenum, + width: TGLsizei, height: TGLsizei, depth: TGLsizei, + border: TGLint, format: TGLenum, thetype: TGLenum, + pixels: PGLvoid){.dynlib: dllname, + importc: "glTexImage3DEXT".} + #***** GL_EXT_texture_compression_s3tc *****// +const + GL_COMPRESSED_RGB_S3TC_DXT1_EXT* = 0x000083F0 + GL_COMPRESSED_RGBA_S3TC_DXT1_EXT* = 0x000083F1 + GL_COMPRESSED_RGBA_S3TC_DXT3_EXT* = 0x000083F2 + GL_COMPRESSED_RGBA_S3TC_DXT5_EXT* = 0x000083F3 + #***** GL_EXT_texture_env_add *****// + #***** GL_EXT_texture_env_combine *****// + +const + GL_COMBINE_EXT* = 0x00008570 + GL_COMBINE_RGB_EXT* = 0x00008571 + GL_COMBINE_ALPHA_EXT* = 0x00008572 + GL_SOURCE0_RGB_EXT* = 0x00008580 + GL_SOURCE1_RGB_EXT* = 0x00008581 + GL_SOURCE2_RGB_EXT* = 0x00008582 + GL_SOURCE0_ALPHA_EXT* = 0x00008588 + GL_SOURCE1_ALPHA_EXT* = 0x00008589 + GL_SOURCE2_ALPHA_EXT* = 0x0000858A + GL_OPERAND0_RGB_EXT* = 0x00008590 + GL_OPERAND1_RGB_EXT* = 0x00008591 + GL_OPERAND2_RGB_EXT* = 0x00008592 + GL_OPERAND0_ALPHA_EXT* = 0x00008598 + GL_OPERAND1_ALPHA_EXT* = 0x00008599 + GL_OPERAND2_ALPHA_EXT* = 0x0000859A + GL_RGB_SCALE_EXT* = 0x00008573 + GL_ADD_SIGNED_EXT* = 0x00008574 + GL_INTERPOLATE_EXT* = 0x00008575 + GL_CONSTANT_EXT* = 0x00008576 + GL_PRIMARY_COLOR_EXT* = 0x00008577 + GL_PREVIOUS_EXT* = 0x00008578 + #***** GL_EXT_texture_env_dot3 *****// + +const + GL_DOT3_RGB_EXT* = 0x00008740 + GL_DOT3_RGBA_EXT* = 0x00008741 + #***** GL_EXT_texture_filter_anisotropic *****// + +const + GL_TEXTURE_MAX_ANISOTROPY_EXT* = 0x000084FE + GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT* = 0x000084FF + #***** GL_EXT_texture_lod_bias *****// + +const + GL_TEXTURE_FILTER_CONTROL_EXT* = 0x00008500 + GL_TEXTURE_LOD_BIAS_EXT* = 0x00008501 + GL_MAX_TEXTURE_LOD_BIAS_EXT* = 0x000084FD + #***** GL_EXT_texture_object *****// + +const + GL_TEXTURE_PRIORITY_EXT* = 0x00008066 + GL_TEXTURE_RESIDENT_EXT* = 0x00008067 + GL_TEXTURE_1D_BINDING_EXT* = 0x00008068 + GL_TEXTURE_2D_BINDING_EXT* = 0x00008069 + GL_TEXTURE_3D_BINDING_EXT* = 0x0000806A + +proc glGenTexturesEXT*(n: TGLsizei, textures: PGLuint){.dynlib: dllname, + importc: "glGenTexturesEXT".} +proc glDeleteTexturesEXT*(n: TGLsizei, textures: PGLuint){.dynlib: dllname, + importc: "glDeleteTexturesEXT".} +proc glBindTextureEXT*(target: TGLenum, texture: TGLuint){.dynlib: dllname, + importc: "glBindTextureEXT".} +proc glPrioritizeTexturesEXT*(n: TGLsizei, textures: PGLuint, + priorities: PGLclampf){.dynlib: dllname, + importc: "glPrioritizeTexturesEXT".} +proc glAreTexturesResidentEXT*(n: TGLsizei, textures: PGLuint, + residences: PGLboolean): TGLboolean{. + dynlib: dllname, importc: "glAreTexturesResidentEXT".} +proc glIsTextureEXT*(texture: TGLuint): TGLboolean{.dynlib: dllname, + importc: "glIsTextureEXT".} + #***** GL_EXT_vertex_array *****// +const + GL_VERTEX_ARRAY_EXT* = 0x00008074 + GL_NORMAL_ARRAY_EXT* = 0x00008075 + GL_COLOR_ARRAY_EXT* = 0x00008076 + GL_INDEX_ARRAY_EXT* = 0x00008077 + GL_TEXTURE_COORD_ARRAY_EXT* = 0x00008078 + GL_EDGE_FLAG_ARRAY_EXT* = 0x00008079 + GL_DOUBLE_EXT* = 0x0000140A + GL_VERTEX_ARRAY_SIZE_EXT* = 0x0000807A + GL_VERTEX_ARRAY_TYPE_EXT* = 0x0000807B + GL_VERTEX_ARRAY_STRIDE_EXT* = 0x0000807C + GL_VERTEX_ARRAY_COUNT_EXT* = 0x0000807D + GL_NORMAL_ARRAY_TYPE_EXT* = 0x0000807E + GL_NORMAL_ARRAY_STRIDE_EXT* = 0x0000807F + GL_NORMAL_ARRAY_COUNT_EXT* = 0x00008080 + GL_COLOR_ARRAY_SIZE_EXT* = 0x00008081 + GL_COLOR_ARRAY_TYPE_EXT* = 0x00008082 + GL_COLOR_ARRAY_STRIDE_EXT* = 0x00008083 + GL_COLOR_ARRAY_COUNT_EXT* = 0x00008084 + GL_INDEX_ARRAY_TYPE_EXT* = 0x00008085 + GL_INDEX_ARRAY_STRIDE_EXT* = 0x00008086 + GL_INDEX_ARRAY_COUNT_EXT* = 0x00008087 + GL_TEXTURE_COORD_ARRAY_SIZE_EXT* = 0x00008088 + GL_TEXTURE_COORD_ARRAY_TYPE_EXT* = 0x00008089 + GL_TEXTURE_COORD_ARRAY_STRIDE_EXT* = 0x0000808A + GL_TEXTURE_COORD_ARRAY_COUNT_EXT* = 0x0000808B + GL_EDGE_FLAG_ARRAY_STRIDE_EXT* = 0x0000808C + GL_EDGE_FLAG_ARRAY_COUNT_EXT* = 0x0000808D + GL_VERTEX_ARRAY_POINTER_EXT* = 0x0000808E + GL_NORMAL_ARRAY_POINTER_EXT* = 0x0000808F + GL_COLOR_ARRAY_POINTER_EXT* = 0x00008090 + GL_INDEX_ARRAY_POINTER_EXT* = 0x00008091 + GL_TEXTURE_COORD_ARRAY_POINTER_EXT* = 0x00008092 + GL_EDGE_FLAG_ARRAY_POINTER_EXT* = 0x00008093 + +proc glArrayElementEXT*(i: TGLint){.dynlib: dllname, + importc: "glArrayElementEXT".} +proc glDrawArraysEXT*(mode: TGLenum, first: TGLint, count: TGLsizei){. + dynlib: dllname, importc: "glDrawArraysEXT".} +proc glVertexPointerEXT*(size: TGLint, thetype: TGLenum, stride: TGLsizei, + count: TGLsizei, pointer: PGLvoid){.dynlib: dllname, + importc: "glVertexPointerEXT".} +proc glNormalPointerEXT*(thetype: TGLenum, stride: TGLsizei, count: TGLsizei, + pointer: PGLvoid){.dynlib: dllname, + importc: "glNormalPointerEXT".} +proc glColorPointerEXT*(size: TGLint, thetype: TGLenum, stride: TGLsizei, + count: TGLsizei, pointer: PGLvoid){.dynlib: dllname, + importc: "glColorPointerEXT".} +proc glIndexPointerEXT*(thetype: TGLenum, stride: TGLsizei, count: TGLsizei, + pointer: PGLvoid){.dynlib: dllname, + importc: "glIndexPointerEXT".} +proc glTexCoordPointerEXT*(size: TGLint, thetype: TGLenum, stride: TGLsizei, + count: TGLsizei, pointer: PGLvoid){.dynlib: dllname, + importc: "glTexCoordPointerEXT".} +proc glEdgeFlagPointerEXT*(stride: TGLsizei, count: TGLsizei, + pointer: PGLboolean){.dynlib: dllname, + importc: "glEdgeFlagPointerEXT".} +proc glGetPointervEXT*(pname: TGLenum, params: PGLvoid){.dynlib: dllname, + importc: "glGetPointervEXT".} + #***** GL_EXT_vertex_shader *****// +const + GL_VERTEX_SHADER_EXT* = 0x00008780 + GL_VARIANT_VALUE_EXT* = 0x000087E4 + GL_VARIANT_DATATYPE_EXT* = 0x000087E5 + GL_VARIANT_ARRAY_STRIDE_EXT* = 0x000087E6 + GL_VARIANT_ARRAY_TYPE_EXT* = 0x000087E7 + GL_VARIANT_ARRAY_EXT* = 0x000087E8 + GL_VARIANT_ARRAY_POINTER_EXT* = 0x000087E9 + GL_INVARIANT_VALUE_EXT* = 0x000087EA + GL_INVARIANT_DATATYPE_EXT* = 0x000087EB + GL_LOCAL_CONSTANT_VALUE_EXT* = 0x000087EC + GL_LOCAL_CONSTANT_DATATYPE_EXT* = 0x000087ED + GL_OP_INDEX_EXT* = 0x00008782 + GL_OP_NEGATE_EXT* = 0x00008783 + GL_OP_DOT3_EXT* = 0x00008784 + GL_OP_DOT4_EXT* = 0x00008785 + GL_OP_MUL_EXT* = 0x00008786 + GL_OP_ADD_EXT* = 0x00008787 + GL_OP_MADD_EXT* = 0x00008788 + GL_OP_FRAC_EXT* = 0x00008789 + GL_OP_MAX_EXT* = 0x0000878A + GL_OP_MIN_EXT* = 0x0000878B + GL_OP_SET_GE_EXT* = 0x0000878C + GL_OP_SET_LT_EXT* = 0x0000878D + GL_OP_CLAMP_EXT* = 0x0000878E + GL_OP_FLOOR_EXT* = 0x0000878F + GL_OP_ROUND_EXT* = 0x00008790 + GL_OP_EXP_BASE_2_EXT* = 0x00008791 + GL_OP_LOG_BASE_2_EXT* = 0x00008792 + GL_OP_POWER_EXT* = 0x00008793 + GL_OP_RECIP_EXT* = 0x00008794 + GL_OP_RECIP_SQRT_EXT* = 0x00008795 + GL_OP_SUB_EXT* = 0x00008796 + GL_OP_CROSS_PRODUCT_EXT* = 0x00008797 + GL_OP_MULTIPLY_MATRIX_EXT* = 0x00008798 + GL_OP_MOV_EXT* = 0x00008799 + GL_OUTPUT_VERTEX_EXT* = 0x0000879A + GL_OUTPUT_COLOR0_EXT* = 0x0000879B + GL_OUTPUT_COLOR1_EXT* = 0x0000879C + GL_OUTPUT_TEXTURE_COORD0_EXT* = 0x0000879D + GL_OUTPUT_TEXTURE_COORD1_EXT* = 0x0000879E + GL_OUTPUT_TEXTURE_COORD2_EXT* = 0x0000879F + GL_OUTPUT_TEXTURE_COORD3_EXT* = 0x000087A0 + GL_OUTPUT_TEXTURE_COORD4_EXT* = 0x000087A1 + GL_OUTPUT_TEXTURE_COORD5_EXT* = 0x000087A2 + GL_OUTPUT_TEXTURE_COORD6_EXT* = 0x000087A3 + GL_OUTPUT_TEXTURE_COORD7_EXT* = 0x000087A4 + GL_OUTPUT_TEXTURE_COORD8_EXT* = 0x000087A5 + GL_OUTPUT_TEXTURE_COORD9_EXT* = 0x000087A6 + GL_OUTPUT_TEXTURE_COORD10_EXT* = 0x000087A7 + GL_OUTPUT_TEXTURE_COORD11_EXT* = 0x000087A8 + GL_OUTPUT_TEXTURE_COORD12_EXT* = 0x000087A9 + GL_OUTPUT_TEXTURE_COORD13_EXT* = 0x000087AA + GL_OUTPUT_TEXTURE_COORD14_EXT* = 0x000087AB + GL_OUTPUT_TEXTURE_COORD15_EXT* = 0x000087AC + GL_OUTPUT_TEXTURE_COORD16_EXT* = 0x000087AD + GL_OUTPUT_TEXTURE_COORD17_EXT* = 0x000087AE + GL_OUTPUT_TEXTURE_COORD18_EXT* = 0x000087AF + GL_OUTPUT_TEXTURE_COORD19_EXT* = 0x000087B0 + GL_OUTPUT_TEXTURE_COORD20_EXT* = 0x000087B1 + GL_OUTPUT_TEXTURE_COORD21_EXT* = 0x000087B2 + GL_OUTPUT_TEXTURE_COORD22_EXT* = 0x000087B3 + GL_OUTPUT_TEXTURE_COORD23_EXT* = 0x000087B4 + GL_OUTPUT_TEXTURE_COORD24_EXT* = 0x000087B5 + GL_OUTPUT_TEXTURE_COORD25_EXT* = 0x000087B6 + GL_OUTPUT_TEXTURE_COORD26_EXT* = 0x000087B7 + GL_OUTPUT_TEXTURE_COORD27_EXT* = 0x000087B8 + GL_OUTPUT_TEXTURE_COORD28_EXT* = 0x000087B9 + GL_OUTPUT_TEXTURE_COORD29_EXT* = 0x000087BA + GL_OUTPUT_TEXTURE_COORD30_EXT* = 0x000087BB + GL_OUTPUT_TEXTURE_COORD31_EXT* = 0x000087BC + GL_OUTPUT_FOG_EXT* = 0x000087BD + GL_SCALAR_EXT* = 0x000087BE + GL_VECTOR_EXT* = 0x000087BF + GL_MATRIX_EXT* = 0x000087C0 + GL_VARIANT_EXT* = 0x000087C1 + GL_INVARIANT_EXT* = 0x000087C2 + GL_LOCAL_CONSTANT_EXT* = 0x000087C3 + GL_LOCAL_EXT* = 0x000087C4 + GL_MAX_VERTEX_SHADER_INSTRUCTIONS_EXT* = 0x000087C5 + GL_MAX_VERTEX_SHADER_VARIANTS_EXT* = 0x000087C6 + GL_MAX_VERTEX_SHADER_INVARIANTS_EXT* = 0x000087C7 + GL_MAX_VERTEX_SHADER_LOCAL_CONSTANTS_EXT* = 0x000087C8 + GL_MAX_VERTEX_SHADER_LOCALS_EXT* = 0x000087C9 + GL_MAX_OPTIMIZED_VERTEX_SHADER_INSTRUCTIONS_EXT* = 0x000087CA + GL_MAX_OPTIMIZED_VERTEX_SHADER_VARIANTS_EXT* = 0x000087CB + GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCAL_CONSTANTS_EXT* = 0x000087CC + GL_MAX_OPTIMIZED_VERTEX_SHADER_INVARIANTS_EXT* = 0x000087CD + GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCALS_EXT* = 0x000087CE + GL_VERTEX_SHADER_INSTRUCTIONS_EXT* = 0x000087CF + GL_VERTEX_SHADER_VARIANTS_EXT* = 0x000087D0 + GL_VERTEX_SHADER_INVARIANTS_EXT* = 0x000087D1 + GL_VERTEX_SHADER_LOCAL_CONSTANTS_EXT* = 0x000087D2 + GL_VERTEX_SHADER_LOCALS_EXT* = 0x000087D3 + GL_VERTEX_SHADER_BINDING_EXT* = 0x00008781 + GL_VERTEX_SHADER_OPTIMIZED_EXT* = 0x000087D4 + GL_X_EXT* = 0x000087D5 + GL_Y_EXT* = 0x000087D6 + GL_Z_EXT* = 0x000087D7 + GL_W_EXT* = 0x000087D8 + GL_NEGATIVE_X_EXT* = 0x000087D9 + GL_NEGATIVE_Y_EXT* = 0x000087DA + GL_NEGATIVE_Z_EXT* = 0x000087DB + GL_NEGATIVE_W_EXT* = 0x000087DC + GL_ZERO_EXT* = 0x000087DD + GL_ONE_EXT* = 0x000087DE + GL_NEGATIVE_ONE_EXT* = 0x000087DF + GL_NORMALIZED_RANGE_EXT* = 0x000087E0 + GL_FULL_RANGE_EXT* = 0x000087E1 + GL_CURRENT_VERTEX_EXT* = 0x000087E2 + GL_MVP_MATRIX_EXT* = 0x000087E3 + +proc glBeginVertexShaderEXT*(){.dynlib: dllname, + importc: "glBeginVertexShaderEXT".} +proc glEndVertexShaderEXT*(){.dynlib: dllname, importc: "glEndVertexShaderEXT".} +proc glBindVertexShaderEXT*(id: TGLuint){.dynlib: dllname, + importc: "glBindVertexShaderEXT".} +proc glGenVertexShadersEXT*(range: TGLuint): TGLuint{.dynlib: dllname, + importc: "glGenVertexShadersEXT".} +proc glDeleteVertexShaderEXT*(id: TGLuint){.dynlib: dllname, + importc: "glDeleteVertexShaderEXT".} +proc glShaderOp1EXT*(op: TGLenum, res: TGLuint, arg1: TGLuint){.dynlib: dllname, + importc: "glShaderOp1EXT".} +proc glShaderOp2EXT*(op: TGLenum, res: TGLuint, arg1: TGLuint, arg2: TGLuint){. + dynlib: dllname, importc: "glShaderOp2EXT".} +proc glShaderOp3EXT*(op: TGLenum, res: TGLuint, arg1: TGLuint, arg2: TGLuint, + arg3: TGLuint){.dynlib: dllname, importc: "glShaderOp3EXT".} +proc glSwizzleEXT*(res: TGLuint, theIn: TGLuint, outX: TGLenum, outY: TGLenum, + outZ: TGLenum, outW: TGLenum){.dynlib: dllname, + importc: "glSwizzleEXT".} +proc glWriteMaskEXT*(res: TGLuint, theIn: TGLuint, outX: TGLenum, outY: TGLenum, + outZ: TGLenum, outW: TGLenum){.dynlib: dllname, + importc: "glWriteMaskEXT".} +proc glInsertComponentEXT*(res: TGLuint, src: TGLuint, num: TGLuint){. + dynlib: dllname, importc: "glInsertComponentEXT".} +proc glExtractComponentEXT*(res: TGLuint, src: TGLuint, num: TGLuint){. + dynlib: dllname, importc: "glExtractComponentEXT".} +proc glGenSymbolsEXT*(datatype: TGLenum, storagetype: TGLenum, range: TGLenum, + components: TGLuint): TGLuint{.dynlib: dllname, + importc: "glGenSymbolsEXT".} +proc glSetInvariantEXT*(id: TGLuint, thetype: TGLenum, address: PGLvoid){. + dynlib: dllname, importc: "glSetInvariantEXT".} +proc glSetLocalConstantEXT*(id: TGLuint, thetype: TGLenum, address: PGLvoid){. + dynlib: dllname, importc: "glSetLocalConstantEXT".} +proc glVariantbvEXT*(id: TGLuint, address: PGLbyte){.dynlib: dllname, + importc: "glVariantbvEXT".} +proc glVariantsvEXT*(id: TGLuint, address: PGLshort){.dynlib: dllname, + importc: "glVariantsvEXT".} +proc glVariantivEXT*(id: TGLuint, address: PGLint){.dynlib: dllname, + importc: "glVariantivEXT".} +proc glVariantfvEXT*(id: TGLuint, address: PGLfloat){.dynlib: dllname, + importc: "glVariantfvEXT".} +proc glVariantdvEXT*(id: TGLuint, address: PGLdouble){.dynlib: dllname, + importc: "glVariantdvEXT".} +proc glVariantubvEXT*(id: TGLuint, address: PGLubyte){.dynlib: dllname, + importc: "glVariantubvEXT".} +proc glVariantusvEXT*(id: TGLuint, address: PGLushort){.dynlib: dllname, + importc: "glVariantusvEXT".} +proc glVariantuivEXT*(id: TGLuint, address: PGLuint){.dynlib: dllname, + importc: "glVariantuivEXT".} +proc glVariantPointerEXT*(id: TGLuint, thetype: TGLenum, stride: TGLuint, + address: PGLvoid){.dynlib: dllname, + importc: "glVariantPointerEXT".} +proc glEnableVariantClientStateEXT*(id: TGLuint){.dynlib: dllname, + importc: "glEnableVariantClientStateEXT".} +proc glDisableVariantClientStateEXT*(id: TGLuint){.dynlib: dllname, + importc: "glDisableVariantClientStateEXT".} +proc glBindLightParameterEXT*(light: TGLenum, value: TGLenum): TGLuint{. + dynlib: dllname, importc: "glBindLightParameterEXT".} +proc glBindMaterialParameterEXT*(face: TGLenum, value: TGLenum): TGLuint{. + dynlib: dllname, importc: "glBindMaterialParameterEXT".} +proc glBindTexGenParameterEXT*(theunit: TGLenum, coord: TGLenum, value: TGLenum): TGLuint{. + dynlib: dllname, importc: "glBindTexGenParameterEXT".} +proc glBindTextureUnitParameterEXT*(theunit: TGLenum, value: TGLenum): TGLuint{. + dynlib: dllname, importc: "glBindTextureUnitParameterEXT".} +proc glBindParameterEXT*(value: TGLenum): TGLuint{.dynlib: dllname, + importc: "glBindParameterEXT".} +proc glIsVariantEnabledEXT*(id: TGLuint, cap: TGLenum): TGLboolean{. + dynlib: dllname, importc: "glIsVariantEnabledEXT".} +proc glGetVariantBooleanvEXT*(id: TGLuint, value: TGLenum, data: PGLboolean){. + dynlib: dllname, importc: "glGetVariantBooleanvEXT".} +proc glGetVariantIntegervEXT*(id: TGLuint, value: TGLenum, data: PGLint){. + dynlib: dllname, importc: "glGetVariantIntegervEXT".} +proc glGetVariantFloatvEXT*(id: TGLuint, value: TGLenum, data: PGLfloat){. + dynlib: dllname, importc: "glGetVariantFloatvEXT".} +proc glGetVariantPointervEXT*(id: TGLuint, value: TGLenum, data: PGLvoid){. + dynlib: dllname, importc: "glGetVariantPointervEXT".} +proc glGetInvariantBooleanvEXT*(id: TGLuint, value: TGLenum, data: PGLboolean){. + dynlib: dllname, importc: "glGetInvariantBooleanvEXT".} +proc glGetInvariantIntegervEXT*(id: TGLuint, value: TGLenum, data: PGLint){. + dynlib: dllname, importc: "glGetInvariantIntegervEXT".} +proc glGetInvariantFloatvEXT*(id: TGLuint, value: TGLenum, data: PGLfloat){. + dynlib: dllname, importc: "glGetInvariantFloatvEXT".} +proc glGetLocalConstantBooleanvEXT*(id: TGLuint, value: TGLenum, + data: PGLboolean){.dynlib: dllname, + importc: "glGetLocalConstantBooleanvEXT".} +proc glGetLocalConstantIntegervEXT*(id: TGLuint, value: TGLenum, data: PGLint){. + dynlib: dllname, importc: "glGetLocalConstantIntegervEXT".} +proc glGetLocalConstantFloatvEXT*(id: TGLuint, value: TGLenum, data: PGLfloat){. + dynlib: dllname, importc: "glGetLocalConstantFloatvEXT".} + #***** GL_EXT_vertex_weighting *****// +const + GL_VERTEX_WEIGHTING_EXT* = 0x00008509 + GL_MODELVIEW0_EXT* = 0x00001700 + GL_MODELVIEW1_EXT* = 0x0000850A + GL_MODELVIEW0_MATRIX_EXT* = 0x00000BA6 + GL_MODELVIEW1_MATRIX_EXT* = 0x00008506 + GL_CURRENT_VERTEX_WEIGHT_EXT* = 0x0000850B + GL_VERTEX_WEIGHT_ARRAY_EXT* = 0x0000850C + GL_VERTEX_WEIGHT_ARRAY_SIZE_EXT* = 0x0000850D + GL_VERTEX_WEIGHT_ARRAY_TYPE_EXT* = 0x0000850E + GL_VERTEX_WEIGHT_ARRAY_STRIDE_EXT* = 0x0000850F + GL_MODELVIEW0_STACK_DEPTH_EXT* = 0x00000BA3 + GL_MODELVIEW1_STACK_DEPTH_EXT* = 0x00008502 + GL_VERTEX_WEIGHT_ARRAY_POINTER_EXT* = 0x00008510 + +proc glVertexWeightfEXT*(weight: TGLfloat){.dynlib: dllname, + importc: "glVertexWeightfEXT".} +proc glVertexWeightfvEXT*(weight: PGLfloat){.dynlib: dllname, + importc: "glVertexWeightfvEXT".} +proc glVertexWeightPointerEXT*(size: TGLint, thetype: TGLenum, stride: TGLsizei, + pointer: PGLvoid){.dynlib: dllname, + importc: "glVertexWeightPointerEXT".} + #***** GL_HP_occlusion_test *****// +const + GL_OCCLUSION_TEST_HP* = 0x00008165 + GL_OCCLUSION_TEST_RESULT_HP* = 0x00008166 + #***** GL_NV_blend_square *****// + #***** GL_NV_copy_depth_to_color *****// + +const + GL_DEPTH_STENCIL_TO_RGBA_NV* = 0x0000886E + GL_DEPTH_STENCIL_TO_BGRA_NV* = 0x0000886F + #***** GL_NV_depth_clamp *****// + +const + GL_DEPTH_CLAMP_NV* = 0x0000864F + #***** GL_NV_evaluators *****// + +const + GL_EVAL_2D_NV* = 0x000086C0 + GL_EVAL_TRIANGULAR_2D_NV* = 0x000086C1 + GL_MAP_TESSELLATION_NV* = 0x000086C2 + GL_MAP_ATTRIB_U_ORDER_NV* = 0x000086C3 + GL_MAP_ATTRIB_V_ORDER_NV* = 0x000086C4 + GL_EVAL_FRACTIONAL_TESSELLATION_NV* = 0x000086C5 + GL_EVAL_VERTEX_ATTRIB0_NV* = 0x000086C6 + GL_EVAL_VERTEX_ATTRIB1_NV* = 0x000086C7 + GL_EVAL_VERTEX_ATTRIB2_NV* = 0x000086C8 + GL_EVAL_VERTEX_ATTRIB3_NV* = 0x000086C9 + GL_EVAL_VERTEX_ATTRIB4_NV* = 0x000086CA + GL_EVAL_VERTEX_ATTRIB5_NV* = 0x000086CB + GL_EVAL_VERTEX_ATTRIB6_NV* = 0x000086CC + GL_EVAL_VERTEX_ATTRIB7_NV* = 0x000086CD + GL_EVAL_VERTEX_ATTRIB8_NV* = 0x000086CE + GL_EVAL_VERTEX_ATTRIB9_NV* = 0x000086CF + GL_EVAL_VERTEX_ATTRIB10_NV* = 0x000086D0 + GL_EVAL_VERTEX_ATTRIB11_NV* = 0x000086D1 + GL_EVAL_VERTEX_ATTRIB12_NV* = 0x000086D2 + GL_EVAL_VERTEX_ATTRIB13_NV* = 0x000086D3 + GL_EVAL_VERTEX_ATTRIB14_NV* = 0x000086D4 + GL_EVAL_VERTEX_ATTRIB15_NV* = 0x000086D5 + GL_MAX_MAP_TESSELLATION_NV* = 0x000086D6 + GL_MAX_RATIONAL_EVAL_ORDER_NV* = 0x000086D7 + +proc glMapControlPointsNV*(target: TGLenum, index: TGLuint, thetype: TGLenum, + ustride: TGLsizei, vstride: TGLsizei, uorder: TGLint, + vorder: TGLint, thepacked: TGLboolean, + points: PGLvoid){.dynlib: dllname, + importc: "glMapControlPointsNV".} +proc glMapParameterivNV*(target: TGLenum, pname: TGLenum, params: PGLint){. + dynlib: dllname, importc: "glMapParameterivNV".} +proc glMapParameterfvNV*(target: TGLenum, pname: TGLenum, params: PGLfloat){. + dynlib: dllname, importc: "glMapParameterfvNV".} +proc glGetMapControlPointsNV*(target: TGLenum, index: TGLuint, thetype: TGLenum, + ustride: TGLsizei, vstride: TGLsizei, + thepacked: TGLboolean, points: PGLvoid){. + dynlib: dllname, importc: "glGetMapControlPointsNV".} +proc glGetMapParameterivNV*(target: TGLenum, pname: TGLenum, params: PGLint){. + dynlib: dllname, importc: "glGetMapParameterivNV".} +proc glGetMapParameterfvNV*(target: TGLenum, pname: TGLenum, params: PGLfloat){. + dynlib: dllname, importc: "glGetMapParameterfvNV".} +proc glGetMapAttribParameterivNV*(target: TGLenum, index: TGLuint, + pname: TGLenum, params: PGLint){. + dynlib: dllname, importc: "glGetMapAttribParameterivNV".} +proc glGetMapAttribParameterfvNV*(target: TGLenum, index: TGLuint, + pname: TGLenum, params: PGLfloat){. + dynlib: dllname, importc: "glGetMapAttribParameterfvNV".} +proc glEvalMapsNV*(target: TGLenum, mode: TGLenum){.dynlib: dllname, + importc: "glEvalMapsNV".} + #***** GL_NV_fence *****// +const + GL_ALL_COMPLETED_NV* = 0x000084F2 + GL_FENCE_STATUS_NV* = 0x000084F3 + GL_FENCE_CONDITION_NV* = 0x000084F4 + +proc glGenFencesNV*(n: TGLsizei, fences: PGLuint){.dynlib: dllname, + importc: "glGenFencesNV".} +proc glDeleteFencesNV*(n: TGLsizei, fences: PGLuint){.dynlib: dllname, + importc: "glDeleteFencesNV".} +proc glSetFenceNV*(fence: TGLuint, condition: TGLenum){.dynlib: dllname, + importc: "glSetFenceNV".} +proc glTestFenceNV*(fence: TGLuint): TGLboolean{.dynlib: dllname, + importc: "glTestFenceNV".} +proc glFinishFenceNV*(fence: TGLuint){.dynlib: dllname, + importc: "glFinishFenceNV".} +proc glIsFenceNV*(fence: TGLuint): TGLboolean{.dynlib: dllname, + importc: "glIsFenceNV".} +proc glGetFenceivNV*(fence: TGLuint, pname: TGLenum, params: PGLint){. + dynlib: dllname, importc: "glGetFenceivNV".} + #***** GL_NV_fog_distance *****// +const + GL_FOG_DISTANCE_MODE_NV* = 0x0000855A + GL_EYE_RADIAL_NV* = 0x0000855B + GL_EYE_PLANE_ABSOLUTE_NV* = 0x0000855C + #***** GL_NV_light_max_exponent *****// + +const + GL_MAX_SHININESS_NV* = 0x00008504 + GL_MAX_SPOT_EXPONENT_NV* = 0x00008505 + #***** GL_NV_multisample_filter_hint *****// + +const + GL_MULTISAMPLE_FILTER_HINT_NV* = 0x00008534 + #***** GL_NV_occlusion_query *****// + # GL_OCCLUSION_TEST_HP { already defined } + # GL_OCCLUSION_TEST_RESULT_HP { already defined } + +const + GL_PIXEL_COUNTER_BITS_NV* = 0x00008864 + GL_CURRENT_OCCLUSION_QUERY_ID_NV* = 0x00008865 + GL_PIXEL_COUNT_NV* = 0x00008866 + GL_PIXEL_COUNT_AVAILABLE_NV* = 0x00008867 + +proc glGenOcclusionQueriesNV*(n: TGLsizei, ids: PGLuint){.dynlib: dllname, + importc: "glGenOcclusionQueriesNV".} +proc glDeleteOcclusionQueriesNV*(n: TGLsizei, ids: PGLuint){.dynlib: dllname, + importc: "glDeleteOcclusionQueriesNV".} +proc glIsOcclusionQueryNV*(id: TGLuint): TGLboolean{.dynlib: dllname, + importc: "glIsOcclusionQueryNV".} +proc glBeginOcclusionQueryNV*(id: TGLuint){.dynlib: dllname, + importc: "glBeginOcclusionQueryNV".} +proc glEndOcclusionQueryNV*(){.dynlib: dllname, importc: "glEndOcclusionQueryNV".} +proc glGetOcclusionQueryivNV*(id: TGLuint, pname: TGLenum, params: PGLint){. + dynlib: dllname, importc: "glGetOcclusionQueryivNV".} +proc glGetOcclusionQueryuivNV*(id: TGLuint, pname: TGLenum, params: PGLuint){. + dynlib: dllname, importc: "glGetOcclusionQueryuivNV".} + #***** GL_NV_packed_depth_stencil *****// +const + GL_DEPTH_STENCIL_NV* = 0x000084F9 + GL_UNSIGNED_INT_24_8_NV* = 0x000084FA + #***** GL_NV_point_sprite *****// + +const + GL_POINT_SPRITE_NV* = 0x00008861 + GL_COORD_REPLACE_NV* = 0x00008862 + GL_POINT_SPRITE_R_MODE_NV* = 0x00008863 + +proc glPointParameteriNV*(pname: TGLenum, param: TGLint){.dynlib: dllname, + importc: "glPointParameteriNV".} +proc glPointParameterivNV*(pname: TGLenum, params: PGLint){.dynlib: dllname, + importc: "glPointParameterivNV".} + #***** GL_NV_register_combiners *****// +const + GL_REGISTER_COMBINERS_NV* = 0x00008522 + GL_COMBINER0_NV* = 0x00008550 + GL_COMBINER1_NV* = 0x00008551 + GL_COMBINER2_NV* = 0x00008552 + GL_COMBINER3_NV* = 0x00008553 + GL_COMBINER4_NV* = 0x00008554 + GL_COMBINER5_NV* = 0x00008555 + GL_COMBINER6_NV* = 0x00008556 + GL_COMBINER7_NV* = 0x00008557 + GL_VARIABLE_A_NV* = 0x00008523 + GL_VARIABLE_B_NV* = 0x00008524 + GL_VARIABLE_C_NV* = 0x00008525 + GL_VARIABLE_D_NV* = 0x00008526 + GL_VARIABLE_E_NV* = 0x00008527 + GL_VARIABLE_F_NV* = 0x00008528 + GL_VARIABLE_G_NV* = 0x00008529 + GL_CONSTANT_COLOR0_NV* = 0x0000852A + GL_CONSTANT_COLOR1_NV* = 0x0000852B + GL_PRIMARY_COLOR_NV* = 0x0000852C + GL_SECONDARY_COLOR_NV* = 0x0000852D + GL_SPARE0_NV* = 0x0000852E + GL_SPARE1_NV* = 0x0000852F + GL_UNSIGNED_IDENTITY_NV* = 0x00008536 + GL_UNSIGNED_INVERT_NV* = 0x00008537 + GL_EXPAND_NORMAL_NV* = 0x00008538 + GL_EXPAND_NEGATE_NV* = 0x00008539 + GL_HALF_BIAS_NORMAL_NV* = 0x0000853A + GL_HALF_BIAS_NEGATE_NV* = 0x0000853B + GL_SIGNED_IDENTITY_NV* = 0x0000853C + GL_SIGNED_NEGATE_NV* = 0x0000853D + GL_E_TIMES_F_NV* = 0x00008531 + GL_SPARE0_PLUS_SECONDARY_COLOR_NV* = 0x00008532 + GL_SCALE_BY_TWO_NV* = 0x0000853E + GL_SCALE_BY_FOUR_NV* = 0x0000853F + GL_SCALE_BY_ONE_HALF_NV* = 0x00008540 + GL_BIAS_BY_NEGATIVE_ONE_HALF_NV* = 0x00008541 + GL_DISCARD_NV* = 0x00008530 + constGL_COMBINER_INPUT_NV* = 0x00008542 + GL_COMBINER_MAPPING_NV* = 0x00008543 + GL_COMBINER_COMPONENT_USAGE_NV* = 0x00008544 + GL_COMBINER_AB_DOT_PRODUCT_NV* = 0x00008545 + GL_COMBINER_CD_DOT_PRODUCT_NV* = 0x00008546 + GL_COMBINER_MUX_SUM_NV* = 0x00008547 + GL_COMBINER_SCALE_NV* = 0x00008548 + GL_COMBINER_BIAS_NV* = 0x00008549 + GL_COMBINER_AB_OUTPUT_NV* = 0x0000854A + GL_COMBINER_CD_OUTPUT_NV* = 0x0000854B + GL_COMBINER_SUM_OUTPUT_NV* = 0x0000854C + GL_NUM_GENERAL_COMBINERS_NV* = 0x0000854E + GL_COLOR_SUM_CLAMP_NV* = 0x0000854F + GL_MAX_GENERAL_COMBINERS_NV* = 0x0000854D + +proc glCombinerParameterfvNV*(pname: TGLenum, params: PGLfloat){. + dynlib: dllname, importc: "glCombinerParameterfvNV".} +proc glCombinerParameterivNV*(pname: TGLenum, params: PGLint){.dynlib: dllname, + importc: "glCombinerParameterivNV".} +proc glCombinerParameterfNV*(pname: TGLenum, param: TGLfloat){.dynlib: dllname, + importc: "glCombinerParameterfNV".} +proc glCombinerParameteriNV*(pname: TGLenum, param: TGLint){.dynlib: dllname, + importc: "glCombinerParameteriNV".} +proc glCombinerInputNV*(stage: TGLenum, portion: TGLenum, variable: TGLenum, + input: TGLenum, mapping: TGLenum, + componentUsage: TGLenum){.dynlib: dllname, + importc: "glCombinerInputNV".} +proc glCombinerOutputNV*(stage: TGLenum, portion: TGLenum, abOutput: TGLenum, + cdOutput: TGLenum, sumOutput: TGLenum, scale: TGLenum, + bias: TGLenum, abDotProduct: TGLboolean, + cdDotProduct: TGLboolean, muxSum: TGLboolean){. + dynlib: dllname, importc: "glCombinerOutputNV".} +proc glFinalCombinerInputNV*(variable: TGLenum, input: TGLenum, + mapping: TGLenum, componentUsage: TGLenum){. + dynlib: dllname, importc: "glFinalCombinerInputNV".} +proc glGetCombinerInputParameterfvNV*(stage: TGLenum, portion: TGLenum, + variable: TGLenum, pname: TGLenum, + params: PGLfloat){.dynlib: dllname, + importc: "glGetCombinerInputParameterfvNV".} +proc glGetCombinerInputParameterivNV*(stage: TGLenum, portion: TGLenum, + variable: TGLenum, pname: TGLenum, + params: PGLint){.dynlib: dllname, + importc: "glGetCombinerInputParameterivNV".} +proc glGetCombinerOutputParameterfvNV*(stage: TGLenum, portion: TGLenum, + pname: TGLenum, params: PGLfloat){. + dynlib: dllname, importc: "glGetCombinerOutputParameterfvNV".} +proc glGetCombinerOutputParameterivNV*(stage: TGLenum, portion: TGLenum, + pname: TGLenum, params: PGLint){. + dynlib: dllname, importc: "glGetCombinerOutputParameterivNV".} +proc glGetFinalCombinerInputParameterfvNV*(variable: TGLenum, pname: TGLenum, + params: PGLfloat){.dynlib: dllname, + importc: "glGetFinalCombinerInputParameterfvNV".} +proc glGetFinalCombinerInputParameterivNV*(variable: TGLenum, pname: TGLenum, + params: PGLint){.dynlib: dllname, + importc: "glGetFinalCombinerInputParameterivNV".} + #***** GL_NV_register_combiners2 *****// +const + GL_PER_STAGE_CONSTANTS_NV* = 0x00008535 + +proc glCombinerStageParameterfvNV*(stage: TGLenum, pname: TGLenum, + params: PGLfloat){.dynlib: dllname, + importc: "glCombinerStageParameterfvNV".} +proc glGetCombinerStageParameterfvNV*(stage: TGLenum, pname: TGLenum, + params: PGLfloat){.dynlib: dllname, + importc: "glGetCombinerStageParameterfvNV".} + #***** GL_NV_texgen_emboss *****// +const + GL_EMBOSS_MAP_NV* = 0x0000855F + GL_EMBOSS_LIGHT_NV* = 0x0000855D + GL_EMBOSS_CONSTANT_NV* = 0x0000855E + #***** GL_NV_texgen_reflection *****// + +const + GL_NORMAL_MAP_NV* = 0x00008511 + GL_REFLECTION_MAP_NV* = 0x00008512 + #***** GL_NV_texture_compression_vtc *****// + # GL_COMPRESSED_RGB_S3TC_DXT1_EXT { already defined } + # GL_COMPRESSED_RGBA_S3TC_DXT1_EXT { already defined } + # GL_COMPRESSED_RGBA_S3TC_DXT3_EXT { already defined } + # GL_COMPRESSED_RGBA_S3TC_DXT5_EXT { already defined } + #***** GL_NV_texture_env_combine4 *****// + +const + GL_COMBINE4_NV* = 0x00008503 + GL_SOURCE3_RGB_NV* = 0x00008583 + GL_SOURCE3_ALPHA_NV* = 0x0000858B + GL_OPERAND3_RGB_NV* = 0x00008593 + GL_OPERAND3_ALPHA_NV* = 0x0000859B + #***** GL_NV_texture_rectangle *****// + +const + GL_TEXTURE_RECTANGLE_NV* = 0x000084F5 + GL_TEXTURE_BINDING_RECTANGLE_NV* = 0x000084F6 + GL_PROXY_TEXTURE_RECTANGLE_NV* = 0x000084F7 + GL_MAX_RECTANGLE_TEXTURE_SIZE_NV* = 0x000084F8 + #***** GL_NV_texture_shader *****// + +const + GL_TEXTURE_SHADER_NV* = 0x000086DE + GL_RGBA_UNSIGNED_DOT_PRODUCT_MAPPING_NV* = 0x000086D9 + GL_SHADER_OPERATION_NV* = 0x000086DF + GL_CULL_MODES_NV* = 0x000086E0 + GL_OFFSET_TEXTURE_MATRIX_NV* = 0x000086E1 + GL_OFFSET_TEXTURE_SCALE_NV* = 0x000086E2 + GL_OFFSET_TEXTURE_BIAS_NV* = 0x000086E3 + GL_PREVIOUS_TEXTURE_INPUT_NV* = 0x000086E4 + GL_CONST_EYE_NV* = 0x000086E5 + GL_SHADER_CONSISTENT_NV* = 0x000086DD + GL_PASS_THROUGH_NV* = 0x000086E6 + GL_CULL_FRAGMENT_NV* = 0x000086E7 + GL_OFFSET_TEXTURE_2D_NV* = 0x000086E8 + GL_OFFSET_TEXTURE_RECTANGLE_NV* = 0x0000864C + GL_OFFSET_TEXTURE_RECTANGLE_SCALE_NV* = 0x0000864D + GL_DEPENDENT_AR_TEXTURE_2D_NV* = 0x000086E9 + GL_DEPENDENT_GB_TEXTURE_2D_NV* = 0x000086EA + GL_DOT_PRODUCT_NV* = 0x000086EC + GL_DOT_PRODUCT_DEPTH_REPLACE_NV* = 0x000086ED + GL_DOT_PRODUCT_TEXTURE_2D_NV* = 0x000086EE + GL_DOT_PRODUCT_TEXTURE_RECTANGLE_NV* = 0x0000864E + GL_DOT_PRODUCT_TEXTURE_CUBE_MAP_NV* = 0x000086F0 + GL_DOT_PRODUCT_DIFFUSE_CUBE_MAP_NV* = 0x000086F1 + GL_DOT_PRODUCT_REFLECT_CUBE_MAP_NV* = 0x000086F2 + GL_DOT_PRODUCT_CONST_EYE_REFLECT_CUBE_MAP_NV* = 0x000086F3 + GL_HILO_NV* = 0x000086F4 + GL_DSDT_NV* = 0x000086F5 + GL_DSDT_MAG_NV* = 0x000086F6 + GL_DSDT_MAG_VIB_NV* = 0x000086F7 + GL_UNSIGNED_INT_S8_S8_8_8_NV* = 0x000086DA + GL_UNSIGNED_INT_8_8_S8_S8_REV_NV* = 0x000086DB + GL_SIGNED_RGBA_NV* = 0x000086FB + GL_SIGNED_RGBA8_NV* = 0x000086FC + GL_SIGNED_RGB_NV* = 0x000086FE + GL_SIGNED_RGB8_NV* = 0x000086FF + GL_SIGNED_LUMINANCE_NV* = 0x00008701 + GL_SIGNED_LUMINANCE8_NV* = 0x00008702 + GL_SIGNED_LUMINANCE_ALPHA_NV* = 0x00008703 + GL_SIGNED_LUMINANCE8_ALPHA8_NV* = 0x00008704 + GL_SIGNED_ALPHA_NV* = 0x00008705 + GL_SIGNED_ALPHA8_NV* = 0x00008706 + GL_SIGNED_INTENSITY_NV* = 0x00008707 + GL_SIGNED_INTENSITY8_NV* = 0x00008708 + GL_SIGNED_RGB_UNSIGNED_ALPHA_NV* = 0x0000870C + GL_SIGNED_RGB8_UNSIGNED_ALPHA8_NV* = 0x0000870D + GL_HILO16_NV* = 0x000086F8 + GL_SIGNED_HILO_NV* = 0x000086F9 + GL_SIGNED_HILO16_NV* = 0x000086FA + GL_DSDT8_NV* = 0x00008709 + GL_DSDT8_MAG8_NV* = 0x0000870A + GL_DSDT_MAG_INTENSITY_NV* = 0x000086DC + GL_DSDT8_MAG8_INTENSITY8_NV* = 0x0000870B + GL_HI_SCALE_NV* = 0x0000870E + GL_LO_SCALE_NV* = 0x0000870F + GL_DS_SCALE_NV* = 0x00008710 + GL_DT_SCALE_NV* = 0x00008711 + GL_MAGNITUDE_SCALE_NV* = 0x00008712 + GL_VIBRANCE_SCALE_NV* = 0x00008713 + GL_HI_BIAS_NV* = 0x00008714 + GL_LO_BIAS_NV* = 0x00008715 + GL_DS_BIAS_NV* = 0x00008716 + GL_DT_BIAS_NV* = 0x00008717 + GL_MAGNITUDE_BIAS_NV* = 0x00008718 + GL_VIBRANCE_BIAS_NV* = 0x00008719 + GL_TEXTURE_BORDER_VALUES_NV* = 0x0000871A + GL_TEXTURE_HI_SIZE_NV* = 0x0000871B + GL_TEXTURE_LO_SIZE_NV* = 0x0000871C + GL_TEXTURE_DS_SIZE_NV* = 0x0000871D + GL_TEXTURE_DT_SIZE_NV* = 0x0000871E + GL_TEXTURE_MAG_SIZE_NV* = 0x0000871F + #***** GL_NV_texture_shader2 *****// + +const + GL_DOT_PRODUCT_TEXTURE_3D_NV* = 0x000086EF # GL_HILO_NV { already defined } + # GL_DSDT_NV { already defined } + # GL_DSDT_MAG_NV { already defined } + # GL_DSDT_MAG_VIB_NV { already defined } + # GL_UNSIGNED_INT_S8_S8_8_8_NV { already defined } + # GL_UNSIGNED_INT_8_8_S8_S8_REV_NV { already defined } + # GL_SIGNED_RGBA_NV { already defined } + # GL_SIGNED_RGBA8_NV { already defined } + # GL_SIGNED_RGB_NV { already defined } + # GL_SIGNED_RGB8_NV { already defined } + # GL_SIGNED_LUMINANCE_NV { already defined } + # GL_SIGNED_LUMINANCE8_NV { already defined } + # GL_SIGNED_LUMINANCE_ALPHA_NV { already defined } + # GL_SIGNED_LUMINANCE8_ALPHA8_NV { already defined } + # GL_SIGNED_ALPHA_NV { already defined } + # GL_SIGNED_ALPHA8_NV { already defined } + # GL_SIGNED_INTENSITY_NV { already defined } + # GL_SIGNED_INTENSITY8_NV { already defined } + # GL_SIGNED_RGB_UNSIGNED_ALPHA_NV { already defined } + # GL_SIGNED_RGB8_UNSIGNED_ALPHA8_NV { already defined } + # GL_HILO16_NV { already defined } + # GL_SIGNED_HILO_NV { already defined } + # GL_SIGNED_HILO16_NV { already defined } + # GL_DSDT8_NV { already defined } + # GL_DSDT8_MAG8_NV { already defined } + # GL_DSDT_MAG_INTENSITY_NV { already defined } + # GL_DSDT8_MAG8_INTENSITY8_NV { already defined } + #***** GL_NV_texture_shader3 *****// + +const + GL_OFFSET_PROJECTIVE_TEXTURE_2D_NV* = 0x00008850 + GL_OFFSET_PROJECTIVE_TEXTURE_2D_SCALE_NV* = 0x00008851 + GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_NV* = 0x00008852 + GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_SCALE_NV* = 0x00008853 + GL_OFFSET_HILO_TEXTURE_2D_NV* = 0x00008854 + GL_OFFSET_HILO_TEXTURE_RECTANGLE_NV* = 0x00008855 + GL_OFFSET_HILO_PROJECTIVE_TEXTURE_2D_NV* = 0x00008856 + GL_OFFSET_HILO_PROJECTIVE_TEXTURE_RECTANGLE_NV* = 0x00008857 + GL_DEPENDENT_HILO_TEXTURE_2D_NV* = 0x00008858 + GL_DEPENDENT_RGB_TEXTURE_3D_NV* = 0x00008859 + GL_DEPENDENT_RGB_TEXTURE_CUBE_MAP_NV* = 0x0000885A + GL_DOT_PRODUCT_PASS_THROUGH_NV* = 0x0000885B + GL_DOT_PRODUCT_TEXTURE_1D_NV* = 0x0000885C + GL_DOT_PRODUCT_AFFINE_DEPTH_REPLACE_NV* = 0x0000885D + GL_HILO8_NV* = 0x0000885E + GL_SIGNED_HILO8_NV* = 0x0000885F + GL_FORCE_BLUE_TO_ONE_NV* = 0x00008860 + #***** GL_NV_vertex_array_range *****// + +const + constGL_VERTEX_ARRAY_RANGE_NV* = 0x0000851D + GL_VERTEX_ARRAY_RANGE_LENGTH_NV* = 0x0000851E + GL_VERTEX_ARRAY_RANGE_VALID_NV* = 0x0000851F + GL_MAX_VERTEX_ARRAY_RANGE_ELEMENT_NV* = 0x00008520 + GL_VERTEX_ARRAY_RANGE_POINTER_NV* = 0x00008521 + +proc glVertexArrayRangeNV*(len: TGLsizei, pointer: PGLvoid){.dynlib: dllname, + importc: "glVertexArrayRangeNV".} +proc glFlushVertexArrayRangeNV*(){.dynlib: dllname, + importc: "glFlushVertexArrayRangeNV".} + #***** GL_NV_vertex_array_range2 *****// +const + GL_VERTEX_ARRAY_RANGE_WITHOUT_FLUSH_NV* = 0x00008533 + #***** GL_NV_vertex_program *****// + +const + GL_VERTEX_PROGRAM_NV* = 0x00008620 + GL_VERTEX_PROGRAM_POINT_SIZE_NV* = 0x00008642 + GL_VERTEX_PROGRAM_TWO_SIDE_NV* = 0x00008643 + GL_VERTEX_STATE_PROGRAM_NV* = 0x00008621 + GL_ATTRIB_ARRAY_SIZE_NV* = 0x00008623 + GL_ATTRIB_ARRAY_STRIDE_NV* = 0x00008624 + GL_ATTRIB_ARRAY_TYPE_NV* = 0x00008625 + GL_CURRENT_ATTRIB_NV* = 0x00008626 + GL_PROGRAM_PARAMETER_NV* = 0x00008644 + GL_ATTRIB_ARRAY_POINTER_NV* = 0x00008645 + GL_PROGRAM_TARGET_NV* = 0x00008646 + GL_PROGRAM_LENGTH_NV* = 0x00008627 + GL_PROGRAM_RESIDENT_NV* = 0x00008647 + GL_PROGRAM_STRING_NV* = 0x00008628 + constGL_TRACK_MATRIX_NV* = 0x00008648 + GL_TRACK_MATRIX_TRANSFORM_NV* = 0x00008649 + GL_MAX_TRACK_MATRIX_STACK_DEPTH_NV* = 0x0000862E + GL_MAX_TRACK_MATRICES_NV* = 0x0000862F + GL_CURRENT_MATRIX_STACK_DEPTH_NV* = 0x00008640 + GL_CURRENT_MATRIX_NV* = 0x00008641 + GL_VERTEX_PROGRAM_BINDING_NV* = 0x0000864A + GL_PROGRAM_ERROR_POSITION_NV* = 0x0000864B + GL_MODELVIEW_PROJECTION_NV* = 0x00008629 + GL_MATRIX0_NV* = 0x00008630 + GL_MATRIX1_NV* = 0x00008631 + GL_MATRIX2_NV* = 0x00008632 + GL_MATRIX3_NV* = 0x00008633 + GL_MATRIX4_NV* = 0x00008634 + GL_MATRIX5_NV* = 0x00008635 + GL_MATRIX6_NV* = 0x00008636 + GL_MATRIX7_NV* = 0x00008637 + GL_IDENTITY_NV* = 0x0000862A + GL_INVERSE_NV* = 0x0000862B + GL_TRANSPOSE_NV* = 0x0000862C + GL_INVERSE_TRANSPOSE_NV* = 0x0000862D + GL_VERTEX_ATTRIB_ARRAY0_NV* = 0x00008650 + GL_VERTEX_ATTRIB_ARRAY1_NV* = 0x00008651 + GL_VERTEX_ATTRIB_ARRAY2_NV* = 0x00008652 + GL_VERTEX_ATTRIB_ARRAY3_NV* = 0x00008653 + GL_VERTEX_ATTRIB_ARRAY4_NV* = 0x00008654 + GL_VERTEX_ATTRIB_ARRAY5_NV* = 0x00008655 + GL_VERTEX_ATTRIB_ARRAY6_NV* = 0x00008656 + GL_VERTEX_ATTRIB_ARRAY7_NV* = 0x00008657 + GL_VERTEX_ATTRIB_ARRAY8_NV* = 0x00008658 + GL_VERTEX_ATTRIB_ARRAY9_NV* = 0x00008659 + GL_VERTEX_ATTRIB_ARRAY10_NV* = 0x0000865A + GL_VERTEX_ATTRIB_ARRAY11_NV* = 0x0000865B + GL_VERTEX_ATTRIB_ARRAY12_NV* = 0x0000865C + GL_VERTEX_ATTRIB_ARRAY13_NV* = 0x0000865D + GL_VERTEX_ATTRIB_ARRAY14_NV* = 0x0000865E + GL_VERTEX_ATTRIB_ARRAY15_NV* = 0x0000865F + GL_MAP1_VERTEX_ATTRIB0_4_NV* = 0x00008660 + GL_MAP1_VERTEX_ATTRIB1_4_NV* = 0x00008661 + GL_MAP1_VERTEX_ATTRIB2_4_NV* = 0x00008662 + GL_MAP1_VERTEX_ATTRIB3_4_NV* = 0x00008663 + GL_MAP1_VERTEX_ATTRIB4_4_NV* = 0x00008664 + GL_MAP1_VERTEX_ATTRIB5_4_NV* = 0x00008665 + GL_MAP1_VERTEX_ATTRIB6_4_NV* = 0x00008666 + GL_MAP1_VERTEX_ATTRIB7_4_NV* = 0x00008667 + GL_MAP1_VERTEX_ATTRIB8_4_NV* = 0x00008668 + GL_MAP1_VERTEX_ATTRIB9_4_NV* = 0x00008669 + GL_MAP1_VERTEX_ATTRIB10_4_NV* = 0x0000866A + GL_MAP1_VERTEX_ATTRIB11_4_NV* = 0x0000866B + GL_MAP1_VERTEX_ATTRIB12_4_NV* = 0x0000866C + GL_MAP1_VERTEX_ATTRIB13_4_NV* = 0x0000866D + GL_MAP1_VERTEX_ATTRIB14_4_NV* = 0x0000866E + GL_MAP1_VERTEX_ATTRIB15_4_NV* = 0x0000866F + GL_MAP2_VERTEX_ATTRIB0_4_NV* = 0x00008670 + GL_MAP2_VERTEX_ATTRIB1_4_NV* = 0x00008671 + GL_MAP2_VERTEX_ATTRIB2_4_NV* = 0x00008672 + GL_MAP2_VERTEX_ATTRIB3_4_NV* = 0x00008673 + GL_MAP2_VERTEX_ATTRIB4_4_NV* = 0x00008674 + GL_MAP2_VERTEX_ATTRIB5_4_NV* = 0x00008675 + GL_MAP2_VERTEX_ATTRIB6_4_NV* = 0x00008676 + GL_MAP2_VERTEX_ATTRIB7_4_NV* = 0x00008677 + GL_MAP2_VERTEX_ATTRIB8_4_NV* = 0x00008678 + GL_MAP2_VERTEX_ATTRIB9_4_NV* = 0x00008679 + GL_MAP2_VERTEX_ATTRIB10_4_NV* = 0x0000867A + GL_MAP2_VERTEX_ATTRIB11_4_NV* = 0x0000867B + GL_MAP2_VERTEX_ATTRIB12_4_NV* = 0x0000867C + GL_MAP2_VERTEX_ATTRIB13_4_NV* = 0x0000867D + GL_MAP2_VERTEX_ATTRIB14_4_NV* = 0x0000867E + GL_MAP2_VERTEX_ATTRIB15_4_NV* = 0x0000867F + +proc glBindProgramNV*(target: TGLenum, id: TGLuint){.dynlib: dllname, + importc: "glBindProgramNV".} +proc glDeleteProgramsNV*(n: TGLsizei, ids: PGLuint){.dynlib: dllname, + importc: "glDeleteProgramsNV".} +proc glExecuteProgramNV*(target: TGLenum, id: TGLuint, params: PGLfloat){. + dynlib: dllname, importc: "glExecuteProgramNV".} +proc glGenProgramsNV*(n: TGLsizei, ids: PGLuint){.dynlib: dllname, + importc: "glGenProgramsNV".} +proc glAreProgramsResidentNV*(n: TGLsizei, ids: PGLuint, residences: PGLboolean): TGLboolean{. + dynlib: dllname, importc: "glAreProgramsResidentNV".} +proc glRequestResidentProgramsNV*(n: TGLsizei, ids: PGLuint){.dynlib: dllname, + importc: "glRequestResidentProgramsNV".} +proc glGetProgramParameterfvNV*(target: TGLenum, index: TGLuint, pname: TGLenum, + params: PGLfloat){.dynlib: dllname, + importc: "glGetProgramParameterfvNV".} +proc glGetProgramParameterdvNV*(target: TGLenum, index: TGLuint, pname: TGLenum, + params: PGLdouble){.dynlib: dllname, + importc: "glGetProgramParameterdvNV".} +proc glGetProgramivNV*(id: TGLuint, pname: TGLenum, params: PGLint){. + dynlib: dllname, importc: "glGetProgramivNV".} +proc glGetProgramStringNV*(id: TGLuint, pname: TGLenum, theProgram: PGLubyte){. + dynlib: dllname, importc: "glGetProgramStringNV".} +proc glGetTrackMatrixivNV*(target: TGLenum, address: TGLuint, pname: TGLenum, + params: PGLint){.dynlib: dllname, + importc: "glGetTrackMatrixivNV".} +proc glGetVertexAttribdvNV*(index: TGLuint, pname: TGLenum, params: PGLdouble){. + dynlib: dllname, importc: "glGetVertexAttribdvNV".} +proc glGetVertexAttribfvNV*(index: TGLuint, pname: TGLenum, params: PGLfloat){. + dynlib: dllname, importc: "glGetVertexAttribfvNV".} +proc glGetVertexAttribivNV*(index: TGLuint, pname: TGLenum, params: PGLint){. + dynlib: dllname, importc: "glGetVertexAttribivNV".} +proc glGetVertexAttribPointervNV*(index: TGLuint, pname: TGLenum, + pointer: PGLvoid){.dynlib: dllname, + importc: "glGetVertexAttribPointervNV".} +proc glIsProgramNV*(id: TGLuint): TGLboolean{.dynlib: dllname, + importc: "glIsProgramNV".} +proc glLoadProgramNV*(target: TGLenum, id: TGLuint, length: TGLsizei, + theProgram: PGLubyte){.dynlib: dllname, + importc: "glLoadProgramNV".} +proc glProgramParameter4fNV*(target: TGLenum, index: TGLuint, x: TGLfloat, + y: TGLfloat, z: TGLfloat, w: TGLfloat){. + dynlib: dllname, importc: "glProgramParameter4fNV".} +proc glProgramParameter4fvNV*(target: TGLenum, index: TGLuint, params: PGLfloat){. + dynlib: dllname, importc: "glProgramParameter4fvNV".} +proc glProgramParameters4dvNV*(target: TGLenum, index: TGLuint, num: TGLuint, + params: PGLdouble){.dynlib: dllname, + importc: "glProgramParameters4dvNV".} +proc glProgramParameters4fvNV*(target: TGLenum, index: TGLuint, num: TGLuint, + params: PGLfloat){.dynlib: dllname, + importc: "glProgramParameters4fvNV".} +proc glTrackMatrixNV*(target: TGLenum, address: TGLuint, matrix: TGLenum, + transform: TGLenum){.dynlib: dllname, + importc: "glTrackMatrixNV".} +proc glVertexAttribPointerNV*(index: TGLuint, size: TGLint, thetype: TGLenum, + stride: TGLsizei, pointer: PGLvoid){. + dynlib: dllname, importc: "glVertexAttribPointerNV".} +proc glVertexAttrib1sNV*(index: TGLuint, x: TGLshort){.dynlib: dllname, + importc: "glVertexAttrib1sNV".} +proc glVertexAttrib1fNV*(index: TGLuint, x: TGLfloat){.dynlib: dllname, + importc: "glVertexAttrib1fNV".} +proc glVertexAttrib1dNV*(index: TGLuint, x: TGLdouble){.dynlib: dllname, + importc: "glVertexAttrib1dNV".} +proc glVertexAttrib2sNV*(index: TGLuint, x: TGLshort, y: TGLshort){. + dynlib: dllname, importc: "glVertexAttrib2sNV".} +proc glVertexAttrib2fNV*(index: TGLuint, x: TGLfloat, y: TGLfloat){. + dynlib: dllname, importc: "glVertexAttrib2fNV".} +proc glVertexAttrib2dNV*(index: TGLuint, x: TGLdouble, y: TGLdouble){. + dynlib: dllname, importc: "glVertexAttrib2dNV".} +proc glVertexAttrib3sNV*(index: TGLuint, x: TGLshort, y: TGLshort, z: TGLshort){. + dynlib: dllname, importc: "glVertexAttrib3sNV".} +proc glVertexAttrib3fNV*(index: TGLuint, x: TGLfloat, y: TGLfloat, z: TGLfloat){. + dynlib: dllname, importc: "glVertexAttrib3fNV".} +proc glVertexAttrib3dNV*(index: TGLuint, x: TGLdouble, y: TGLdouble, + z: TGLdouble){.dynlib: dllname, + importc: "glVertexAttrib3dNV".} +proc glVertexAttrib4sNV*(index: TGLuint, x: TGLshort, y: TGLshort, z: TGLshort, + w: TGLshort){.dynlib: dllname, + importc: "glVertexAttrib4sNV".} +proc glVertexAttrib4fNV*(index: TGLuint, x: TGLfloat, y: TGLfloat, z: TGLfloat, + w: TGLfloat){.dynlib: dllname, + importc: "glVertexAttrib4fNV".} +proc glVertexAttrib4dNV*(index: TGLuint, x: TGLdouble, y: TGLdouble, + z: TGLdouble, w: TGLdouble){.dynlib: dllname, + importc: "glVertexAttrib4dNV".} +proc glVertexAttrib4ubNV*(index: TGLuint, x: TGLubyte, y: TGLubyte, z: TGLubyte, + w: TGLubyte){.dynlib: dllname, + importc: "glVertexAttrib4ubNV".} +proc glVertexAttrib1svNV*(index: TGLuint, v: PGLshort){.dynlib: dllname, + importc: "glVertexAttrib1svNV".} +proc glVertexAttrib1fvNV*(index: TGLuint, v: PGLfloat){.dynlib: dllname, + importc: "glVertexAttrib1fvNV".} +proc glVertexAttrib1dvNV*(index: TGLuint, v: PGLdouble){.dynlib: dllname, + importc: "glVertexAttrib1dvNV".} +proc glVertexAttrib2svNV*(index: TGLuint, v: PGLshort){.dynlib: dllname, + importc: "glVertexAttrib2svNV".} +proc glVertexAttrib2fvNV*(index: TGLuint, v: PGLfloat){.dynlib: dllname, + importc: "glVertexAttrib2fvNV".} +proc glVertexAttrib2dvNV*(index: TGLuint, v: PGLdouble){.dynlib: dllname, + importc: "glVertexAttrib2dvNV".} +proc glVertexAttrib3svNV*(index: TGLuint, v: PGLshort){.dynlib: dllname, + importc: "glVertexAttrib3svNV".} +proc glVertexAttrib3fvNV*(index: TGLuint, v: PGLfloat){.dynlib: dllname, + importc: "glVertexAttrib3fvNV".} +proc glVertexAttrib3dvNV*(index: TGLuint, v: PGLdouble){.dynlib: dllname, + importc: "glVertexAttrib3dvNV".} +proc glVertexAttrib4svNV*(index: TGLuint, v: PGLshort){.dynlib: dllname, + importc: "glVertexAttrib4svNV".} +proc glVertexAttrib4fvNV*(index: TGLuint, v: PGLfloat){.dynlib: dllname, + importc: "glVertexAttrib4fvNV".} +proc glVertexAttrib4dvNV*(index: TGLuint, v: PGLdouble){.dynlib: dllname, + importc: "glVertexAttrib4dvNV".} +proc glVertexAttrib4ubvNV*(index: TGLuint, v: PGLubyte){.dynlib: dllname, + importc: "glVertexAttrib4ubvNV".} +proc glVertexAttribs1svNV*(index: TGLuint, n: TGLsizei, v: PGLshort){. + dynlib: dllname, importc: "glVertexAttribs1svNV".} +proc glVertexAttribs1fvNV*(index: TGLuint, n: TGLsizei, v: PGLfloat){. + dynlib: dllname, importc: "glVertexAttribs1fvNV".} +proc glVertexAttribs1dvNV*(index: TGLuint, n: TGLsizei, v: PGLdouble){. + dynlib: dllname, importc: "glVertexAttribs1dvNV".} +proc glVertexAttribs2svNV*(index: TGLuint, n: TGLsizei, v: PGLshort){. + dynlib: dllname, importc: "glVertexAttribs2svNV".} +proc glVertexAttribs2fvNV*(index: TGLuint, n: TGLsizei, v: PGLfloat){. + dynlib: dllname, importc: "glVertexAttribs2fvNV".} +proc glVertexAttribs2dvNV*(index: TGLuint, n: TGLsizei, v: PGLdouble){. + dynlib: dllname, importc: "glVertexAttribs2dvNV".} +proc glVertexAttribs3svNV*(index: TGLuint, n: TGLsizei, v: PGLshort){. + dynlib: dllname, importc: "glVertexAttribs3svNV".} +proc glVertexAttribs3fvNV*(index: TGLuint, n: TGLsizei, v: PGLfloat){. + dynlib: dllname, importc: "glVertexAttribs3fvNV".} +proc glVertexAttribs3dvNV*(index: TGLuint, n: TGLsizei, v: PGLdouble){. + dynlib: dllname, importc: "glVertexAttribs3dvNV".} +proc glVertexAttribs4svNV*(index: TGLuint, n: TGLsizei, v: PGLshort){. + dynlib: dllname, importc: "glVertexAttribs4svNV".} +proc glVertexAttribs4fvNV*(index: TGLuint, n: TGLsizei, v: PGLfloat){. + dynlib: dllname, importc: "glVertexAttribs4fvNV".} +proc glVertexAttribs4dvNV*(index: TGLuint, n: TGLsizei, v: PGLdouble){. + dynlib: dllname, importc: "glVertexAttribs4dvNV".} +proc glVertexAttribs4ubvNV*(index: TGLuint, n: TGLsizei, v: PGLubyte){. + dynlib: dllname, importc: "glVertexAttribs4ubvNV".} + #***** GL_NV_vertex_program1_1 *****// + #***** GL_ATI_element_array *****// +const + GL_ELEMENT_ARRAY_ATI* = 0x00008768 + GL_ELEMENT_ARRAY_TYPE_ATI* = 0x00008769 + GL_ELEMENT_ARRAY_POINTER_ATI* = 0x0000876A + +proc glElementPointerATI*(thetype: TGLenum, pointer: PGLvoid){.dynlib: dllname, + importc: "glElementPointerATI".} +proc glDrawElementArrayATI*(mode: TGLenum, count: TGLsizei){.dynlib: dllname, + importc: "glDrawElementArrayATI".} +proc glDrawRangeElementArrayATI*(mode: TGLenum, start: TGLuint, theend: TGLuint, + count: TGLsizei){.dynlib: dllname, + importc: "glDrawRangeElementArrayATI".} + #***** GL_ATI_envmap_bumpmap *****// +const + GL_BUMP_ROT_MATRIX_ATI* = 0x00008775 + GL_BUMP_ROT_MATRIX_SIZE_ATI* = 0x00008776 + GL_BUMP_NUM_TEX_UNITS_ATI* = 0x00008777 + GL_BUMP_TEX_UNITS_ATI* = 0x00008778 + GL_DUDV_ATI* = 0x00008779 + GL_DU8DV8_ATI* = 0x0000877A + GL_BUMP_ENVMAP_ATI* = 0x0000877B + GL_BUMP_TARGET_ATI* = 0x0000877C + +proc glTexBumpParameterivATI*(pname: TGLenum, param: PGLint){.dynlib: dllname, + importc: "glTexBumpParameterivATI".} +proc glTexBumpParameterfvATI*(pname: TGLenum, param: PGLfloat){.dynlib: dllname, + importc: "glTexBumpParameterfvATI".} +proc glGetTexBumpParameterivATI*(pname: TGLenum, param: PGLint){. + dynlib: dllname, importc: "glGetTexBumpParameterivATI".} +proc glGetTexBumpParameterfvATI*(pname: TGLenum, param: PGLfloat){. + dynlib: dllname, importc: "glGetTexBumpParameterfvATI".} + #***** GL_ATI_fragment_shader *****// +const + GL_FRAGMENT_SHADER_ATI* = 0x00008920 + GL_REG_0_ATI* = 0x00008921 + GL_REG_1_ATI* = 0x00008922 + GL_REG_2_ATI* = 0x00008923 + GL_REG_3_ATI* = 0x00008924 + GL_REG_4_ATI* = 0x00008925 + GL_REG_5_ATI* = 0x00008926 + GL_CON_0_ATI* = 0x00008941 + GL_CON_1_ATI* = 0x00008942 + GL_CON_2_ATI* = 0x00008943 + GL_CON_3_ATI* = 0x00008944 + GL_CON_4_ATI* = 0x00008945 + GL_CON_5_ATI* = 0x00008946 + GL_CON_6_ATI* = 0x00008947 + GL_CON_7_ATI* = 0x00008948 + GL_MOV_ATI* = 0x00008961 + GL_ADD_ATI* = 0x00008963 + GL_MUL_ATI* = 0x00008964 + GL_SUB_ATI* = 0x00008965 + GL_DOT3_ATI* = 0x00008966 + GL_DOT4_ATI* = 0x00008967 + GL_MAD_ATI* = 0x00008968 + GL_LERP_ATI* = 0x00008969 + GL_CND_ATI* = 0x0000896A + GL_CND0_ATI* = 0x0000896B + GL_DOT2_ADD_ATI* = 0x0000896C + GL_SECONDARY_INTERPOLATOR_ATI* = 0x0000896D + GL_SWIZZLE_STR_ATI* = 0x00008976 + GL_SWIZZLE_STQ_ATI* = 0x00008977 + GL_SWIZZLE_STR_DR_ATI* = 0x00008978 + GL_SWIZZLE_STQ_DQ_ATI* = 0x00008979 + GL_RED_BIT_ATI* = 0x00000001 + GL_GREEN_BIT_ATI* = 0x00000002 + GL_BLUE_BIT_ATI* = 0x00000004 + GL_2X_BIT_ATI* = 0x00000001 + GL_4X_BIT_ATI* = 0x00000002 + GL_8X_BIT_ATI* = 0x00000004 + GL_HALF_BIT_ATI* = 0x00000008 + GL_QUARTER_BIT_ATI* = 0x00000010 + GL_EIGHTH_BIT_ATI* = 0x00000020 + GL_SATURATE_BIT_ATI* = 0x00000040 # GL_2X_BIT_ATI { already defined } + GL_COMP_BIT_ATI* = 0x00000002 + GL_NEGATE_BIT_ATI* = 0x00000004 + GL_BIAS_BIT_ATI* = 0x00000008 + +proc glGenFragmentShadersATI*(range: TGLuint): TGLuint{.dynlib: dllname, + importc: "glGenFragmentShadersATI".} +proc glBindFragmentShaderATI*(id: TGLuint){.dynlib: dllname, + importc: "glBindFragmentShaderATI".} +proc glDeleteFragmentShaderATI*(id: TGLuint){.dynlib: dllname, + importc: "glDeleteFragmentShaderATI".} +proc glBeginFragmentShaderATI*(){.dynlib: dllname, + importc: "glBeginFragmentShaderATI".} +proc glEndFragmentShaderATI*(){.dynlib: dllname, + importc: "glEndFragmentShaderATI".} +proc glPassTexCoordATI*(dst: TGLuint, coord: TGLuint, swizzle: TGLenum){. + dynlib: dllname, importc: "glPassTexCoordATI".} +proc glSampleMapATI*(dst: TGLuint, interp: TGLuint, swizzle: TGLenum){. + dynlib: dllname, importc: "glSampleMapATI".} +proc glColorFragmentOp1ATI*(op: TGLenum, dst: TGLuint, dstMask: TGLuint, + dstMod: TGLuint, arg1: TGLuint, arg1Rep: TGLuint, + arg1Mod: TGLuint){.dynlib: dllname, + importc: "glColorFragmentOp1ATI".} +proc glColorFragmentOp2ATI*(op: TGLenum, dst: TGLuint, dstMask: TGLuint, + dstMod: TGLuint, arg1: TGLuint, arg1Rep: TGLuint, + arg1Mod: TGLuint, arg2: TGLuint, arg2Rep: TGLuint, + arg2Mod: TGLuint){.dynlib: dllname, + importc: "glColorFragmentOp2ATI".} +proc glColorFragmentOp3ATI*(op: TGLenum, dst: TGLuint, dstMask: TGLuint, + dstMod: TGLuint, arg1: TGLuint, arg1Rep: TGLuint, + arg1Mod: TGLuint, arg2: TGLuint, arg2Rep: TGLuint, + arg2Mod: TGLuint, arg3: TGLuint, arg3Rep: TGLuint, + arg3Mod: TGLuint){.dynlib: dllname, + importc: "glColorFragmentOp3ATI".} +proc glAlphaFragmentOp1ATI*(op: TGLenum, dst: TGLuint, dstMod: TGLuint, + arg1: TGLuint, arg1Rep: TGLuint, arg1Mod: TGLuint){. + dynlib: dllname, importc: "glAlphaFragmentOp1ATI".} +proc glAlphaFragmentOp2ATI*(op: TGLenum, dst: TGLuint, dstMod: TGLuint, + arg1: TGLuint, arg1Rep: TGLuint, arg1Mod: TGLuint, + arg2: TGLuint, arg2Rep: TGLuint, arg2Mod: TGLuint){. + dynlib: dllname, importc: "glAlphaFragmentOp2ATI".} +proc glAlphaFragmentOp3ATI*(op: TGLenum, dst: TGLuint, dstMod: TGLuint, + arg1: TGLuint, arg1Rep: TGLuint, arg1Mod: TGLuint, + arg2: TGLuint, arg2Rep: TGLuint, arg2Mod: TGLuint, + arg3: TGLuint, arg3Rep: TGLuint, arg3Mod: TGLuint){. + dynlib: dllname, importc: "glAlphaFragmentOp3ATI".} +proc glSetFragmentShaderConstantATI*(dst: TGLuint, value: PGLfloat){. + dynlib: dllname, importc: "glSetFragmentShaderConstantATI".} + #***** GL_ATI_pn_triangles *****// +const + GL_PN_TRIANGLES_ATI* = 0x000087F0 + GL_MAX_PN_TRIANGLES_TESSELATION_LEVEL_ATI* = 0x000087F1 + GL_PN_TRIANGLES_POINT_MODE_ATI* = 0x000087F2 + GL_PN_TRIANGLES_NORMAL_MODE_ATI* = 0x000087F3 + GL_PN_TRIANGLES_TESSELATION_LEVEL_ATI* = 0x000087F4 + GL_PN_TRIANGLES_POINT_MODE_LINEAR_ATI* = 0x000087F5 + GL_PN_TRIANGLES_POINT_MODE_CUBIC_ATI* = 0x000087F6 + GL_PN_TRIANGLES_NORMAL_MODE_LINEAR_ATI* = 0x000087F7 + GL_PN_TRIANGLES_NORMAL_MODE_QUADRATIC_ATI* = 0x000087F8 + +proc glPNTrianglesiATI*(pname: TGLenum, param: TGLint){.dynlib: dllname, + importc: "glPNTrianglesiATI".} +proc glPNTrianglesfATI*(pname: TGLenum, param: TGLfloat){.dynlib: dllname, + importc: "glPNTrianglesfATI".} + #***** GL_ATI_texture_mirror_once *****// +const + GL_MIRROR_CLAMP_ATI* = 0x00008742 + GL_MIRROR_CLAMP_TO_EDGE_ATI* = 0x00008743 + #***** GL_ATI_vertex_array_object *****// + +const + GL_STATIC_ATI* = 0x00008760 + GL_DYNAMIC_ATI* = 0x00008761 + GL_PRESERVE_ATI* = 0x00008762 + GL_DISCARD_ATI* = 0x00008763 + GL_OBJECT_BUFFER_SIZE_ATI* = 0x00008764 + GL_OBJECT_BUFFER_USAGE_ATI* = 0x00008765 + GL_ARRAY_OBJECT_BUFFER_ATI* = 0x00008766 + GL_ARRAY_OBJECT_OFFSET_ATI* = 0x00008767 + +proc glNewObjectBufferATI*(size: TGLsizei, pointer: PGLvoid, usage: TGLenum): TGLuint{. + dynlib: dllname, importc: "glNewObjectBufferATI".} +proc glIsObjectBufferATI*(buffer: TGLuint): TGLboolean{.dynlib: dllname, + importc: "glIsObjectBufferATI".} +proc glUpdateObjectBufferATI*(buffer: TGLuint, offset: TGLuint, size: TGLsizei, + pointer: PGLvoid, preserve: TGLenum){. + dynlib: dllname, importc: "glUpdateObjectBufferATI".} +proc glGetObjectBufferfvATI*(buffer: TGLuint, pname: TGLenum, params: PGLfloat){. + dynlib: dllname, importc: "glGetObjectBufferfvATI".} +proc glGetObjectBufferivATI*(buffer: TGLuint, pname: TGLenum, params: PGLint){. + dynlib: dllname, importc: "glGetObjectBufferivATI".} +proc glDeleteObjectBufferATI*(buffer: TGLuint){.dynlib: dllname, + importc: "glDeleteObjectBufferATI".} +proc glArrayObjectATI*(thearray: TGLenum, size: TGLint, thetype: TGLenum, + stride: TGLsizei, buffer: TGLuint, offset: TGLuint){. + dynlib: dllname, importc: "glArrayObjectATI".} +proc glGetArrayObjectfvATI*(thearray: TGLenum, pname: TGLenum, params: PGLfloat){. + dynlib: dllname, importc: "glGetArrayObjectfvATI".} +proc glGetArrayObjectivATI*(thearray: TGLenum, pname: TGLenum, params: PGLint){. + dynlib: dllname, importc: "glGetArrayObjectivATI".} +proc glVariantArrayObjectATI*(id: TGLuint, thetype: TGLenum, stride: TGLsizei, + buffer: TGLuint, offset: TGLuint){. + dynlib: dllname, importc: "glVariantArrayObjectATI".} +proc glGetVariantArrayObjectfvATI*(id: TGLuint, pname: TGLenum, params: PGLfloat){. + dynlib: dllname, importc: "glGetVariantArrayObjectfvATI".} +proc glGetVariantArrayObjectivATI*(id: TGLuint, pname: TGLenum, params: PGLint){. + dynlib: dllname, importc: "glGetVariantArrayObjectivATI".} + #***** GL_ATI_vertex_streams *****// +const + GL_MAX_VERTEX_STREAMS_ATI* = 0x0000876B + GL_VERTEX_STREAM0_ATI* = 0x0000876C + GL_VERTEX_STREAM1_ATI* = 0x0000876D + GL_VERTEX_STREAM2_ATI* = 0x0000876E + GL_VERTEX_STREAM3_ATI* = 0x0000876F + GL_VERTEX_STREAM4_ATI* = 0x00008770 + GL_VERTEX_STREAM5_ATI* = 0x00008771 + GL_VERTEX_STREAM6_ATI* = 0x00008772 + GL_VERTEX_STREAM7_ATI* = 0x00008773 + GL_VERTEX_SOURCE_ATI* = 0x00008774 + +proc glVertexStream1s*(stream: TGLenum, coords: TGLshort){.dynlib: dllname, + importc: "glVertexStream1s".} +proc glVertexStream1i*(stream: TGLenum, coords: TGLint){.dynlib: dllname, + importc: "glVertexStream1i".} +proc glVertexStream1f*(stream: TGLenum, coords: TGLfloat){.dynlib: dllname, + importc: "glVertexStream1f".} +proc glVertexStream1d*(stream: TGLenum, coords: TGLdouble){.dynlib: dllname, + importc: "glVertexStream1d".} +proc glVertexStream1sv*(stream: TGLenum, coords: TGLshort){.dynlib: dllname, + importc: "glVertexStream1sv".} +proc glVertexStream1iv*(stream: TGLenum, coords: TGLint){.dynlib: dllname, + importc: "glVertexStream1iv".} +proc glVertexStream1fv*(stream: TGLenum, coords: TGLfloat){.dynlib: dllname, + importc: "glVertexStream1fv".} +proc glVertexStream1dv*(stream: TGLenum, coords: TGLdouble){.dynlib: dllname, + importc: "glVertexStream1dv".} +proc glVertexStream2s*(stream: TGLenum, coords: TGLshort){.dynlib: dllname, + importc: "glVertexStream2s".} +proc glVertexStream2i*(stream: TGLenum, coords: TGLint){.dynlib: dllname, + importc: "glVertexStream2i".} +proc glVertexStream2f*(stream: TGLenum, coords: TGLfloat){.dynlib: dllname, + importc: "glVertexStream2f".} +proc glVertexStream2d*(stream: TGLenum, coords: TGLdouble){.dynlib: dllname, + importc: "glVertexStream2d".} +proc glVertexStream2sv*(stream: TGLenum, coords: TGLshort){.dynlib: dllname, + importc: "glVertexStream2sv".} +proc glVertexStream2iv*(stream: TGLenum, coords: TGLint){.dynlib: dllname, + importc: "glVertexStream2iv".} +proc glVertexStream2fv*(stream: TGLenum, coords: TGLfloat){.dynlib: dllname, + importc: "glVertexStream2fv".} +proc glVertexStream2dv*(stream: TGLenum, coords: TGLdouble){.dynlib: dllname, + importc: "glVertexStream2dv".} +proc glVertexStream3s*(stream: TGLenum, coords: TGLshort){.dynlib: dllname, + importc: "glVertexStream3s".} +proc glVertexStream3i*(stream: TGLenum, coords: TGLint){.dynlib: dllname, + importc: "glVertexStream3i".} +proc glVertexStream3f*(stream: TGLenum, coords: TGLfloat){.dynlib: dllname, + importc: "glVertexStream3f".} +proc glVertexStream3d*(stream: TGLenum, coords: TGLdouble){.dynlib: dllname, + importc: "glVertexStream3d".} +proc glVertexStream3sv*(stream: TGLenum, coords: TGLshort){.dynlib: dllname, + importc: "glVertexStream3sv".} +proc glVertexStream3iv*(stream: TGLenum, coords: TGLint){.dynlib: dllname, + importc: "glVertexStream3iv".} +proc glVertexStream3fv*(stream: TGLenum, coords: TGLfloat){.dynlib: dllname, + importc: "glVertexStream3fv".} +proc glVertexStream3dv*(stream: TGLenum, coords: TGLdouble){.dynlib: dllname, + importc: "glVertexStream3dv".} +proc glVertexStream4s*(stream: TGLenum, coords: TGLshort){.dynlib: dllname, + importc: "glVertexStream4s".} +proc glVertexStream4i*(stream: TGLenum, coords: TGLint){.dynlib: dllname, + importc: "glVertexStream4i".} +proc glVertexStream4f*(stream: TGLenum, coords: TGLfloat){.dynlib: dllname, + importc: "glVertexStream4f".} +proc glVertexStream4d*(stream: TGLenum, coords: TGLdouble){.dynlib: dllname, + importc: "glVertexStream4d".} +proc glVertexStream4sv*(stream: TGLenum, coords: TGLshort){.dynlib: dllname, + importc: "glVertexStream4sv".} +proc glVertexStream4iv*(stream: TGLenum, coords: TGLint){.dynlib: dllname, + importc: "glVertexStream4iv".} +proc glVertexStream4fv*(stream: TGLenum, coords: TGLfloat){.dynlib: dllname, + importc: "glVertexStream4fv".} +proc glVertexStream4dv*(stream: TGLenum, coords: TGLdouble){.dynlib: dllname, + importc: "glVertexStream4dv".} +proc glNormalStream3b*(stream: TGLenum, coords: TGLByte){.dynlib: dllname, + importc: "glNormalStream3b".} +proc glNormalStream3s*(stream: TGLenum, coords: TGLshort){.dynlib: dllname, + importc: "glNormalStream3s".} +proc glNormalStream3i*(stream: TGLenum, coords: TGLint){.dynlib: dllname, + importc: "glNormalStream3i".} +proc glNormalStream3f*(stream: TGLenum, coords: TGLfloat){.dynlib: dllname, + importc: "glNormalStream3f".} +proc glNormalStream3d*(stream: TGLenum, coords: TGLdouble){.dynlib: dllname, + importc: "glNormalStream3d".} +proc glNormalStream3bv*(stream: TGLenum, coords: TGLByte){.dynlib: dllname, + importc: "glNormalStream3bv".} +proc glNormalStream3sv*(stream: TGLenum, coords: TGLshort){.dynlib: dllname, + importc: "glNormalStream3sv".} +proc glNormalStream3iv*(stream: TGLenum, coords: TGLint){.dynlib: dllname, + importc: "glNormalStream3iv".} +proc glNormalStream3fv*(stream: TGLenum, coords: TGLfloat){.dynlib: dllname, + importc: "glNormalStream3fv".} +proc glNormalStream3dv*(stream: TGLenum, coords: TGLdouble){.dynlib: dllname, + importc: "glNormalStream3dv".} +proc glClientActiveVertexStream*(stream: TGLenum){.dynlib: dllname, + importc: "glClientActiveVertexStream".} +proc glVertexBlendEnvi*(pname: TGLenum, param: TGLint){.dynlib: dllname, + importc: "glVertexBlendEnvi".} +proc glVertexBlendEnvf*(pname: TGLenum, param: TGLfloat){.dynlib: dllname, + importc: "glVertexBlendEnvf".} + #***** GL_3DFX_texture_compression_FXT1 *****// +const + GL_COMPRESSED_RGB_FXT1_3DFX* = 0x000086B0 + GL_COMPRESSED_RGBA_FXT1_3DFX* = 0x000086B1 + #***** GL_IBM_cull_vertex *****// + +const + GL_CULL_VERTEX_IBM* = 0x0001928A + #***** GL_IBM_multimode_draw_arrays *****// + +proc glMultiModeDrawArraysIBM*(mode: PGLenum, first: PGLint, count: PGLsizei, + primcount: TGLsizei, modestride: TGLint){. + dynlib: dllname, importc: "glMultiModeDrawArraysIBM".} +proc glMultiModeDrawElementsIBM*(mode: PGLenum, count: PGLsizei, + thetype: TGLenum, indices: PGLvoid, + primcount: TGLsizei, modestride: TGLint){. + dynlib: dllname, importc: "glMultiModeDrawElementsIBM".} + #***** GL_IBM_raster_pos_clip *****// +const + GL_RASTER_POSITION_UNCLIPPED_IBM* = 0x00019262 + #***** GL_IBM_texture_mirrored_repeat *****// + +const + GL_MIRRORED_REPEAT_IBM* = 0x00008370 + #***** GL_IBM_vertex_array_lists *****// + +const + GL_VERTEX_ARRAY_LIST_IBM* = 0x0001929E + GL_NORMAL_ARRAY_LIST_IBM* = 0x0001929F + GL_COLOR_ARRAY_LIST_IBM* = 0x000192A0 + GL_INDEX_ARRAY_LIST_IBM* = 0x000192A1 + GL_TEXTURE_COORD_ARRAY_LIST_IBM* = 0x000192A2 + GL_EDGE_FLAG_ARRAY_LIST_IBM* = 0x000192A3 + GL_FOG_COORDINATE_ARRAY_LIST_IBM* = 0x000192A4 + GL_SECONDARY_COLOR_ARRAY_LIST_IBM* = 0x000192A5 + GL_VERTEX_ARRAY_LIST_STRIDE_IBM* = 0x000192A8 + GL_NORMAL_ARRAY_LIST_STRIDE_IBM* = 0x000192A9 + GL_COLOR_ARRAY_LIST_STRIDE_IBM* = 0x000192AA + GL_INDEX_ARRAY_LIST_STRIDE_IBM* = 0x000192AB + GL_TEXTURE_COORD_ARRAY_LIST_STRIDE_IBM* = 0x000192AC + GL_EDGE_FLAG_ARRAY_LIST_STRIDE_IBM* = 0x000192AD + GL_FOG_COORDINATE_ARRAY_LIST_STRIDE_IBM* = 0x000192AE + GL_SECONDARY_COLOR_ARRAY_LIST_STRIDE_IBM* = 0x000192AF + +proc glColorPointerListIBM*(size: TGLint, thetype: TGLenum, stride: TGLint, + pointer: PGLvoid, ptrstride: TGLint){. + dynlib: dllname, importc: "glColorPointerListIBM".} +proc glSecondaryColorPointerListIBM*(size: TGLint, thetype: TGLenum, + stride: TGLint, pointer: PGLvoid, + ptrstride: TGLint){.dynlib: dllname, + importc: "glSecondaryColorPointerListIBM".} +proc glEdgeFlagPointerListIBM*(stride: TGLint, pointer: PGLboolean, + ptrstride: TGLint){.dynlib: dllname, + importc: "glEdgeFlagPointerListIBM".} +proc glFogCoordPointerListIBM*(thetype: TGLenum, stride: TGLint, + pointer: PGLvoid, ptrstride: TGLint){. + dynlib: dllname, importc: "glFogCoordPointerListIBM".} +proc glNormalPointerListIBM*(thetype: TGLenum, stride: TGLint, pointer: PGLvoid, + ptrstride: TGLint){.dynlib: dllname, + importc: "glNormalPointerListIBM".} +proc glTexCoordPointerListIBM*(size: TGLint, thetype: TGLenum, stride: TGLint, + pointer: PGLvoid, ptrstride: TGLint){. + dynlib: dllname, importc: "glTexCoordPointerListIBM".} +proc glVertexPointerListIBM*(size: TGLint, thetype: TGLenum, stride: TGLint, + pointer: PGLvoid, ptrstride: TGLint){. + dynlib: dllname, importc: "glVertexPointerListIBM".} + #***** GL_MESA_resize_buffers *****// +proc glResizeBuffersMESA*(){.dynlib: dllname, importc: "glResizeBuffersMESA".} + #***** GL_MESA_window_pos *****// +proc glWindowPos2dMESA*(x: TGLdouble, y: TGLdouble){.dynlib: dllname, + importc: "glWindowPos2dMESA".} +proc glWindowPos2fMESA*(x: TGLfloat, y: TGLfloat){.dynlib: dllname, + importc: "glWindowPos2fMESA".} +proc glWindowPos2iMESA*(x: TGLint, y: TGLint){.dynlib: dllname, + importc: "glWindowPos2iMESA".} +proc glWindowPos2sMESA*(x: TGLshort, y: TGLshort){.dynlib: dllname, + importc: "glWindowPos2sMESA".} +proc glWindowPos2ivMESA*(p: PGLint){.dynlib: dllname, + importc: "glWindowPos2ivMESA".} +proc glWindowPos2svMESA*(p: PGLshort){.dynlib: dllname, + importc: "glWindowPos2svMESA".} +proc glWindowPos2fvMESA*(p: PGLfloat){.dynlib: dllname, + importc: "glWindowPos2fvMESA".} +proc glWindowPos2dvMESA*(p: PGLdouble){.dynlib: dllname, + importc: "glWindowPos2dvMESA".} +proc glWindowPos3iMESA*(x: TGLint, y: TGLint, z: TGLint){.dynlib: dllname, + importc: "glWindowPos3iMESA".} +proc glWindowPos3sMESA*(x: TGLshort, y: TGLshort, z: TGLshort){.dynlib: dllname, + importc: "glWindowPos3sMESA".} +proc glWindowPos3fMESA*(x: TGLfloat, y: TGLfloat, z: TGLfloat){.dynlib: dllname, + importc: "glWindowPos3fMESA".} +proc glWindowPos3dMESA*(x: TGLdouble, y: TGLdouble, z: TGLdouble){. + dynlib: dllname, importc: "glWindowPos3dMESA".} +proc glWindowPos3ivMESA*(p: PGLint){.dynlib: dllname, + importc: "glWindowPos3ivMESA".} +proc glWindowPos3svMESA*(p: PGLshort){.dynlib: dllname, + importc: "glWindowPos3svMESA".} +proc glWindowPos3fvMESA*(p: PGLfloat){.dynlib: dllname, + importc: "glWindowPos3fvMESA".} +proc glWindowPos3dvMESA*(p: PGLdouble){.dynlib: dllname, + importc: "glWindowPos3dvMESA".} +proc glWindowPos4iMESA*(x: TGLint, y: TGLint, z: TGLint, w: TGLint){. + dynlib: dllname, importc: "glWindowPos4iMESA".} +proc glWindowPos4sMESA*(x: TGLshort, y: TGLshort, z: TGLshort, w: TGLshort){. + dynlib: dllname, importc: "glWindowPos4sMESA".} +proc glWindowPos4fMESA*(x: TGLfloat, y: TGLfloat, z: TGLfloat, w: TGLfloat){. + dynlib: dllname, importc: "glWindowPos4fMESA".} +proc glWindowPos4dMESA*(x: TGLdouble, y: TGLdouble, z: TGLdouble, w: TGLdouble){. + dynlib: dllname, importc: "glWindowPos4dMESA".} +proc glWindowPos4ivMESA*(p: PGLint){.dynlib: dllname, + importc: "glWindowPos4ivMESA".} +proc glWindowPos4svMESA*(p: PGLshort){.dynlib: dllname, + importc: "glWindowPos4svMESA".} +proc glWindowPos4fvMESA*(p: PGLfloat){.dynlib: dllname, + importc: "glWindowPos4fvMESA".} +proc glWindowPos4dvMESA*(p: PGLdouble){.dynlib: dllname, + importc: "glWindowPos4dvMESA".} + #***** GL_OML_interlace *****// +const + GL_INTERLACE_OML* = 0x00008980 + GL_INTERLACE_READ_OML* = 0x00008981 + #***** GL_OML_resample *****// + +const + GL_PACK_RESAMPLE_OML* = 0x00008984 + GL_UNPACK_RESAMPLE_OML* = 0x00008985 + GL_RESAMPLE_REPLICATE_OML* = 0x00008986 + GL_RESAMPLE_ZERO_FILL_OML* = 0x00008987 + GL_RESAMPLE_AVERAGE_OML* = 0x00008988 + GL_RESAMPLE_DECIMATE_OML* = 0x00008989 # GL_RESAMPLE_AVERAGE_OML { already defined } + #***** GL_OML_subsample *****// + +const + GL_FORMAT_SUBSAMPLE_24_24_OML* = 0x00008982 + GL_FORMAT_SUBSAMPLE_244_244_OML* = 0x00008983 + #***** GL_SGIS_generate_mipmap *****// + +const + GL_GENERATE_MIPMAP_SGIS* = 0x00008191 + GL_GENERATE_MIPMAP_HINT_SGIS* = 0x00008192 + #***** GL_SGIS_multisample *****// + +const + GLX_SAMPLE_BUFFERS_SGIS* = 0x000186A0 + GLX_SAMPLES_SGIS* = 0x000186A1 + GL_MULTISAMPLE_SGIS* = 0x0000809D + GL_SAMPLE_ALPHA_TO_MASK_SGIS* = 0x0000809E + GL_SAMPLE_ALPHA_TO_ONE_SGIS* = 0x0000809F + constGL_SAMPLE_MASK_SGIS* = 0x000080A0 + GL_MULTISAMPLE_BIT_EXT* = 0x20000000 + GL_1PASS_SGIS* = 0x000080A1 + GL_2PASS_0_SGIS* = 0x000080A2 + GL_2PASS_1_SGIS* = 0x000080A3 + GL_4PASS_0_SGIS* = 0x000080A4 + GL_4PASS_1_SGIS* = 0x000080A5 + GL_4PASS_2_SGIS* = 0x000080A6 + GL_4PASS_3_SGIS* = 0x000080A7 + GL_SAMPLE_BUFFERS_SGIS* = 0x000080A8 + GL_SAMPLES_SGIS* = 0x000080A9 + GL_SAMPLE_MASK_VALUE_SGIS* = 0x000080AA + GL_SAMPLE_MASK_INVERT_SGIS* = 0x000080AB + constGL_SAMPLE_PATTERN_SGIS* = 0x000080AC + +proc glSampleMaskSGIS*(value: TGLclampf, invert: TGLboolean){.dynlib: dllname, + importc: "glSampleMaskSGIS".} +proc glSamplePatternSGIS*(pattern: TGLenum){.dynlib: dllname, + importc: "glSamplePatternSGIS".} + #***** GL_SGIS_pixel_texture *****// +const + GL_PIXEL_TEXTURE_SGIS* = 0x00008353 + GL_PIXEL_FRAGMENT_RGB_SOURCE_SGIS* = 0x00008354 + GL_PIXEL_FRAGMENT_ALPHA_SOURCE_SGIS* = 0x00008355 + GL_PIXEL_GROUP_COLOR_SGIS* = 0x00008356 + +proc glPixelTexGenParameteriSGIS*(pname: TGLenum, param: TGLint){. + dynlib: dllname, importc: "glPixelTexGenParameteriSGIS".} +proc glPixelTexGenParameterfSGIS*(pname: TGLenum, param: TGLfloat){. + dynlib: dllname, importc: "glPixelTexGenParameterfSGIS".} +proc glGetPixelTexGenParameterivSGIS*(pname: TGLenum, params: TGLint){. + dynlib: dllname, importc: "glGetPixelTexGenParameterivSGIS".} +proc glGetPixelTexGenParameterfvSGIS*(pname: TGLenum, params: TGLfloat){. + dynlib: dllname, importc: "glGetPixelTexGenParameterfvSGIS".} + #***** GL_SGIS_texture_border_clamp *****// + # GL_CLAMP_TO_BORDER_SGIS { already defined } + #***** GL_SGIS_texture_color_mask *****// +const + GL_TEXTURE_COLOR_WRITEMASK_SGIS* = 0x000081EF + +proc glTextureColorMaskSGIS*(r: TGLboolean, g: TGLboolean, b: TGLboolean, + a: TGLboolean){.dynlib: dllname, + importc: "glTextureColorMaskSGIS".} + #***** GL_SGIS_texture_edge_clamp *****// +const + GL_CLAMP_TO_EDGE_SGIS* = 0x0000812F + #***** GL_SGIS_texture_lod *****// + +const + GL_TEXTURE_MIN_LOD_SGIS* = 0x0000813A + GL_TEXTURE_MAX_LOD_SGIS* = 0x0000813B + GL_TEXTURE_BASE_LEVEL_SGIS* = 0x0000813C + GL_TEXTURE_MAX_LEVEL_SGIS* = 0x0000813D + #***** GL_SGIS_depth_texture *****// + +const + GL_DEPTH_COMPONENT16_SGIX* = 0x000081A5 + GL_DEPTH_COMPONENT24_SGIX* = 0x000081A6 + GL_DEPTH_COMPONENT32_SGIX* = 0x000081A7 + #***** GL_SGIX_fog_offset *****// + +const + GL_FOG_OFFSET_SGIX* = 0x00008198 + GL_FOG_OFFSET_VALUE_SGIX* = 0x00008199 + #***** GL_SGIX_interlace *****// + +const + GL_INTERLACE_SGIX* = 0x00008094 + #***** GL_SGIX_shadow_ambient *****// + +const + GL_SHADOW_AMBIENT_SGIX* = 0x000080BF + #***** GL_SGI_color_matrix *****// + +const + GL_COLOR_MATRIX_SGI* = 0x000080B1 + GL_COLOR_MATRIX_STACK_DEPTH_SGI* = 0x000080B2 + GL_MAX_COLOR_MATRIX_STACK_DEPTH_SGI* = 0x000080B3 + GL_POST_COLOR_MATRIX_RED_SCALE_SGI* = 0x000080B4 + GL_POST_COLOR_MATRIX_GREEN_SCALE_SGI* = 0x000080B5 + GL_POST_COLOR_MATRIX_BLUE_SCALE_SGI* = 0x000080B6 + GL_POST_COLOR_MATRIX_ALPHA_SCALE_SGI* = 0x000080B7 + GL_POST_COLOR_MATRIX_RED_BIAS_SGI* = 0x000080B8 + GL_POST_COLOR_MATRIX_GREEN_BIAS_SGI* = 0x000080B9 + GL_POST_COLOR_MATRIX_BLUE_BIAS_SGI* = 0x000080BA + GL_POST_COLOR_MATRIX_ALPHA_BIAS_SGI* = 0x000080BB + #***** GL_SGI_color_table *****// + +const + constGL_COLOR_TABLE_SGI* = 0x000080D0 + GL_POST_CONVOLUTION_COLOR_TABLE_SGI* = 0x000080D1 + GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI* = 0x000080D2 + GL_PROXY_COLOR_TABLE_SGI* = 0x000080D3 + GL_PROXY_POST_CONVOLUTION_COLOR_TABLE_SGI* = 0x000080D4 + GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE_SGI* = 0x000080D5 + GL_COLOR_TABLE_SCALE_SGI* = 0x000080D6 + GL_COLOR_TABLE_BIAS_SGI* = 0x000080D7 + GL_COLOR_TABLE_FORMAT_SGI* = 0x000080D8 + GL_COLOR_TABLE_WIDTH_SGI* = 0x000080D9 + GL_COLOR_TABLE_RED_SIZE_SGI* = 0x000080DA + GL_COLOR_TABLE_GREEN_SIZE_SGI* = 0x000080DB + GL_COLOR_TABLE_BLUE_SIZE_SGI* = 0x000080DC + GL_COLOR_TABLE_ALPHA_SIZE_SGI* = 0x000080DD + GL_COLOR_TABLE_LUMINANCE_SIZE_SGI* = 0x000080DE + GL_COLOR_TABLE_INTENSITY_SIZE_SGI* = 0x000080DF + +proc glColorTableSGI*(target: TGLenum, internalformat: TGLenum, width: TGLsizei, + format: TGLenum, thetype: TGLenum, table: PGLvoid){. + dynlib: dllname, importc: "glColorTableSGI".} +proc glCopyColorTableSGI*(target: TGLenum, internalformat: TGLenum, x: TGLint, + y: TGLint, width: TGLsizei){.dynlib: dllname, + importc: "glCopyColorTableSGI".} +proc glColorTableParameterivSGI*(target: TGLenum, pname: TGLenum, params: PGLint){. + dynlib: dllname, importc: "glColorTableParameterivSGI".} +proc glColorTableParameterfvSGI*(target: TGLenum, pname: TGLenum, + params: PGLfloat){.dynlib: dllname, + importc: "glColorTableParameterfvSGI".} +proc glGetColorTableSGI*(target: TGLenum, format: TGLenum, thetype: TGLenum, + table: PGLvoid){.dynlib: dllname, + importc: "glGetColorTableSGI".} +proc glGetColorTableParameterivSGI*(target: TGLenum, pname: TGLenum, + params: PGLint){.dynlib: dllname, + importc: "glGetColorTableParameterivSGI".} +proc glGetColorTableParameterfvSGI*(target: TGLenum, pname: TGLenum, + params: PGLfloat){.dynlib: dllname, + importc: "glGetColorTableParameterfvSGI".} + #***** GL_SGI_texture_color_table *****// +const + GL_TEXTURE_COLOR_TABLE_SGI* = 0x000080BC + GL_PROXY_TEXTURE_COLOR_TABLE_SGI* = 0x000080BD + #***** GL_SUN_vertex *****// + +proc glColor4ubVertex2fSUN*(r: TGLubyte, g: TGLubyte, b: TGLubyte, a: TGLubyte, + x: TGLfloat, y: TGLfloat){.dynlib: dllname, + importc: "glColor4ubVertex2fSUN".} +proc glColor4ubVertex2fvSUN*(c: PGLubyte, v: PGLfloat){.dynlib: dllname, + importc: "glColor4ubVertex2fvSUN".} +proc glColor4ubVertex3fSUN*(r: TGLubyte, g: TGLubyte, b: TGLubyte, a: TGLubyte, + x: TGLfloat, y: TGLfloat, z: TGLfloat){. + dynlib: dllname, importc: "glColor4ubVertex3fSUN".} +proc glColor4ubVertex3fvSUN*(c: PGLubyte, v: PGLfloat){.dynlib: dllname, + importc: "glColor4ubVertex3fvSUN".} +proc glColor3fVertex3fSUN*(r: TGLfloat, g: TGLfloat, b: TGLfloat, x: TGLfloat, + y: TGLfloat, z: TGLfloat){.dynlib: dllname, + importc: "glColor3fVertex3fSUN".} +proc glColor3fVertex3fvSUN*(c: PGLfloat, v: PGLfloat){.dynlib: dllname, + importc: "glColor3fVertex3fvSUN".} +proc glNormal3fVertex3fSUN*(nx: TGLfloat, ny: TGLfloat, nz: TGLfloat, + x: TGLfloat, y: TGLfloat, z: TGLfloat){. + dynlib: dllname, importc: "glNormal3fVertex3fSUN".} +proc glNormal3fVertex3fvSUN*(n: PGLfloat, v: PGLfloat){.dynlib: dllname, + importc: "glNormal3fVertex3fvSUN".} +proc glColor4fNormal3fVertex3fSUN*(r: TGLfloat, g: TGLfloat, b: TGLfloat, + a: TGLfloat, nx: TGLfloat, ny: TGLfloat, + nz: TGLfloat, x: TGLfloat, y: TGLfloat, + z: TGLfloat){.dynlib: dllname, + importc: "glColor4fNormal3fVertex3fSUN".} +proc glColor4fNormal3fVertex3fvSUN*(c: PGLfloat, n: PGLfloat, v: PGLfloat){. + dynlib: dllname, importc: "glColor4fNormal3fVertex3fvSUN".} +proc glTexCoord2fVertex3fSUN*(s: TGLfloat, t: TGLfloat, x: TGLfloat, + y: TGLfloat, z: TGLfloat){.dynlib: dllname, + importc: "glTexCoord2fVertex3fSUN".} +proc glTexCoord2fVertex3fvSUN*(tc: PGLfloat, v: PGLfloat){.dynlib: dllname, + importc: "glTexCoord2fVertex3fvSUN".} +proc glTexCoord4fVertex4fSUN*(s: TGLfloat, t: TGLfloat, p: TGLfloat, + q: TGLfloat, x: TGLfloat, y: TGLfloat, + z: TGLfloat, w: TGLfloat){.dynlib: dllname, + importc: "glTexCoord4fVertex4fSUN".} +proc glTexCoord4fVertex4fvSUN*(tc: PGLfloat, v: PGLfloat){.dynlib: dllname, + importc: "glTexCoord4fVertex4fvSUN".} +proc glTexCoord2fColor4ubVertex3fSUN*(s: TGLfloat, t: TGLfloat, r: TGLubyte, + g: TGLubyte, b: TGLubyte, a: TGLubyte, + x: TGLfloat, y: TGLfloat, z: TGLfloat){. + dynlib: dllname, importc: "glTexCoord2fColor4ubVertex3fSUN".} +proc glTexCoord2fColor4ubVertex3fvSUN*(tc: PGLfloat, c: PGLubyte, v: PGLfloat){. + dynlib: dllname, importc: "glTexCoord2fColor4ubVertex3fvSUN".} +proc glTexCoord2fColor3fVertex3fSUN*(s: TGLfloat, t: TGLfloat, r: TGLfloat, + g: TGLfloat, b: TGLfloat, x: TGLfloat, + y: TGLfloat, z: TGLfloat){.dynlib: dllname, + importc: "glTexCoord2fColor3fVertex3fSUN".} +proc glTexCoord2fColor3fVertex3fvSUN*(tc: PGLfloat, c: PGLfloat, v: PGLfloat){. + dynlib: dllname, importc: "glTexCoord2fColor3fVertex3fvSUN".} +proc glTexCoord2fNormal3fVertex3fSUN*(s: TGLfloat, t: TGLfloat, nx: TGLfloat, + ny: TGLfloat, nz: TGLfloat, x: TGLfloat, + y: TGLfloat, z: TGLfloat){. + dynlib: dllname, importc: "glTexCoord2fNormal3fVertex3fSUN".} +proc glTexCoord2fNormal3fVertex3fvSUN*(tc: PGLfloat, n: PGLfloat, v: PGLfloat){. + dynlib: dllname, importc: "glTexCoord2fNormal3fVertex3fvSUN".} +proc glTexCoord2fColor4fNormal3fVertex3fSUN*(s: TGLfloat, t: TGLfloat, + r: TGLfloat, g: TGLfloat, b: TGLfloat, a: TGLfloat, nx: TGLfloat, + ny: TGLfloat, nz: TGLfloat, x: TGLfloat, y: TGLfloat, z: TGLfloat){. + dynlib: dllname, importc: "glTexCoord2fColor4fNormal3fVertex3fSUN".} +proc glTexCoord2fColor4fNormal3fVertex3fvSUN*(tc: PGLfloat, c: PGLfloat, + n: PGLfloat, v: PGLfloat){.dynlib: dllname, importc: "glTexCoord2fColor4fNormal3fVertex3fvSUN".} +proc glTexCoord4fColor4fNormal3fVertex4fSUN*(s: TGLfloat, t: TGLfloat, + p: TGLfloat, q: TGLfloat, r: TGLfloat, g: TGLfloat, b: TGLfloat, + a: TGLfloat, nx: TGLfloat, ny: TGLfloat, nz: TGLfloat, x: TGLfloat, + y: TGLfloat, z: TGLfloat, w: TGLfloat){.dynlib: dllname, + importc: "glTexCoord4fColor4fNormal3fVertex4fSUN".} +proc glTexCoord4fColor4fNormal3fVertex4fvSUN*(tc: PGLfloat, c: PGLfloat, + n: PGLfloat, v: PGLfloat){.dynlib: dllname, importc: "glTexCoord4fColor4fNormal3fVertex4fvSUN".} +proc glReplacementCodeuiVertex3fSUN*(rc: TGLuint, x: TGLfloat, y: TGLfloat, + z: TGLfloat){.dynlib: dllname, + importc: "glReplacementCodeuiVertex3fSUN".} +proc glReplacementCodeuiVertex3fvSUN*(rc: PGLuint, v: PGLfloat){. + dynlib: dllname, importc: "glReplacementCodeuiVertex3fvSUN".} +proc glReplacementCodeuiColor4ubVertex3fSUN*(rc: TGLuint, r: TGLubyte, + g: TGLubyte, b: TGLubyte, a: TGLubyte, x: TGLfloat, y: TGLfloat, z: TGLfloat){. + dynlib: dllname, importc: "glReplacementCodeuiColor4ubVertex3fSUN".} +proc glReplacementCodeuiColor4ubVertex3fvSUN*(rc: PGLuint, c: PGLubyte, + v: PGLfloat){.dynlib: dllname, + importc: "glReplacementCodeuiColor4ubVertex3fvSUN".} +proc glReplacementCodeuiColor3fVertex3fSUN*(rc: TGLuint, r: TGLfloat, + g: TGLfloat, b: TGLfloat, x: TGLfloat, y: TGLfloat, z: TGLfloat){. + dynlib: dllname, importc: "glReplacementCodeuiColor3fVertex3fSUN".} +proc glReplacementCodeuiColor3fVertex3fvSUN*(rc: PGLuint, c: PGLfloat, + v: PGLfloat){.dynlib: dllname, + importc: "glReplacementCodeuiColor3fVertex3fvSUN".} +proc glReplacementCodeuiNormal3fVertex3fSUN*(rc: TGLuint, nx: TGLfloat, + ny: TGLfloat, nz: TGLfloat, x: TGLfloat, y: TGLfloat, z: TGLfloat){. + dynlib: dllname, importc: "glReplacementCodeuiNormal3fVertex3fSUN".} +proc glReplacementCodeuiNormal3fVertex3fvSUN*(rc: PGLuint, n: PGLfloat, + v: PGLfloat){.dynlib: dllname, + importc: "glReplacementCodeuiNormal3fVertex3fvSUN".} +proc glReplacementCodeuiColor4fNormal3fVertex3fSUN*(rc: TGLuint, r: TGLfloat, + g: TGLfloat, b: TGLfloat, a: TGLfloat, nx: TGLfloat, ny: TGLfloat, + nz: TGLfloat, x: TGLfloat, y: TGLfloat, z: TGLfloat){.dynlib: dllname, + importc: "glReplacementCodeuiColor4fNormal3fVertex3fSUN".} +proc glReplacementCodeuiColor4fNormal3fVertex3fvSUN*(rc: PGLuint, c: PGLfloat, + n: PGLfloat, v: PGLfloat){.dynlib: dllname, importc: "glReplacementCodeuiColor4fNormal3fVertex3fvSUN".} +proc glReplacementCodeuiTexCoord2fVertex3fSUN*(rc: TGLuint, s: TGLfloat, + t: TGLfloat, x: TGLfloat, y: TGLfloat, z: TGLfloat){.dynlib: dllname, + importc: "glReplacementCodeuiTexCoord2fVertex3fSUN".} +proc glReplacementCodeuiTexCoord2fVertex3fvSUN*(rc: PGLuint, tc: PGLfloat, + v: PGLfloat){.dynlib: dllname, + importc: "glReplacementCodeuiTexCoord2fVertex3fvSUN".} +proc glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN*(rc: TGLuint, s: TGLfloat, + t: TGLfloat, nx: TGLfloat, ny: TGLfloat, nz: TGLfloat, x: TGLfloat, + y: TGLfloat, z: TGLfloat){.dynlib: dllname, importc: "glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN".} +proc glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN*(rc: PGLuint, + tc: PGLfloat, n: PGLfloat, v: PGLfloat){.dynlib: dllname, + importc: "glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN".} +proc glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN*(rc: TGLuint, + s: TGLfloat, t: TGLfloat, r: TGLfloat, g: TGLfloat, b: TGLfloat, + a: TGLfloat, nx: TGLfloat, ny: TGLfloat, nz: TGLfloat, x: TGLfloat, + y: TGLfloat, z: TGLfloat){.dynlib: dllname, importc: "glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN".} +proc glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN*(rc: PGLuint, + tc: PGLfloat, c: PGLfloat, n: PGLfloat, v: PGLfloat){.dynlib: dllname, + importc: "glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN".} + #***** GL_ARB_fragment_program *****// +const + GL_FRAGMENT_PROGRAM_ARB* = 0x00008804 # GL_PROGRAM_FORMAT_ASCII_ARB { already defined } + # GL_PROGRAM_LENGTH_ARB { already defined } + # GL_PROGRAM_FORMAT_ARB { already defined } + # GL_PROGRAM_BINDING_ARB { already defined } + # GL_PROGRAM_INSTRUCTIONS_ARB { already defined } + # GL_MAX_PROGRAM_INSTRUCTIONS_ARB { already defined } + # GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB { already defined } + # GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB { already defined } + # GL_PROGRAM_TEMPORARIES_ARB { already defined } + # GL_MAX_PROGRAM_TEMPORARIES_ARB { already defined } + # GL_PROGRAM_NATIVE_TEMPORARIES_ARB { already defined } + # GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB { already defined } + # GL_PROGRAM_PARAMETERS_ARB { already defined } + # GL_MAX_PROGRAM_PARAMETERS_ARB { already defined } + # GL_PROGRAM_NATIVE_PARAMETERS_ARB { already defined } + # GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB { already defined } + # GL_PROGRAM_ATTRIBS_ARB { already defined } + # GL_MAX_PROGRAM_ATTRIBS_ARB { already defined } + # GL_PROGRAM_NATIVE_ATTRIBS_ARB { already defined } + # GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB { already defined } + # GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB { already defined } + # GL_MAX_PROGRAM_ENV_PARAMETERS_ARB { already defined } + # GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB { already defined } + GL_PROGRAM_ALU_INSTRUCTIONS_ARB* = 0x00008805 + GL_PROGRAM_TEX_INSTRUCTIONS_ARB* = 0x00008806 + GL_PROGRAM_TEX_INDIRECTIONS_ARB* = 0x00008807 + GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB* = 0x00008808 + GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB* = 0x00008809 + GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB* = 0x0000880A + GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB* = 0x0000880B + GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB* = 0x0000880C + GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB* = 0x0000880D + GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB* = 0x0000880E + GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB* = 0x0000880F + GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB* = 0x00008810 # GL_PROGRAM_STRING_ARB { already defined } + # + # + # GL_PROGRAM_ERROR_POSITION_ARB { already defined } + # GL_CURRENT_MATRIX_ARB { already defined } + # + # + # GL_TRANSPOSE_CURRENT_MATRIX_ARB { already defined } + # + # + # GL_CURRENT_MATRIX_STACK_DEPTH_ARB { already defined } + # + # + # GL_MAX_PROGRAM_MATRICES_ARB { already defined } + # + # + # GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB { already defined } + GL_MAX_TEXTURE_COORDS_ARB* = 0x00008871 + GL_MAX_TEXTURE_IMAGE_UNITS_ARB* = 0x00008872 # GL_PROGRAM_ERROR_STRING_ARB { already defined } + # GL_MATRIX0_ARB { already defined } + # GL_MATRIX1_ARB { already defined } + # GL_MATRIX2_ARB { already defined } + # GL_MATRIX3_ARB { already defined } + # GL_MATRIX4_ARB { already defined } + # GL_MATRIX5_ARB { already defined } + # GL_MATRIX6_ARB { already defined } + # GL_MATRIX7_ARB { already defined } + # GL_MATRIX8_ARB { already defined } + # GL_MATRIX9_ARB { already defined } + # GL_MATRIX10_ARB { already defined } + # GL_MATRIX11_ARB { already defined } + # GL_MATRIX12_ARB { already defined } + # GL_MATRIX13_ARB { already defined } + # GL_MATRIX14_ARB { already defined } + # GL_MATRIX15_ARB { already defined } + # GL_MATRIX16_ARB { already defined } + # GL_MATRIX17_ARB { already defined } + # GL_MATRIX18_ARB { already defined } + # GL_MATRIX19_ARB { already defined } + # GL_MATRIX20_ARB { already defined } + # GL_MATRIX21_ARB { already defined } + # GL_MATRIX22_ARB { already defined } + # GL_MATRIX23_ARB { already defined } + # GL_MATRIX24_ARB { already defined } + # GL_MATRIX25_ARB { already defined } + # GL_MATRIX26_ARB { already defined } + # GL_MATRIX27_ARB { already defined } + # GL_MATRIX28_ARB { already defined } + # GL_MATRIX29_ARB { already defined } + # GL_MATRIX30_ARB { already defined } + # GL_MATRIX31_ARB { already defined } + # glProgramStringARB { already defined } + # glBindProgramARB { already defined } + # glDeleteProgramsARB { already defined } + # glGenProgramsARB { already defined } + # glProgramEnvParameter4dARB { already defined } + # glProgramEnvParameter4dvARB { already defined } + # glProgramEnvParameter4fARB { already defined } + # glProgramEnvParameter4fvARB { already defined } + # glProgramLocalParameter4dARB { already defined } + # glProgramLocalParameter4dvARB { already defined } + # glProgramLocalParameter4fARB { already defined } + # glProgramLocalParameter4fvARB { already defined } + # glGetProgramEnvParameterdvARB { already defined } + # glGetProgramEnvParameterfvARB { already defined } + # glGetProgramLocalParameterdvARB { already defined } + # glGetProgramLocalParameterfvARB { already defined } + # glGetProgramivARB { already defined } + # glGetProgramStringARB { already defined } + # glIsProgramARB { already defined } + #***** GL_ATI_text_fragment_shader ***** + +const + GL_TEXT_FRAGMENT_SHADER_ATI* = 0x00008200 #***** GL_ARB_vertex_buffer_object ***** + +const + GL_BUFFER_SIZE_ARB* = 0x00008764 + GL_BUFFER_USAGE_ARB* = 0x00008765 + GL_ARRAY_BUFFER_ARB* = 0x00008892 + GL_ELEMENT_ARRAY_BUFFER_ARB* = 0x00008893 + GL_ARRAY_BUFFER_BINDING_ARB* = 0x00008894 + GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB* = 0x00008895 + GL_VERTEX_ARRAY_BUFFER_BINDING_ARB* = 0x00008896 + GL_NORMAL_ARRAY_BUFFER_BINDING_ARB* = 0x00008897 + GL_COLOR_ARRAY_BUFFER_BINDING_ARB* = 0x00008898 + GL_INDEX_ARRAY_BUFFER_BINDING_ARB* = 0x00008899 + GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB* = 0x0000889A + GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB* = 0x0000889B + GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB* = 0x0000889C + GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB* = 0x0000889D + GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB* = 0x0000889E + GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB* = 0x0000889F + GL_READ_ONLY_ARB* = 0x000088B8 + GL_WRITE_ONLY_ARB* = 0x000088B9 + GL_READ_WRITE_ARB* = 0x000088BA + GL_BUFFER_ACCESS_ARB* = 0x000088BB + GL_BUFFER_MAPPED_ARB* = 0x000088BC + GL_BUFFER_MAP_POINTER_ARB* = 0x000088BD + GL_STREAM_DRAW_ARB* = 0x000088E0 + GL_STREAM_READ_ARB* = 0x000088E1 + GL_STREAM_COPY_ARB* = 0x000088E2 + GL_STATIC_DRAW_ARB* = 0x000088E4 + GL_STATIC_READ_ARB* = 0x000088E5 + GL_STATIC_COPY_ARB* = 0x000088E6 + GL_DYNAMIC_DRAW_ARB* = 0x000088E8 + GL_DYNAMIC_READ_ARB* = 0x000088E9 + GL_DYNAMIC_COPY_ARB* = 0x000088EA + +proc glBindBufferARB*(target: TGLenum, buffer: TGLuint){.dynlib: dllname, + importc: "glBindBufferARB".} +proc glDeleteBuffersARB*(n: TGLsizei, buffers: PGLuint){.dynlib: dllname, + importc: "glDeleteBuffersARB".} +proc glGenBuffersARB*(n: TGLsizei, buffers: PGLuint){.dynlib: dllname, + importc: "glGenBuffersARB".} +proc glIsBufferARB*(buffer: TGLuint): TGLboolean{.dynlib: dllname, + importc: "glIsBufferARB".} +proc glBufferDataARB*(target: TGLenum, size: TGLsizei, data: PGLvoid, + usage: TGLenum){.dynlib: dllname, + importc: "glBufferDataARB".} +proc glBufferSubDataARB*(target: TGLenum, offset: TGLint, size: TGLsizei, + data: PGLvoid){.dynlib: dllname, + importc: "glBufferSubDataARB".} +proc glGetBufferSubDataARB*(target: TGLenum, offset: TGLint, size: TGLsizei, + data: PGLvoid){.dynlib: dllname, + importc: "glGetBufferSubDataARB".} +proc glMapBufferARB*(target: TGLenum, access: TGLenum): PGLvoid{. + dynlib: dllname, importc: "glMapBufferARB".} +proc glUnmapBufferARB*(target: TGLenum): TGLboolean{.dynlib: dllname, + importc: "glUnmapBufferARB".} +proc glGetBufferParameterivARB*(target: TGLenum, pname: TGLenum, params: PGLint){. + dynlib: dllname, importc: "glGetBufferParameterivARB".} +proc glGetBufferPointervARB*(target: TGLenum, pname: TGLenum, params: PPGLvoid){. + dynlib: dllname, importc: "glGetBufferPointervARB".} + #***** GL_APPLE_client_storage *****// +const + GL_UNPACK_CLIENT_STORAGE_APPLE* = 0x000085B2 + #***** GL_APPLE_element_array *****// + +const + GL_ELEMENT_ARRAY_APPLE* = 0x00008768 + GL_ELEMENT_ARRAY_TYPE_APPLE* = 0x00008769 + GL_ELEMENT_ARRAY_POINTER_APPLE* = 0x0000876A + +proc glElementPointerAPPLE*(thetype: TGLenum, pointer: PGLvoid){. + dynlib: dllname, importc: "glElementPointerAPPLE".} +proc glDrawElementArrayAPPLE*(mode: TGLenum, first: TGLint, count: TGLsizei){. + dynlib: dllname, importc: "glDrawElementArrayAPPLE".} +proc glDrawRangeElementArrayAPPLE*(mode: TGLenum, start: TGLuint, + theend: TGLuint, first: TGLint, + count: TGLsizei){.dynlib: dllname, + importc: "glDrawRangeElementArrayAPPLE".} +proc glMultiDrawElementArrayAPPLE*(mode: TGLenum, first: PGLint, + count: PGLsizei, primcount: TGLsizei){. + dynlib: dllname, importc: "glMultiDrawElementArrayAPPLE".} +proc glMultiDrawRangeElementArrayAPPLE*(mode: TGLenum, start: TGLuint, + theend: TGLuint, first: PGLint, + count: PGLsizei, primcount: TGLsizei){. + dynlib: dllname, importc: "glMultiDrawRangeElementArrayAPPLE".} + #***** GL_APPLE_fence *****// +const + GL_DRAW_PIXELS_APPLE* = 0x00008A0A + GL_FENCE_APPLE* = 0x00008A0B + +proc glGenFencesAPPLE*(n: TGLsizei, fences: PGLuint){.dynlib: dllname, + importc: "glGenFencesAPPLE".} +proc glDeleteFencesAPPLE*(n: TGLsizei, fences: PGLuint){.dynlib: dllname, + importc: "glDeleteFencesAPPLE".} +proc glSetFenceAPPLE*(fence: TGLuint){.dynlib: dllname, + importc: "glSetFenceAPPLE".} +proc glIsFenceAPPLE*(fence: TGLuint): TGLboolean{.dynlib: dllname, + importc: "glIsFenceAPPLE".} +proc glTestFenceAPPLE*(fence: TGLuint): TGLboolean{.dynlib: dllname, + importc: "glTestFenceAPPLE".} +proc glFinishFenceAPPLE*(fence: TGLuint){.dynlib: dllname, + importc: "glFinishFenceAPPLE".} +proc glTestObjectAPPLE*(theobject: TGLenum, name: TGLuint): TGLboolean{. + dynlib: dllname, importc: "glTestObjectAPPLE".} +proc glFinishObjectAPPLE*(theobject: TGLenum, name: TGLint){.dynlib: dllname, + importc: "glFinishObjectAPPLE".} + #***** GL_APPLE_vertex_array_object *****// +const + GL_VERTEX_ARRAY_BINDING_APPLE* = 0x000085B5 + +proc glBindVertexArrayAPPLE*(thearray: TGLuint){.dynlib: dllname, + importc: "glBindVertexArrayAPPLE".} +proc glDeleteVertexArraysAPPLE*(n: TGLsizei, arrays: PGLuint){.dynlib: dllname, + importc: "glDeleteVertexArraysAPPLE".} +proc glGenVertexArraysAPPLE*(n: TGLsizei, arrays: PGLuint){.dynlib: dllname, + importc: "glGenVertexArraysAPPLE".} +proc glIsVertexArrayAPPLE*(thearray: TGLuint): TGLboolean{.dynlib: dllname, + importc: "glIsVertexArrayAPPLE".} + #***** GL_APPLE_vertex_array_range *****// +const + constGL_VERTEX_ARRAY_RANGE_APPLE* = 0x0000851D + GL_VERTEX_ARRAY_RANGE_LENGTH_APPLE* = 0x0000851E + GL_MAX_VERTEX_ARRAY_RANGE_ELEMENT_APPLE* = 0x00008520 + GL_VERTEX_ARRAY_RANGE_POINTER_APPLE* = 0x00008521 + GL_VERTEX_ARRAY_STORAGE_HINT_APPLE* = 0x0000851F + GL_STORAGE_CACHED_APPLE* = 0x000085BE + GL_STORAGE_SHARED_APPLE* = 0x000085BF + +proc glVertexArrayRangeAPPLE*(len: TGLsizei, pointer: PGLvoid){.dynlib: dllname, + importc: "glVertexArrayRangeAPPLE".} +proc glFlushVertexArrayRangeAPPLE*(len: TGLsizei, pointer: PGLvoid){. + dynlib: dllname, importc: "glFlushVertexArrayRangeAPPLE".} +proc glVertexArrayParameteriAPPLE*(pname: TGLenum, param: TGLint){. + dynlib: dllname, importc: "glVertexArrayParameteriAPPLE".} + #***** GL_ARB_matrix_palette *****// +const + GL_MATRIX_PALETTE_ARB* = 0x00008840 + GL_MAX_MATRIX_PALETTE_STACK_DEPTH_ARB* = 0x00008841 + GL_MAX_PALETTE_MATRICES_ARB* = 0x00008842 + constGL_CURRENT_PALETTE_MATRIX_ARB* = 0x00008843 + GL_MATRIX_INDEX_ARRAY_ARB* = 0x00008844 + GL_CURRENT_MATRIX_INDEX_ARB* = 0x00008845 + GL_MATRIX_INDEX_ARRAY_SIZE_ARB* = 0x00008846 + GL_MATRIX_INDEX_ARRAY_TYPE_ARB* = 0x00008847 + GL_MATRIX_INDEX_ARRAY_STRIDE_ARB* = 0x00008848 + GL_MATRIX_INDEX_ARRAY_POINTER_ARB* = 0x00008849 + +proc glCurrentPaletteMatrixARB*(index: TGLint){.dynlib: dllname, + importc: "glCurrentPaletteMatrixARB".} +proc glMatrixIndexubvARB*(size: TGLint, indices: PGLubyte){.dynlib: dllname, + importc: "glMatrixIndexubvARB".} +proc glMatrixIndexusvARB*(size: TGLint, indices: PGLushort){.dynlib: dllname, + importc: "glMatrixIndexusvARB".} +proc glMatrixIndexuivARB*(size: TGLint, indices: PGLuint){.dynlib: dllname, + importc: "glMatrixIndexuivARB".} +proc glMatrixIndexPointerARB*(size: TGLint, thetype: TGLenum, stride: TGLsizei, + pointer: PGLvoid){.dynlib: dllname, + importc: "glMatrixIndexPointerARB".} + #***** GL_NV_element_array *****// +const + GL_ELEMENT_ARRAY_TYPE_NV* = 0x00008769 + GL_ELEMENT_ARRAY_POINTER_NV* = 0x0000876A + +proc glElementPointerNV*(thetype: TGLenum, pointer: PGLvoid){.dynlib: dllname, + importc: "glElementPointerNV".} +proc glDrawElementArrayNV*(mode: TGLenum, first: TGLint, count: TGLsizei){. + dynlib: dllname, importc: "glDrawElementArrayNV".} +proc glDrawRangeElementArrayNV*(mode: TGLenum, start: TGLuint, theend: TGLuint, + first: TGLint, count: TGLsizei){. + dynlib: dllname, importc: "glDrawRangeElementArrayNV".} +proc glMultiDrawElementArrayNV*(mode: TGLenum, first: PGLint, count: PGLsizei, + primcount: TGLsizei){.dynlib: dllname, + importc: "glMultiDrawElementArrayNV".} +proc glMultiDrawRangeElementArrayNV*(mode: TGLenum, start: TGLuint, + theend: TGLuint, first: PGLint, + count: PGLsizei, primcount: TGLsizei){. + dynlib: dllname, importc: "glMultiDrawRangeElementArrayNV".} + #***** GL_NV_float_buffer *****// +const + GL_FLOAT_R_NV* = 0x00008880 + GL_FLOAT_RG_NV* = 0x00008881 + GL_FLOAT_RGB_NV* = 0x00008882 + GL_FLOAT_RGBA_NV* = 0x00008883 + GL_FLOAT_R16_NV* = 0x00008884 + GL_FLOAT_R32_NV* = 0x00008885 + GL_FLOAT_RG16_NV* = 0x00008886 + GL_FLOAT_RG32_NV* = 0x00008887 + GL_FLOAT_RGB16_NV* = 0x00008888 + GL_FLOAT_RGB32_NV* = 0x00008889 + GL_FLOAT_RGBA16_NV* = 0x0000888A + GL_FLOAT_RGBA32_NV* = 0x0000888B + GL_TEXTURE_FLOAT_COMPONENTS_NV* = 0x0000888C + GL_FLOAT_CLEAR_COLOR_VALUE_NV* = 0x0000888D + GL_FLOAT_RGBA_MODE_NV* = 0x0000888E + #***** GL_NV_fragment_program *****// + +const + GL_FRAGMENT_PROGRAM_NV* = 0x00008870 + GL_MAX_TEXTURE_COORDS_NV* = 0x00008871 + GL_MAX_TEXTURE_IMAGE_UNITS_NV* = 0x00008872 + GL_FRAGMENT_PROGRAM_BINDING_NV* = 0x00008873 + GL_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMETERS_NV* = 0x00008868 + GL_PROGRAM_ERROR_STRING_NV* = 0x00008874 + +proc glProgramNamedParameter4fNV*(id: TGLuint, length: TGLsizei, name: PGLubyte, + x: TGLfloat, y: TGLfloat, z: TGLfloat, + w: TGLfloat){.dynlib: dllname, + importc: "glProgramNamedParameter4fNV".} +proc glProgramNamedParameter4dNV*(id: TGLuint, length: TGLsizei, name: PGLubyte, + x: TGLdouble, y: TGLdouble, z: TGLdouble, + w: TGLdouble){.dynlib: dllname, + importc: "glProgramNamedParameter4dNV".} +proc glGetProgramNamedParameterfvNV*(id: TGLuint, length: TGLsizei, + name: PGLubyte, params: PGLfloat){. + dynlib: dllname, importc: "glGetProgramNamedParameterfvNV".} +proc glGetProgramNamedParameterdvNV*(id: TGLuint, length: TGLsizei, + name: PGLubyte, params: PGLdouble){. + dynlib: dllname, importc: "glGetProgramNamedParameterdvNV".} + # glProgramLocalParameter4dARB { already defined } + # glProgramLocalParameter4dvARB { already defined } + # glProgramLocalParameter4fARB { already defined } + # glProgramLocalParameter4fvARB { already defined } + # glGetProgramLocalParameterdvARB { already defined } + # glGetProgramLocalParameterfvARB { already defined } + #***** GL_NV_primitive_restart *****// +const + constGL_PRIMITIVE_RESTART_NV* = 0x00008558 + constGL_PRIMITIVE_RESTART_INDEX_NV* = 0x00008559 + +proc glPrimitiveRestartNV*(){.dynlib: dllname, importc: "glPrimitiveRestartNV".} +proc glPrimitiveRestartIndexNV*(index: TGLuint){.dynlib: dllname, + importc: "glPrimitiveRestartIndexNV".} + #***** GL_NV_vertex_program2 *****// + #***** GL_NV_pixel_data_range *****// +const + GL_WRITE_PIXEL_DATA_RANGE_NV* = 0x00008878 + GL_READ_PIXEL_DATA_RANGE_NV* = 0x00008879 + GL_WRITE_PIXEL_DATA_RANGE_LENGTH_NV* = 0x0000887A + GL_READ_PIXEL_DATA_RANGE_LENGTH_NV* = 0x0000887B + GL_WRITE_PIXEL_DATA_RANGE_POINTER_NV* = 0x0000887C + GL_READ_PIXEL_DATA_RANGE_POINTER_NV* = 0x0000887D + +proc glPixelDataRangeNV*(target: TGLenum, len: TGLsizei, pointer: PGLvoid){. + dynlib: dllname, importc: "glPixelDataRangeNV".} +proc glFlushPixelDataRangeNV*(target: TGLenum){.dynlib: dllname, + importc: "glFlushPixelDataRangeNV".} + # wglAllocateMemoryNV { already defined } + # wglFreeMemoryNV { already defined } + #***** GL_EXT_texture_rectangle *****// +const + GL_TEXTURE_RECTANGLE_EXT* = 0x000084F5 + GL_TEXTURE_BINDING_RECTANGLE_EXT* = 0x000084F6 + GL_PROXY_TEXTURE_RECTANGLE_EXT* = 0x000084F7 + GL_MAX_RECTANGLE_TEXTURE_SIZE_EXT* = 0x000084F8 + #***** GL_S3_s3tc *****// + +const + GL_RGB_S3TC* = 0x000083A0 + GL_RGB4_S3TC* = 0x000083A1 + GL_RGBA_S3TC* = 0x000083A2 + GL_RGBA4_S3TC* = 0x000083A3 + #***** GL_ATI_draw_buffers *****// + +const + GL_MAX_DRAW_BUFFERS_ATI* = 0x00008824 + GL_DRAW_BUFFER0_ATI* = 0x00008825 + GL_DRAW_BUFFER1_ATI* = 0x00008826 + GL_DRAW_BUFFER2_ATI* = 0x00008827 + GL_DRAW_BUFFER3_ATI* = 0x00008828 + GL_DRAW_BUFFER4_ATI* = 0x00008829 + GL_DRAW_BUFFER5_ATI* = 0x0000882A + GL_DRAW_BUFFER6_ATI* = 0x0000882B + GL_DRAW_BUFFER7_ATI* = 0x0000882C + GL_DRAW_BUFFER8_ATI* = 0x0000882D + GL_DRAW_BUFFER9_ATI* = 0x0000882E + GL_DRAW_BUFFER10_ATI* = 0x0000882F + GL_DRAW_BUFFER11_ATI* = 0x00008830 + GL_DRAW_BUFFER12_ATI* = 0x00008831 + GL_DRAW_BUFFER13_ATI* = 0x00008832 + GL_DRAW_BUFFER14_ATI* = 0x00008833 + GL_DRAW_BUFFER15_ATI* = 0x00008834 + +proc glDrawBuffersATI*(n: TGLsizei, bufs: PGLenum){.dynlib: dllname, + importc: "glDrawBuffersATI".} + #***** GL_ATI_texture_env_combine3 *****// +const + GL_MODULATE_ADD_ATI* = 0x00008744 + GL_MODULATE_SIGNED_ADD_ATI* = 0x00008745 + GL_MODULATE_SUBTRACT_ATI* = 0x00008746 + #***** GL_ATI_texture_float *****// + +const + GL_RGBA_FLOAT32_ATI* = 0x00008814 + GL_RGB_FLOAT32_ATI* = 0x00008815 + GL_ALPHA_FLOAT32_ATI* = 0x00008816 + GL_INTENSITY_FLOAT32_ATI* = 0x00008817 + GL_LUMINANCE_FLOAT32_ATI* = 0x00008818 + GL_LUMINANCE_ALPHA_FLOAT32_ATI* = 0x00008819 + GL_RGBA_FLOAT16_ATI* = 0x0000881A + GL_RGB_FLOAT16_ATI* = 0x0000881B + GL_ALPHA_FLOAT16_ATI* = 0x0000881C + GL_INTENSITY_FLOAT16_ATI* = 0x0000881D + GL_LUMINANCE_FLOAT16_ATI* = 0x0000881E + GL_LUMINANCE_ALPHA_FLOAT16_ATI* = 0x0000881F + #***** GL_NV_texture_expand_normal *****// + +const + GL_TEXTURE_UNSIGNED_REMAP_MODE_NV* = 0x0000888F + #***** GL_NV_half_float *****// + +const + GL_HALF_FLOAT_NV* = 0x0000140B + +proc glVertex2hNV*(x: TGLushort, y: TGLushort){.dynlib: dllname, + importc: "glVertex2hNV".} +proc glVertex2hvNV*(v: PGLushort){.dynlib: dllname, importc: "glVertex2hvNV".} +proc glVertex3hNV*(x: TGLushort, y: TGLushort, z: TGLushort){.dynlib: dllname, + importc: "glVertex3hNV".} +proc glVertex3hvNV*(v: PGLushort){.dynlib: dllname, importc: "glVertex3hvNV".} +proc glVertex4hNV*(x: TGLushort, y: TGLushort, z: TGLushort, w: TGLushort){. + dynlib: dllname, importc: "glVertex4hNV".} +proc glVertex4hvNV*(v: PGLushort){.dynlib: dllname, importc: "glVertex4hvNV".} +proc glNormal3hNV*(nx: TGLushort, ny: TGLushort, nz: TGLushort){. + dynlib: dllname, importc: "glNormal3hNV".} +proc glNormal3hvNV*(v: PGLushort){.dynlib: dllname, importc: "glNormal3hvNV".} +proc glColor3hNV*(red: TGLushort, green: TGLushort, blue: TGLushort){. + dynlib: dllname, importc: "glColor3hNV".} +proc glColor3hvNV*(v: PGLushort){.dynlib: dllname, importc: "glColor3hvNV".} +proc glColor4hNV*(red: TGLushort, green: TGLushort, blue: TGLushort, + alpha: TGLushort){.dynlib: dllname, importc: "glColor4hNV".} +proc glColor4hvNV*(v: PGLushort){.dynlib: dllname, importc: "glColor4hvNV".} +proc glTexCoord1hNV*(s: TGLushort){.dynlib: dllname, importc: "glTexCoord1hNV".} +proc glTexCoord1hvNV*(v: PGLushort){.dynlib: dllname, importc: "glTexCoord1hvNV".} +proc glTexCoord2hNV*(s: TGLushort, t: TGLushort){.dynlib: dllname, + importc: "glTexCoord2hNV".} +proc glTexCoord2hvNV*(v: PGLushort){.dynlib: dllname, importc: "glTexCoord2hvNV".} +proc glTexCoord3hNV*(s: TGLushort, t: TGLushort, r: TGLushort){.dynlib: dllname, + importc: "glTexCoord3hNV".} +proc glTexCoord3hvNV*(v: PGLushort){.dynlib: dllname, importc: "glTexCoord3hvNV".} +proc glTexCoord4hNV*(s: TGLushort, t: TGLushort, r: TGLushort, q: TGLushort){. + dynlib: dllname, importc: "glTexCoord4hNV".} +proc glTexCoord4hvNV*(v: PGLushort){.dynlib: dllname, importc: "glTexCoord4hvNV".} +proc glMultiTexCoord1hNV*(target: TGLenum, s: TGLushort){.dynlib: dllname, + importc: "glMultiTexCoord1hNV".} +proc glMultiTexCoord1hvNV*(target: TGLenum, v: PGLushort){.dynlib: dllname, + importc: "glMultiTexCoord1hvNV".} +proc glMultiTexCoord2hNV*(target: TGLenum, s: TGLushort, t: TGLushort){. + dynlib: dllname, importc: "glMultiTexCoord2hNV".} +proc glMultiTexCoord2hvNV*(target: TGLenum, v: PGLushort){.dynlib: dllname, + importc: "glMultiTexCoord2hvNV".} +proc glMultiTexCoord3hNV*(target: TGLenum, s: TGLushort, t: TGLushort, + r: TGLushort){.dynlib: dllname, + importc: "glMultiTexCoord3hNV".} +proc glMultiTexCoord3hvNV*(target: TGLenum, v: PGLushort){.dynlib: dllname, + importc: "glMultiTexCoord3hvNV".} +proc glMultiTexCoord4hNV*(target: TGLenum, s: TGLushort, t: TGLushort, + r: TGLushort, q: TGLushort){.dynlib: dllname, + importc: "glMultiTexCoord4hNV".} +proc glMultiTexCoord4hvNV*(target: TGLenum, v: PGLushort){.dynlib: dllname, + importc: "glMultiTexCoord4hvNV".} +proc glFogCoordhNV*(fog: TGLushort){.dynlib: dllname, importc: "glFogCoordhNV".} +proc glFogCoordhvNV*(fog: PGLushort){.dynlib: dllname, importc: "glFogCoordhvNV".} +proc glSecondaryColor3hNV*(red: TGLushort, green: TGLushort, blue: TGLushort){. + dynlib: dllname, importc: "glSecondaryColor3hNV".} +proc glSecondaryColor3hvNV*(v: PGLushort){.dynlib: dllname, + importc: "glSecondaryColor3hvNV".} +proc glVertexWeighthNV*(weight: TGLushort){.dynlib: dllname, + importc: "glVertexWeighthNV".} +proc glVertexWeighthvNV*(weight: PGLushort){.dynlib: dllname, + importc: "glVertexWeighthvNV".} +proc glVertexAttrib1hNV*(index: TGLuint, x: TGLushort){.dynlib: dllname, + importc: "glVertexAttrib1hNV".} +proc glVertexAttrib1hvNV*(index: TGLuint, v: PGLushort){.dynlib: dllname, + importc: "glVertexAttrib1hvNV".} +proc glVertexAttrib2hNV*(index: TGLuint, x: TGLushort, y: TGLushort){. + dynlib: dllname, importc: "glVertexAttrib2hNV".} +proc glVertexAttrib2hvNV*(index: TGLuint, v: PGLushort){.dynlib: dllname, + importc: "glVertexAttrib2hvNV".} +proc glVertexAttrib3hNV*(index: TGLuint, x: TGLushort, y: TGLushort, + z: TGLushort){.dynlib: dllname, + importc: "glVertexAttrib3hNV".} +proc glVertexAttrib3hvNV*(index: TGLuint, v: PGLushort){.dynlib: dllname, + importc: "glVertexAttrib3hvNV".} +proc glVertexAttrib4hNV*(index: TGLuint, x: TGLushort, y: TGLushort, + z: TGLushort, w: TGLushort){.dynlib: dllname, + importc: "glVertexAttrib4hNV".} +proc glVertexAttrib4hvNV*(index: TGLuint, v: PGLushort){.dynlib: dllname, + importc: "glVertexAttrib4hvNV".} +proc glVertexAttribs1hvNV*(index: TGLuint, n: TGLsizei, v: PGLushort){. + dynlib: dllname, importc: "glVertexAttribs1hvNV".} +proc glVertexAttribs2hvNV*(index: TGLuint, n: TGLsizei, v: PGLushort){. + dynlib: dllname, importc: "glVertexAttribs2hvNV".} +proc glVertexAttribs3hvNV*(index: TGLuint, n: TGLsizei, v: PGLushort){. + dynlib: dllname, importc: "glVertexAttribs3hvNV".} +proc glVertexAttribs4hvNV*(index: TGLuint, n: TGLsizei, v: PGLushort){. + dynlib: dllname, importc: "glVertexAttribs4hvNV".} + #***** GL_ATI_map_object_buffer *****// +proc glMapObjectBufferATI*(buffer: TGLuint): PGLvoid{.dynlib: dllname, + importc: "glMapObjectBufferATI".} +proc glUnmapObjectBufferATI*(buffer: TGLuint){.dynlib: dllname, + importc: "glUnmapObjectBufferATI".} + #***** GL_ATI_separate_stencil *****// +const + GL_KEEP* = 0x00001E00 + GL_ZERO* = 0x00000000 + GL_REPLACE* = 0x00001E01 + GL_INCR* = 0x00001E02 + GL_DECR* = 0x00001E03 + GL_INVERT* = 0x0000150A + GL_NEVER* = 0x00000200 + GL_LESS* = 0x00000201 + GL_LEQUAL* = 0x00000203 + GL_GREATER* = 0x00000204 + GL_GEQUAL* = 0x00000206 + GL_EQUAL* = 0x00000202 + GL_NOTEQUAL* = 0x00000205 + GL_ALWAYS* = 0x00000207 + GL_FRONT* = 0x00000404 + GL_BACK* = 0x00000405 + GL_FRONT_AND_BACK* = 0x00000408 + GL_STENCIL_BACK_FUNC_ATI* = 0x00008800 + GL_STENCIL_BACK_FAIL_ATI* = 0x00008801 + GL_STENCIL_BACK_PASS_DEPTH_FAIL_ATI* = 0x00008802 + GL_STENCIL_BACK_PASS_DEPTH_PASS_ATI* = 0x00008803 + +proc glStencilOpSeparateATI*(face: TGLenum, sfail: TGLenum, dpfail: TGLenum, + dppass: TGLenum){.dynlib: dllname, + importc: "glStencilOpSeparateATI".} +proc glStencilFuncSeparateATI*(frontfunc: TGLenum, backfunc: TGLenum, + theRef: TGLint, mask: TGLuint){.dynlib: dllname, + importc: "glStencilFuncSeparateATI".} + #***** GL_ATI_vertex_attrib_array_object *****// +proc glVertexAttribArrayObjectATI*(index: TGLuint, size: TGLint, + thetype: TGLenum, normalized: TGLboolean, + stride: TGLsizei, buffer: TGLuint, + offset: TGLuint){.dynlib: dllname, + importc: "glVertexAttribArrayObjectATI".} +proc glGetVertexAttribArrayObjectfvATI*(index: TGLuint, pname: TGLenum, + params: PGLfloat){.dynlib: dllname, + importc: "glGetVertexAttribArrayObjectfvATI".} +proc glGetVertexAttribArrayObjectivATI*(index: TGLuint, pname: TGLenum, + params: PGLint){.dynlib: dllname, + importc: "glGetVertexAttribArrayObjectivATI".} + #***** GL_ARB_occlusion_query *****// +const + GL_SAMPLES_PASSED_ARB* = 0x00008914 + GL_QUERY_COUNTER_BITS_ARB* = 0x00008864 + GL_CURRENT_QUERY_ARB* = 0x00008865 + GL_QUERY_RESULT_ARB* = 0x00008866 + GL_QUERY_RESULT_AVAILABLE_ARB* = 0x00008867 + +proc glGenQueriesARB*(n: TGLsizei, ids: PGLuint){.dynlib: dllname, + importc: "glGenQueriesARB".} +proc glDeleteQueriesARB*(n: TGLsizei, ids: PGLuint){.dynlib: dllname, + importc: "glDeleteQueriesARB".} +proc glIsQueryARB*(id: TGLuint): TGLboolean{.dynlib: dllname, + importc: "glIsQueryARB".} +proc glBeginQueryARB*(target: TGLenum, id: TGLuint){.dynlib: dllname, + importc: "glBeginQueryARB".} +proc glEndQueryARB*(target: TGLenum){.dynlib: dllname, importc: "glEndQueryARB".} +proc glGetQueryivARB*(target: TGLenum, pname: TGLenum, params: PGLint){. + dynlib: dllname, importc: "glGetQueryivARB".} +proc glGetQueryObjectivARB*(id: TGLuint, pname: TGLenum, params: PGLint){. + dynlib: dllname, importc: "glGetQueryObjectivARB".} +proc glGetQueryObjectuivARB*(id: TGLuint, pname: TGLenum, params: PGLuint){. + dynlib: dllname, importc: "glGetQueryObjectuivARB".} + #***** GL_ARB_shader_objects *****// +const + GL_PROGRAM_OBJECT_ARB* = 0x00008B40 + GL_OBJECT_TYPE_ARB* = 0x00008B4E + GL_OBJECT_SUBTYPE_ARB* = 0x00008B4F + GL_OBJECT_DELETE_STATUS_ARB* = 0x00008B80 + GL_OBJECT_COMPILE_STATUS_ARB* = 0x00008B81 + GL_OBJECT_LINK_STATUS_ARB* = 0x00008B82 + GL_OBJECT_VALIDATE_STATUS_ARB* = 0x00008B83 + GL_OBJECT_INFO_LOG_LENGTH_ARB* = 0x00008B84 + GL_OBJECT_ATTACHED_OBJECTS_ARB* = 0x00008B85 + GL_OBJECT_ACTIVE_UNIFORMS_ARB* = 0x00008B86 + GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB* = 0x00008B87 + GL_OBJECT_SHADER_SOURCE_LENGTH_ARB* = 0x00008B88 + GL_SHADER_OBJECT_ARB* = 0x00008B48 + GL_FLOAT* = 0x00001406 + GL_FLOAT_VEC2_ARB* = 0x00008B50 + GL_FLOAT_VEC3_ARB* = 0x00008B51 + GL_FLOAT_VEC4_ARB* = 0x00008B52 + GL_INT* = 0x00001404 + GL_INT_VEC2_ARB* = 0x00008B53 + GL_INT_VEC3_ARB* = 0x00008B54 + GL_INT_VEC4_ARB* = 0x00008B55 + GL_BOOL_ARB* = 0x00008B56 + GL_BOOL_VEC2_ARB* = 0x00008B57 + GL_BOOL_VEC3_ARB* = 0x00008B58 + GL_BOOL_VEC4_ARB* = 0x00008B59 + GL_FLOAT_MAT2_ARB* = 0x00008B5A + GL_FLOAT_MAT3_ARB* = 0x00008B5B + GL_FLOAT_MAT4_ARB* = 0x00008B5C + +proc glDeleteObjectARB*(obj: GLhandleARB){.dynlib: dllname, + importc: "glDeleteObjectARB".} +proc glGetHandleARB*(pname: TGLenum): GLhandleARB{.dynlib: dllname, + importc: "glGetHandleARB".} +proc glDetachObjectARB*(containerObj: GLhandleARB, attachedObj: GLhandleARB){. + dynlib: dllname, importc: "glDetachObjectARB".} +proc glCreateShaderObjectARB*(shaderType: TGLenum): GLhandleARB{. + dynlib: dllname, importc: "glCreateShaderObjectARB".} +proc glShaderSourceARB*(shaderObj: GLhandleARB, count: TGLsizei, str: PGLvoid, + len: PGLint){.dynlib: dllname, + importc: "glShaderSourceARB".} +proc glCompileShaderARB*(shaderObj: GLhandleARB){.dynlib: dllname, + importc: "glCompileShaderARB".} +proc glCreateProgramObjectARB*(): GLhandleARB{.dynlib: dllname, + importc: "glCreateProgramObjectARB".} +proc glAttachObjectARB*(containerObj: GLhandleARB, obj: GLhandleARB){. + dynlib: dllname, importc: "glAttachObjectARB".} +proc glLinkProgramARB*(programObj: GLhandleARB){.dynlib: dllname, + importc: "glLinkProgramARB".} +proc glUseProgramObjectARB*(programObj: GLhandleARB){.dynlib: dllname, + importc: "glUseProgramObjectARB".} +proc glValidateProgramARB*(programObj: GLhandleARB){.dynlib: dllname, + importc: "glValidateProgramARB".} +proc glUniform1fARB*(location: TGLint, v0: TGLfloat){.dynlib: dllname, + importc: "glUniform1fARB".} +proc glUniform2fARB*(location: TGLint, v0: TGLfloat, v1: TGLfloat){. + dynlib: dllname, importc: "glUniform2fARB".} +proc glUniform3fARB*(location: TGLint, v0: TGLfloat, v1: TGLfloat, v2: TGLfloat){. + dynlib: dllname, importc: "glUniform3fARB".} +proc glUniform4fARB*(location: TGLint, v0: TGLfloat, v1: TGLfloat, v2: TGLfloat, + v3: TGLfloat){.dynlib: dllname, importc: "glUniform4fARB".} +proc glUniform1iARB*(location: TGLint, v0: TGLint){.dynlib: dllname, + importc: "glUniform1iARB".} +proc glUniform2iARB*(location: TGLint, v0: TGLint, v1: TGLint){.dynlib: dllname, + importc: "glUniform2iARB".} +proc glUniform3iARB*(location: TGLint, v0: TGLint, v1: TGLint, v2: TGLint){. + dynlib: dllname, importc: "glUniform3iARB".} +proc glUniform4iARB*(location: TGLint, v0: TGLint, v1: TGLint, v2: TGLint, + v3: TGLint){.dynlib: dllname, importc: "glUniform4iARB".} +proc glUniform1fvARB*(location: TGLint, count: TGLsizei, value: PGLfloat){. + dynlib: dllname, importc: "glUniform1fvARB".} +proc glUniform2fvARB*(location: TGLint, count: TGLsizei, value: PGLfloat){. + dynlib: dllname, importc: "glUniform2fvARB".} +proc glUniform3fvARB*(location: TGLint, count: TGLsizei, value: PGLfloat){. + dynlib: dllname, importc: "glUniform3fvARB".} +proc glUniform4fvARB*(location: TGLint, count: TGLsizei, value: PGLfloat){. + dynlib: dllname, importc: "glUniform4fvARB".} +proc glUniform1ivARB*(location: TGLint, count: TGLsizei, value: PGLint){. + dynlib: dllname, importc: "glUniform1ivARB".} +proc glUniform2ivARB*(location: TGLint, count: TGLsizei, value: PGLint){. + dynlib: dllname, importc: "glUniform2ivARB".} +proc glUniform3ivARB*(location: TGLint, count: TGLsizei, value: PGLint){. + dynlib: dllname, importc: "glUniform3ivARB".} +proc glUniform4ivARB*(location: TGLint, count: TGLsizei, value: PGLint){. + dynlib: dllname, importc: "glUniform4ivARB".} +proc glUniformMatrix2fvARB*(location: TGLint, count: TGLsizei, + transpose: TGLboolean, value: PGLfloat){. + dynlib: dllname, importc: "glUniformMatrix2fvARB".} +proc glUniformMatrix3fvARB*(location: TGLint, count: TGLsizei, + transpose: TGLboolean, value: PGLfloat){. + dynlib: dllname, importc: "glUniformMatrix3fvARB".} +proc glUniformMatrix4fvARB*(location: TGLint, count: TGLsizei, + transpose: TGLboolean, value: PGLfloat){. + dynlib: dllname, importc: "glUniformMatrix4fvARB".} +proc glGetObjectParameterfvARB*(obj: GLhandleARB, pname: TGLenum, + params: PGLfloat){.dynlib: dllname, + importc: "glGetObjectParameterfvARB".} +proc glGetObjectParameterivARB*(obj: GLhandleARB, pname: TGLenum, params: PGLint){. + dynlib: dllname, importc: "glGetObjectParameterivARB".} +proc glGetInfoLogARB*(obj: GLhandleARB, maxLength: TGLsizei, len: PGLsizei, + infoLog: PGLcharARB){.dynlib: dllname, + importc: "glGetInfoLogARB".} +proc glGetAttachedObjectsARB*(containerObj: GLhandleARB, maxCount: TGLsizei, + count: PGLsizei, obj: PGLhandleARB){. + dynlib: dllname, importc: "glGetAttachedObjectsARB".} +proc glGetUniformLocationARB*(programObj: GLhandleARB, name: PGLcharARB): TGLint{. + dynlib: dllname, importc: "glGetUniformLocationARB".} +proc glGetActiveUniformARB*(programObj: GLhandleARB, index: TGLuint, + maxLength: TGLsizei, len: PGLsizei, size: PGLint, + thetype: PGLenum, name: PGLcharARB){. + dynlib: dllname, importc: "glGetActiveUniformARB".} +proc glGetUniformfvARB*(programObj: GLhandleARB, location: TGLint, + params: PGLfloat){.dynlib: dllname, + importc: "glGetUniformfvARB".} +proc glGetUniformivARB*(programObj: GLhandleARB, location: TGLint, + params: PGLint){.dynlib: dllname, + importc: "glGetUniformivARB".} +proc glGetShaderSourceARB*(obj: GLhandleARB, maxLength: TGLsizei, len: PGLsizei, + source: PGLcharARB){.dynlib: dllname, + importc: "glGetShaderSourceARB".} +const + GL_VERTEX_SHADER_ARB* = 0x00008B31 + GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB* = 0x00008B4A + GL_MAX_VARYING_FLOATS_ARB* = 0x00008B4B # GL_MAX_VERTEX_ATTRIBS_ARB { already defined } + # GL_MAX_TEXTURE_IMAGE_UNITS_ARB { already defined } + GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB* = 0x00008B4C + GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB* = 0x00008B4D # + # + # GL_MAX_TEXTURE_COORDS_ARB { already defined } + # + # + # GL_VERTEX_PROGRAM_POINT_SIZE_ARB { already defined } + # + # + # GL_VERTEX_PROGRAM_TWO_SIDE_ARB { already defined } + # GL_OBJECT_TYPE_ARB { already defined } + # GL_OBJECT_SUBTYPE_ARB { already defined } + GL_OBJECT_ACTIVE_ATTRIBUTES_ARB* = 0x00008B89 + GL_OBJECT_ACTIVE_ATTRIBUTE_MAX_LENGTH_ARB* = 0x00008B8A # GL_SHADER_OBJECT_ARB { already defined } + # + # + # GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB { already defined } + # + # + # GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB { already defined } + # + # + # GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB { already defined } + # + # + # GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB { already defined } + # + # + # GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB { already defined } + # + # + # GL_CURRENT_VERTEX_ATTRIB_ARB { already defined } + # + # + # GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB { already defined } + # GL_FLOAT { already defined } + # GL_FLOAT_VEC2_ARB { already defined } + # GL_FLOAT_VEC3_ARB { already defined } + # GL_FLOAT_VEC4_ARB { already defined } + # GL_FLOAT_MAT2_ARB { already defined } + # GL_FLOAT_MAT3_ARB { already defined } + # GL_FLOAT_MAT4_ARB { already defined } + # glVertexAttrib1fARB { already defined } + # glVertexAttrib1sARB { already defined } + # glVertexAttrib1dARB { already defined } + # glVertexAttrib2fARB { already defined } + # glVertexAttrib2sARB { already defined } + # glVertexAttrib2dARB { already defined } + # glVertexAttrib3fARB { already defined } + # glVertexAttrib3sARB { already defined } + # glVertexAttrib3dARB { already defined } + # glVertexAttrib4fARB { already defined } + # glVertexAttrib4sARB { already defined } + # glVertexAttrib4dARB { already defined } + # glVertexAttrib4NubARB { already defined } + # glVertexAttrib1fvARB { already defined } + # glVertexAttrib1svARB { already defined } + # glVertexAttrib1dvARB { already defined } + # glVertexAttrib2fvARB { already defined } + # glVertexAttrib2svARB { already defined } + # glVertexAttrib2dvARB { already defined } + # glVertexAttrib3fvARB { already defined } + # glVertexAttrib3svARB { already defined } + # glVertexAttrib3dvARB { already defined } + # glVertexAttrib4fvARB { already defined } + # glVertexAttrib4svARB { already defined } + # glVertexAttrib4dvARB { already defined } + # glVertexAttrib4ivARB { already defined } + # glVertexAttrib4bvARB { already defined } + # glVertexAttrib4ubvARB { already defined } + # glVertexAttrib4usvARB { already defined } + # glVertexAttrib4uivARB { already defined } + # glVertexAttrib4NbvARB { already defined } + # glVertexAttrib4NsvARB { already defined } + # glVertexAttrib4NivARB { already defined } + # glVertexAttrib4NubvARB { already defined } + # glVertexAttrib4NusvARB { already defined } + # glVertexAttrib4NuivARB { already defined } + # + # + # glVertexAttribPointerARB { already defined } + # + # + # glEnableVertexAttribArrayARB { already defined } + # + # + # glDisableVertexAttribArrayARB { already defined } + +proc glBindAttribLocationARB*(programObj: GLhandleARB, index: TGLuint, + name: PGLcharARB){.dynlib: dllname, + importc: "glBindAttribLocationARB".} +proc glGetActiveAttribARB*(programObj: GLhandleARB, index: TGLuint, + maxLength: TGLsizei, len: PGLsizei, size: PGLint, + thetype: PGLenum, name: PGLcharARB){.dynlib: dllname, + importc: "glGetActiveAttribARB".} +proc glGetAttribLocationARB*(programObj: GLhandleARB, name: PGLcharARB): TGLint{. + dynlib: dllname, importc: "glGetAttribLocationARB".} + # glGetVertexAttribdvARB { already defined } + # glGetVertexAttribfvARB { already defined } + # glGetVertexAttribivARB { already defined } + # glGetVertexAttribPointervARB { already defined } + #***** GL_ARB_fragment_shader *****// +const + GL_FRAGMENT_SHADER_ARB* = 0x00008B30 + GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB* = 0x00008B49 # GL_MAX_TEXTURE_COORDS_ARB { already defined } + # + # + # GL_MAX_TEXTURE_IMAGE_UNITS_ARB { already defined } + # GL_OBJECT_TYPE_ARB { already defined } + # GL_OBJECT_SUBTYPE_ARB { already defined } + # GL_SHADER_OBJECT_ARB { already defined } + #***** GL_ARB_shading_language_100 *****// + #***** GL_ARB_texture_non_power_of_two *****// + #***** GL_ARB_point_sprite *****// + +const + GL_POINT_SPRITE_ARB* = 0x00008861 + GL_COORD_REPLACE_ARB* = 0x00008862 + #***** GL_EXT_depth_bounds_test *****// + +const + constGL_DEPTH_BOUNDS_TEST_EXT* = 0x00008890 + constGL_DEPTH_BOUNDS_EXT* = 0x00008891 + +proc glDepthBoundsEXT*(zmin: TGLclampd, zmax: TGLclampd){.dynlib: dllname, + importc: "glDepthBoundsEXT".} + #***** GL_EXT_texture_mirror_clamp *****// +const + GL_MIRROR_CLAMP_EXT* = 0x00008742 + GL_MIRROR_CLAMP_TO_EDGE_EXT* = 0x00008743 + GL_MIRROR_CLAMP_TO_BORDER_EXT* = 0x00008912 + #***** GL_EXT_blend_equation_separate *****// + +const + GL_BLEND_EQUATION_RGB_EXT* = 0x00008009 + GL_BLEND_EQUATION_ALPHA_EXT* = 0x0000883D + +proc glBlendEquationSeparateEXT*(modeRGB: TGLenum, modeAlpha: TGLenum){. + dynlib: dllname, importc: "glBlendEquationSeparateEXT".} + #***** GL_MESA_pack_invert *****// +const + GL_PACK_INVERT_MESA* = 0x00008758 + #***** GL_MESA_ycbcr_texture *****// + +const + GL_YCBCR_MESA* = 0x00008757 + GL_UNSIGNED_SHORT_8_8_MESA* = 0x000085BA + GL_UNSIGNED_SHORT_8_8_REV_MESA* = 0x000085BB + #***** GL_ARB_fragment_program_shadow *****// + #***** GL_NV_fragment_program_option *****// + #***** GL_EXT_pixel_buffer_object *****// + +const + GL_PIXEL_PACK_BUFFER_EXT* = 0x000088EB + GL_PIXEL_UNPACK_BUFFER_EXT* = 0x000088EC + GL_PIXEL_PACK_BUFFER_BINDING_EXT* = 0x000088ED + GL_PIXEL_UNPACK_BUFFER_BINDING_EXT* = 0x000088EF + #***** GL_NV_fragment_program2 *****// + +const + GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV* = 0x000088F4 + GL_MAX_PROGRAM_CALL_DEPTH_NV* = 0x000088F5 + GL_MAX_PROGRAM_IF_DEPTH_NV* = 0x000088F6 + GL_MAX_PROGRAM_LOOP_DEPTH_NV* = 0x000088F7 + GL_MAX_PROGRAM_LOOP_COUNT_NV* = 0x000088F8 + #***** GL_NV_vertex_program2_option *****// + # GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV { already defined } + # GL_MAX_PROGRAM_CALL_DEPTH_NV { already defined } + #***** GL_NV_vertex_program3 *****// + # GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB { already defined } + #***** GL_ARB_draw_buffers *****// + +const + GL_MAX_DRAW_BUFFERS_ARB* = 0x00008824 + GL_DRAW_BUFFER0_ARB* = 0x00008825 + GL_DRAW_BUFFER1_ARB* = 0x00008826 + GL_DRAW_BUFFER2_ARB* = 0x00008827 + GL_DRAW_BUFFER3_ARB* = 0x00008828 + GL_DRAW_BUFFER4_ARB* = 0x00008829 + GL_DRAW_BUFFER5_ARB* = 0x0000882A + GL_DRAW_BUFFER6_ARB* = 0x0000882B + GL_DRAW_BUFFER7_ARB* = 0x0000882C + GL_DRAW_BUFFER8_ARB* = 0x0000882D + GL_DRAW_BUFFER9_ARB* = 0x0000882E + GL_DRAW_BUFFER10_ARB* = 0x0000882F + GL_DRAW_BUFFER11_ARB* = 0x00008830 + GL_DRAW_BUFFER12_ARB* = 0x00008831 + GL_DRAW_BUFFER13_ARB* = 0x00008832 + GL_DRAW_BUFFER14_ARB* = 0x00008833 + GL_DRAW_BUFFER15_ARB* = 0x00008834 + +proc glDrawBuffersARB*(n: TGLsizei, bufs: PGLenum){.dynlib: dllname, + importc: "glDrawBuffersARB".} + #***** GL_ARB_texture_rectangle *****// +const + GL_TEXTURE_RECTANGLE_ARB* = 0x000084F5 + GL_TEXTURE_BINDING_RECTANGLE_ARB* = 0x000084F6 + GL_PROXY_TEXTURE_RECTANGLE_ARB* = 0x000084F7 + GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB* = 0x000084F8 + #***** GL_ARB_color_buffer_float *****// + +const + GL_RGBA_FLOAT_MODE_ARB* = 0x00008820 + GL_CLAMP_VERTEX_COLOR_ARB* = 0x0000891A + GL_CLAMP_FRAGMENT_COLOR_ARB* = 0x0000891B + GL_CLAMP_READ_COLOR_ARB* = 0x0000891C + GL_FIXED_ONLY_ARB* = 0x0000891D + WGL_TYPE_RGBA_FLOAT_ARB* = 0x000021A0 + +proc glClampColorARB*(target: TGLenum, clamp: TGLenum){.dynlib: dllname, + importc: "glClampColorARB".} + #***** GL_ARB_half_float_pixel *****// +const + GL_HALF_FLOAT_ARB* = 0x0000140B + #***** GL_ARB_texture_float *****// + +const + GL_TEXTURE_RED_TYPE_ARB* = 0x00008C10 + GL_TEXTURE_GREEN_TYPE_ARB* = 0x00008C11 + GL_TEXTURE_BLUE_TYPE_ARB* = 0x00008C12 + GL_TEXTURE_ALPHA_TYPE_ARB* = 0x00008C13 + GL_TEXTURE_LUMINANCE_TYPE_ARB* = 0x00008C14 + GL_TEXTURE_INTENSITY_TYPE_ARB* = 0x00008C15 + GL_TEXTURE_DEPTH_TYPE_ARB* = 0x00008C16 + GL_UNSIGNED_NORMALIZED_ARB* = 0x00008C17 + GL_RGBA32F_ARB* = 0x00008814 + GL_RGB32F_ARB* = 0x00008815 + GL_ALPHA32F_ARB* = 0x00008816 + GL_INTENSITY32F_ARB* = 0x00008817 + GL_LUMINANCE32F_ARB* = 0x00008818 + GL_LUMINANCE_ALPHA32F_ARB* = 0x00008819 + GL_RGBA16F_ARB* = 0x0000881A + GL_RGB16F_ARB* = 0x0000881B + GL_ALPHA16F_ARB* = 0x0000881C + GL_INTENSITY16F_ARB* = 0x0000881D + GL_LUMINANCE16F_ARB* = 0x0000881E + GL_LUMINANCE_ALPHA16F_ARB* = 0x0000881F + #***** GL_EXT_texture_compression_dxt1 *****// + # GL_COMPRESSED_RGB_S3TC_DXT1_EXT { already defined } + # GL_COMPRESSED_RGBA_S3TC_DXT1_EXT { already defined } + #***** GL_ARB_pixel_buffer_object *****// + +const + GL_PIXEL_PACK_BUFFER_ARB* = 0x000088EB + GL_PIXEL_UNPACK_BUFFER_ARB* = 0x000088EC + GL_PIXEL_PACK_BUFFER_BINDING_ARB* = 0x000088ED + GL_PIXEL_UNPACK_BUFFER_BINDING_ARB* = 0x000088EF + #***** GL_EXT_framebuffer_object *****// + +const + GL_FRAMEBUFFER_EXT* = 0x00008D40 + GL_RENDERBUFFER_EXT* = 0x00008D41 + GL_STENCIL_INDEX_EXT* = 0x00008D45 + GL_STENCIL_INDEX1_EXT* = 0x00008D46 + GL_STENCIL_INDEX4_EXT* = 0x00008D47 + GL_STENCIL_INDEX8_EXT* = 0x00008D48 + GL_STENCIL_INDEX16_EXT* = 0x00008D49 + GL_RENDERBUFFER_WIDTH_EXT* = 0x00008D42 + GL_RENDERBUFFER_HEIGHT_EXT* = 0x00008D43 + GL_RENDERBUFFER_INTERNAL_FORMAT_EXT* = 0x00008D44 + GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT* = 0x00008CD0 + GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT* = 0x00008CD1 + GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT* = 0x00008CD2 + GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT* = 0x00008CD3 + GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT* = 0x00008CD4 + GL_COLOR_ATTACHMENT0_EXT* = 0x00008CE0 + GL_COLOR_ATTACHMENT1_EXT* = 0x00008CE1 + GL_COLOR_ATTACHMENT2_EXT* = 0x00008CE2 + GL_COLOR_ATTACHMENT3_EXT* = 0x00008CE3 + GL_COLOR_ATTACHMENT4_EXT* = 0x00008CE4 + GL_COLOR_ATTACHMENT5_EXT* = 0x00008CE5 + GL_COLOR_ATTACHMENT6_EXT* = 0x00008CE6 + GL_COLOR_ATTACHMENT7_EXT* = 0x00008CE7 + GL_COLOR_ATTACHMENT8_EXT* = 0x00008CE8 + GL_COLOR_ATTACHMENT9_EXT* = 0x00008CE9 + GL_COLOR_ATTACHMENT10_EXT* = 0x00008CEA + GL_COLOR_ATTACHMENT11_EXT* = 0x00008CEB + GL_COLOR_ATTACHMENT12_EXT* = 0x00008CEC + GL_COLOR_ATTACHMENT13_EXT* = 0x00008CED + GL_COLOR_ATTACHMENT14_EXT* = 0x00008CEE + GL_COLOR_ATTACHMENT15_EXT* = 0x00008CEF + GL_DEPTH_ATTACHMENT_EXT* = 0x00008D00 + GL_STENCIL_ATTACHMENT_EXT* = 0x00008D20 + GL_FRAMEBUFFER_COMPLETE_EXT* = 0x00008CD5 + GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT* = 0x00008CD6 + GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT* = 0x00008CD7 + GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT* = 0x00008CD8 + GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT* = 0x00008CD9 + GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT* = 0x00008CDA + GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT* = 0x00008CDB + GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT* = 0x00008CDC + GL_FRAMEBUFFER_UNSUPPORTED_EXT* = 0x00008CDD + GL_FRAMEBUFFER_STATUS_ERROR_EXT* = 0x00008CDE + GL_FRAMEBUFFER_BINDING_EXT* = 0x00008CA6 + GL_RENDERBUFFER_BINDING_EXT* = 0x00008CA7 + GL_MAX_COLOR_ATTACHMENTS_EXT* = 0x00008CDF + GL_MAX_RENDERBUFFER_SIZE_EXT* = 0x000084E8 + GL_INVALID_FRAMEBUFFER_OPERATION_EXT* = 0x00000506 + +proc glIsRenderbufferEXT*(renderbuffer: TGLuint): TGLboolean{.dynlib: dllname, + importc: "glIsRenderbufferEXT".} +proc glBindRenderbufferEXT*(target: TGLenum, renderbuffer: TGLuint){. + dynlib: dllname, importc: "glBindRenderbufferEXT".} +proc glDeleteRenderbuffersEXT*(n: TGLsizei, renderbuffers: PGLuint){. + dynlib: dllname, importc: "glDeleteRenderbuffersEXT".} +proc glGenRenderbuffersEXT*(n: TGLsizei, renderbuffers: PGLuint){. + dynlib: dllname, importc: "glGenRenderbuffersEXT".} +proc glRenderbufferStorageEXT*(target: TGLenum, internalformat: TGLenum, + width: TGLsizei, height: TGLsizei){. + dynlib: dllname, importc: "glRenderbufferStorageEXT".} +proc glGetRenderbufferParameterivEXT*(target: TGLenum, pname: TGLenum, + params: PGLint){.dynlib: dllname, + importc: "glGetRenderbufferParameterivEXT".} +proc glIsFramebufferEXT*(framebuffer: TGLuint): TGLboolean{.dynlib: dllname, + importc: "glIsFramebufferEXT".} +proc glBindFramebufferEXT*(target: TGLenum, framebuffer: TGLuint){. + dynlib: dllname, importc: "glBindFramebufferEXT".} +proc glDeleteFramebuffersEXT*(n: TGLsizei, framebuffers: PGLuint){. + dynlib: dllname, importc: "glDeleteFramebuffersEXT".} +proc glGenFramebuffersEXT*(n: TGLsizei, framebuffers: PGLuint){.dynlib: dllname, + importc: "glGenFramebuffersEXT".} +proc glCheckFramebufferStatusEXT*(target: TGLenum): TGLenum{.dynlib: dllname, + importc: "glCheckFramebufferStatusEXT".} +proc glFramebufferTexture1DEXT*(target: TGLenum, attachment: TGLenum, + textarget: TGLenum, texture: TGLuint, + level: TGLint){.dynlib: dllname, + importc: "glFramebufferTexture1DEXT".} +proc glFramebufferTexture2DEXT*(target: TGLenum, attachment: TGLenum, + textarget: TGLenum, texture: TGLuint, + level: TGLint){.dynlib: dllname, + importc: "glFramebufferTexture2DEXT".} +proc glFramebufferTexture3DEXT*(target: TGLenum, attachment: TGLenum, + textarget: TGLenum, texture: TGLuint, + level: TGLint, zoffset: TGLint){. + dynlib: dllname, importc: "glFramebufferTexture3DEXT".} +proc glFramebufferRenderbufferEXT*(target: TGLenum, attachment: TGLenum, + renderbuffertarget: TGLenum, + renderbuffer: TGLuint){.dynlib: dllname, + importc: "glFramebufferRenderbufferEXT".} +proc glGetFramebufferAttachmentParameterivEXT*(target: TGLenum, + attachment: TGLenum, pname: TGLenum, params: PGLint){.dynlib: dllname, + importc: "glGetFramebufferAttachmentParameterivEXT".} +proc glGenerateMipmapEXT*(target: TGLenum){.dynlib: dllname, + importc: "glGenerateMipmapEXT".} + #***** GL_version_1_4 *****// +const + GL_BLEND_DST_RGB* = 0x000080C8 + GL_BLEND_SRC_RGB* = 0x000080C9 + GL_BLEND_DST_ALPHA* = 0x000080CA + GL_BLEND_SRC_ALPHA* = 0x000080CB + GL_POINT_SIZE_MIN* = 0x00008126 + GL_POINT_SIZE_MAX* = 0x00008127 + GL_POINT_FADE_THRESHOLD_SIZE* = 0x00008128 + GL_POINT_DISTANCE_ATTENUATION* = 0x00008129 + GL_GENERATE_MIPMAP* = 0x00008191 + GL_GENERATE_MIPMAP_HINT* = 0x00008192 + GL_DEPTH_COMPONENT16* = 0x000081A5 + GL_DEPTH_COMPONENT24* = 0x000081A6 + GL_DEPTH_COMPONENT32* = 0x000081A7 + GL_MIRRORED_REPEAT* = 0x00008370 + GL_FOG_COORDINATE_SOURCE* = 0x00008450 + GL_FOG_COORDINATE* = 0x00008451 + GL_FRAGMENT_DEPTH* = 0x00008452 + GL_CURRENT_FOG_COORDINATE* = 0x00008453 + GL_FOG_COORDINATE_ARRAY_TYPE* = 0x00008454 + GL_FOG_COORDINATE_ARRAY_STRIDE* = 0x00008455 + GL_FOG_COORDINATE_ARRAY_POINTER* = 0x00008456 + GL_FOG_COORDINATE_ARRAY* = 0x00008457 + GL_COLOR_SUM* = 0x00008458 + GL_CURRENT_SECONDARY_COLOR* = 0x00008459 + GL_SECONDARY_COLOR_ARRAY_SIZE* = 0x0000845A + GL_SECONDARY_COLOR_ARRAY_TYPE* = 0x0000845B + GL_SECONDARY_COLOR_ARRAY_STRIDE* = 0x0000845C + GL_SECONDARY_COLOR_ARRAY_POINTER* = 0x0000845D + GL_SECONDARY_COLOR_ARRAY* = 0x0000845E + GL_MAX_TEXTURE_LOD_BIAS* = 0x000084FD + GL_TEXTURE_FILTER_CONTROL* = 0x00008500 + GL_TEXTURE_LOD_BIAS* = 0x00008501 + GL_INCR_WRAP* = 0x00008507 + GL_DECR_WRAP* = 0x00008508 + GL_TEXTURE_DEPTH_SIZE* = 0x0000884A + GL_DEPTH_TEXTURE_MODE* = 0x0000884B + GL_TEXTURE_COMPARE_MODE* = 0x0000884C + GL_TEXTURE_COMPARE_FUNC* = 0x0000884D + GL_COMPARE_R_TO_TEXTURE* = 0x0000884E + +proc glBlendFuncSeparate*(sfactorRGB: TGLenum, dfactorRGB: TGLenum, + sfactorAlpha: TGLenum, dfactorAlpha: TGLenum){. + dynlib: dllname, importc: "glBlendFuncSeparate".} +proc glFogCoordf*(coord: TGLfloat){.dynlib: dllname, importc: "glFogCoordf".} +proc glFogCoordfv*(coord: PGLfloat){.dynlib: dllname, importc: "glFogCoordfv".} +proc glFogCoordd*(coord: TGLdouble){.dynlib: dllname, importc: "glFogCoordd".} +proc glFogCoorddv*(coord: PGLdouble){.dynlib: dllname, importc: "glFogCoorddv".} +proc glFogCoordPointer*(thetype: TGLenum, stride: TGLsizei, pointer: PGLvoid){. + dynlib: dllname, importc: "glFogCoordPointer".} +proc glMultiDrawArrays*(mode: TGLenum, first: PGLint, count: PGLsizei, + primcount: TGLsizei){.dynlib: dllname, + importc: "glMultiDrawArrays".} +proc glMultiDrawElements*(mode: TGLenum, count: PGLsizei, thetype: TGLenum, + indices: PGLvoid, primcount: TGLsizei){. + dynlib: dllname, importc: "glMultiDrawElements".} +proc glPointParameterf*(pname: TGLenum, param: TGLfloat){.dynlib: dllname, + importc: "glPointParameterf".} +proc glPointParameterfv*(pname: TGLenum, params: PGLfloat){.dynlib: dllname, + importc: "glPointParameterfv".} +proc glPointParameteri*(pname: TGLenum, param: TGLint){.dynlib: dllname, + importc: "glPointParameteri".} +proc glPointParameteriv*(pname: TGLenum, params: PGLint){.dynlib: dllname, + importc: "glPointParameteriv".} +proc glSecondaryColor3b*(red: TGLByte, green: TGLByte, blue: TGLByte){. + dynlib: dllname, importc: "glSecondaryColor3b".} +proc glSecondaryColor3bv*(v: PGLbyte){.dynlib: dllname, + importc: "glSecondaryColor3bv".} +proc glSecondaryColor3d*(red: TGLdouble, green: TGLdouble, blue: TGLdouble){. + dynlib: dllname, importc: "glSecondaryColor3d".} +proc glSecondaryColor3dv*(v: PGLdouble){.dynlib: dllname, + importc: "glSecondaryColor3dv".} +proc glSecondaryColor3f*(red: TGLfloat, green: TGLfloat, blue: TGLfloat){. + dynlib: dllname, importc: "glSecondaryColor3f".} +proc glSecondaryColor3fv*(v: PGLfloat){.dynlib: dllname, + importc: "glSecondaryColor3fv".} +proc glSecondaryColor3i*(red: TGLint, green: TGLint, blue: TGLint){. + dynlib: dllname, importc: "glSecondaryColor3i".} +proc glSecondaryColor3iv*(v: PGLint){.dynlib: dllname, + importc: "glSecondaryColor3iv".} +proc glSecondaryColor3s*(red: TGLshort, green: TGLshort, blue: TGLshort){. + dynlib: dllname, importc: "glSecondaryColor3s".} +proc glSecondaryColor3sv*(v: PGLshort){.dynlib: dllname, + importc: "glSecondaryColor3sv".} +proc glSecondaryColor3ub*(red: TGLubyte, green: TGLubyte, blue: TGLubyte){. + dynlib: dllname, importc: "glSecondaryColor3ub".} +proc glSecondaryColor3ubv*(v: PGLubyte){.dynlib: dllname, + importc: "glSecondaryColor3ubv".} +proc glSecondaryColor3ui*(red: TGLuint, green: TGLuint, blue: TGLuint){. + dynlib: dllname, importc: "glSecondaryColor3ui".} +proc glSecondaryColor3uiv*(v: PGLuint){.dynlib: dllname, + importc: "glSecondaryColor3uiv".} +proc glSecondaryColor3us*(red: TGLushort, green: TGLushort, blue: TGLushort){. + dynlib: dllname, importc: "glSecondaryColor3us".} +proc glSecondaryColor3usv*(v: PGLushort){.dynlib: dllname, + importc: "glSecondaryColor3usv".} +proc glSecondaryColorPointer*(size: TGLint, thetype: TGLenum, stride: TGLsizei, + pointer: PGLvoid){.dynlib: dllname, + importc: "glSecondaryColorPointer".} +proc glWindowPos2d*(x: TGLdouble, y: TGLdouble){.dynlib: dllname, + importc: "glWindowPos2d".} +proc glWindowPos2dv*(v: PGLdouble){.dynlib: dllname, importc: "glWindowPos2dv".} +proc glWindowPos2f*(x: TGLfloat, y: TGLfloat){.dynlib: dllname, + importc: "glWindowPos2f".} +proc glWindowPos2fv*(v: PGLfloat){.dynlib: dllname, importc: "glWindowPos2fv".} +proc glWindowPos2i*(x: TGLint, y: TGLint){.dynlib: dllname, + importc: "glWindowPos2i".} +proc glWindowPos2iv*(v: PGLint){.dynlib: dllname, importc: "glWindowPos2iv".} +proc glWindowPos2s*(x: TGLshort, y: TGLshort){.dynlib: dllname, + importc: "glWindowPos2s".} +proc glWindowPos2sv*(v: PGLshort){.dynlib: dllname, importc: "glWindowPos2sv".} +proc glWindowPos3d*(x: TGLdouble, y: TGLdouble, z: TGLdouble){.dynlib: dllname, + importc: "glWindowPos3d".} +proc glWindowPos3dv*(v: PGLdouble){.dynlib: dllname, importc: "glWindowPos3dv".} +proc glWindowPos3f*(x: TGLfloat, y: TGLfloat, z: TGLfloat){.dynlib: dllname, + importc: "glWindowPos3f".} +proc glWindowPos3fv*(v: PGLfloat){.dynlib: dllname, importc: "glWindowPos3fv".} +proc glWindowPos3i*(x: TGLint, y: TGLint, z: TGLint){.dynlib: dllname, + importc: "glWindowPos3i".} +proc glWindowPos3iv*(v: PGLint){.dynlib: dllname, importc: "glWindowPos3iv".} +proc glWindowPos3s*(x: TGLshort, y: TGLshort, z: TGLshort){.dynlib: dllname, + importc: "glWindowPos3s".} +proc glWindowPos3sv*(v: PGLshort){.dynlib: dllname, importc: "glWindowPos3sv".} + #***** GL_version_1_5 *****// +const + GL_BUFFER_SIZE* = 0x00008764 + GL_BUFFER_USAGE* = 0x00008765 + GL_QUERY_COUNTER_BITS* = 0x00008864 + GL_CURRENT_QUERY* = 0x00008865 + GL_QUERY_RESULT* = 0x00008866 + GL_QUERY_RESULT_AVAILABLE* = 0x00008867 + GL_ARRAY_BUFFER* = 0x00008892 + GL_ELEMENT_ARRAY_BUFFER* = 0x00008893 + GL_ARRAY_BUFFER_BINDING* = 0x00008894 + GL_ELEMENT_ARRAY_BUFFER_BINDING* = 0x00008895 + GL_VERTEX_ARRAY_BUFFER_BINDING* = 0x00008896 + GL_NORMAL_ARRAY_BUFFER_BINDING* = 0x00008897 + GL_COLOR_ARRAY_BUFFER_BINDING* = 0x00008898 + GL_INDEX_ARRAY_BUFFER_BINDING* = 0x00008899 + GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING* = 0x0000889A + GL_EDGE_FLAG_ARRAY_BUFFER_BINDING* = 0x0000889B + GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING* = 0x0000889C + GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING* = 0x0000889D + GL_WEIGHT_ARRAY_BUFFER_BINDING* = 0x0000889E + GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING* = 0x0000889F + GL_READ_ONLY* = 0x000088B8 + GL_WRITE_ONLY* = 0x000088B9 + GL_READ_WRITE* = 0x000088BA + GL_BUFFER_ACCESS* = 0x000088BB + GL_BUFFER_MAPPED* = 0x000088BC + GL_BUFFER_MAP_POINTER* = 0x000088BD + GL_STREAM_DRAW* = 0x000088E0 + GL_STREAM_READ* = 0x000088E1 + GL_STREAM_COPY* = 0x000088E2 + GL_STATIC_DRAW* = 0x000088E4 + GL_STATIC_READ* = 0x000088E5 + GL_STATIC_COPY* = 0x000088E6 + GL_DYNAMIC_DRAW* = 0x000088E8 + GL_DYNAMIC_READ* = 0x000088E9 + GL_DYNAMIC_COPY* = 0x000088EA + GL_SAMPLES_PASSED* = 0x00008914 + GL_FOG_COORD_SRC* = 0x00008450 + GL_FOG_COORD* = 0x00008451 + GL_CURRENT_FOG_COORD* = 0x00008453 + GL_FOG_COORD_ARRAY_TYPE* = 0x00008454 + GL_FOG_COORD_ARRAY_STRIDE* = 0x00008455 + GL_FOG_COORD_ARRAY_POINTER* = 0x00008456 + GL_FOG_COORD_ARRAY* = 0x00008457 + GL_FOG_COORD_ARRAY_BUFFER_BINDING* = 0x0000889D + GL_SRC0_RGB* = 0x00008580 + GL_SRC1_RGB* = 0x00008581 + GL_SRC2_RGB* = 0x00008582 + GL_SRC0_ALPHA* = 0x00008588 + GL_SRC1_ALPHA* = 0x00008589 + GL_SRC2_ALPHA* = 0x0000858A + +proc glGenQueries*(n: TGLsizei, ids: PGLuint){.dynlib: dllname, + importc: "glGenQueries".} +proc glDeleteQueries*(n: TGLsizei, ids: PGLuint){.dynlib: dllname, + importc: "glDeleteQueries".} +proc glIsQuery*(id: TGLuint): TGLboolean{.dynlib: dllname, importc: "glIsQuery".} +proc glBeginQuery*(target: TGLenum, id: TGLuint){.dynlib: dllname, + importc: "glBeginQuery".} +proc glEndQuery*(target: TGLenum){.dynlib: dllname, importc: "glEndQuery".} +proc glGetQueryiv*(target: TGLenum, pname: TGLenum, params: PGLint){. + dynlib: dllname, importc: "glGetQueryiv".} +proc glGetQueryObjectiv*(id: TGLuint, pname: TGLenum, params: PGLint){. + dynlib: dllname, importc: "glGetQueryObjectiv".} +proc glGetQueryObjectuiv*(id: TGLuint, pname: TGLenum, params: PGLuint){. + dynlib: dllname, importc: "glGetQueryObjectuiv".} +proc glBindBuffer*(target: TGLenum, buffer: TGLuint){.dynlib: dllname, + importc: "glBindBuffer".} +proc glDeleteBuffers*(n: TGLsizei, buffers: PGLuint){.dynlib: dllname, + importc: "glDeleteBuffers".} +proc glGenBuffers*(n: TGLsizei, buffers: PGLuint){.dynlib: dllname, + importc: "glGenBuffers".} +proc glIsBuffer*(buffer: TGLuint): TGLboolean{.dynlib: dllname, + importc: "glIsBuffer".} +proc glBufferData*(target: TGLenum, size: GLsizeiptr, data: PGLvoid, + usage: TGLenum){.dynlib: dllname, importc: "glBufferData".} +proc glBufferSubData*(target: TGLenum, offset: GLintptr, size: GLsizeiptr, + data: PGLvoid){.dynlib: dllname, + importc: "glBufferSubData".} +proc glGetBufferSubData*(target: TGLenum, offset: GLintptr, size: GLsizeiptr, + data: PGLvoid){.dynlib: dllname, + importc: "glGetBufferSubData".} +proc glMapBuffer*(target: TGLenum, access: TGLenum): PGLvoid{.dynlib: dllname, + importc: "glMapBuffer".} +proc glUnmapBuffer*(target: TGLenum): TGLboolean{.dynlib: dllname, + importc: "glUnmapBuffer".} +proc glGetBufferParameteriv*(target: TGLenum, pname: TGLenum, params: PGLint){. + dynlib: dllname, importc: "glGetBufferParameteriv".} +proc glGetBufferPointerv*(target: TGLenum, pname: TGLenum, params: PGLvoid){. + dynlib: dllname, importc: "glGetBufferPointerv".} + #***** GL_version_2_0 *****// +const + GL_BLEND_EQUATION_RGB* = 0x00008009 + GL_VERTEX_ATTRIB_ARRAY_ENABLED* = 0x00008622 + GL_VERTEX_ATTRIB_ARRAY_SIZE* = 0x00008623 + GL_VERTEX_ATTRIB_ARRAY_STRIDE* = 0x00008624 + GL_VERTEX_ATTRIB_ARRAY_TYPE* = 0x00008625 + GL_CURRENT_VERTEX_ATTRIB* = 0x00008626 + GL_VERTEX_PROGRAM_POINT_SIZE* = 0x00008642 + GL_VERTEX_PROGRAM_TWO_SIDE* = 0x00008643 + GL_VERTEX_ATTRIB_ARRAY_POINTER* = 0x00008645 + GL_STENCIL_BACK_FUNC* = 0x00008800 + GL_STENCIL_BACK_FAIL* = 0x00008801 + GL_STENCIL_BACK_PASS_DEPTH_FAIL* = 0x00008802 + GL_STENCIL_BACK_PASS_DEPTH_PASS* = 0x00008803 + GL_MAX_DRAW_BUFFERS* = 0x00008824 + GL_DRAW_BUFFER0* = 0x00008825 + GL_DRAW_BUFFER1* = 0x00008826 + GL_DRAW_BUFFER2* = 0x00008827 + GL_DRAW_BUFFER3* = 0x00008828 + GL_DRAW_BUFFER4* = 0x00008829 + GL_DRAW_BUFFER5* = 0x0000882A + GL_DRAW_BUFFER6* = 0x0000882B + GL_DRAW_BUFFER7* = 0x0000882C + GL_DRAW_BUFFER8* = 0x0000882D + GL_DRAW_BUFFER9* = 0x0000882E + GL_DRAW_BUFFER10* = 0x0000882F + GL_DRAW_BUFFER11* = 0x00008830 + GL_DRAW_BUFFER12* = 0x00008831 + GL_DRAW_BUFFER13* = 0x00008832 + GL_DRAW_BUFFER14* = 0x00008833 + GL_DRAW_BUFFER15* = 0x00008834 + GL_BLEND_EQUATION_ALPHA* = 0x0000883D + GL_POINT_SPRITE* = 0x00008861 + GL_COORD_REPLACE* = 0x00008862 + GL_MAX_VERTEX_ATTRIBS* = 0x00008869 + GL_VERTEX_ATTRIB_ARRAY_NORMALIZED* = 0x0000886A + GL_MAX_TEXTURE_COORDS* = 0x00008871 + GL_MAX_TEXTURE_IMAGE_UNITS* = 0x00008872 + GL_FRAGMENT_SHADER* = 0x00008B30 + GL_VERTEX_SHADER* = 0x00008B31 + GL_MAX_FRAGMENT_UNIFORM_COMPONENTS* = 0x00008B49 + GL_MAX_VERTEX_UNIFORM_COMPONENTS* = 0x00008B4A + GL_MAX_VARYING_FLOATS* = 0x00008B4B + GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS* = 0x00008B4C + GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS* = 0x00008B4D + GL_SHADER_TYPE* = 0x00008B4F + GL_FLOAT_VEC2* = 0x00008B50 + GL_FLOAT_VEC3* = 0x00008B51 + GL_FLOAT_VEC4* = 0x00008B52 + GL_INT_VEC2* = 0x00008B53 + GL_INT_VEC3* = 0x00008B54 + GL_INT_VEC4* = 0x00008B55 + GL_BOOL* = 0x00008B56 + GL_BOOL_VEC2* = 0x00008B57 + GL_BOOL_VEC3* = 0x00008B58 + GL_BOOL_VEC4* = 0x00008B59 + GL_FLOAT_MAT2* = 0x00008B5A + GL_FLOAT_MAT3* = 0x00008B5B + GL_FLOAT_MAT4* = 0x00008B5C + GL_SAMPLER_1D* = 0x00008B5D + GL_SAMPLER_2D* = 0x00008B5E + GL_SAMPLER_3D* = 0x00008B5F + GL_SAMPLER_CUBE* = 0x00008B60 + GL_SAMPLER_1D_SHADOW* = 0x00008B61 + GL_SAMPLER_2D_SHADOW* = 0x00008B62 + GL_DELETE_STATUS* = 0x00008B80 + GL_COMPILE_STATUS* = 0x00008B81 + GL_LINK_STATUS* = 0x00008B82 + GL_VALIDATE_STATUS* = 0x00008B83 + GL_INFO_LOG_LENGTH* = 0x00008B84 + GL_ATTACHED_SHADERS* = 0x00008B85 + GL_ACTIVE_UNIFORMS* = 0x00008B86 + GL_ACTIVE_UNIFORM_MAX_LENGTH* = 0x00008B87 + GL_SHADER_SOURCE_LENGTH* = 0x00008B88 + GL_ACTIVE_ATTRIBUTES* = 0x00008B89 + GL_ACTIVE_ATTRIBUTE_MAX_LENGTH* = 0x00008B8A + GL_FRAGMENT_SHADER_DERIVATIVE_HINT* = 0x00008B8B + GL_SHADING_LANGUAGE_VERSION* = 0x00008B8C + GL_CURRENT_PROGRAM* = 0x00008B8D + GL_POINT_SPRITE_COORD_ORIGIN* = 0x00008CA0 + GL_LOWER_LEFT* = 0x00008CA1 + GL_UPPER_LEFT* = 0x00008CA2 + GL_STENCIL_BACK_REF* = 0x00008CA3 + GL_STENCIL_BACK_VALUE_MASK* = 0x00008CA4 + GL_STENCIL_BACK_WRITEMASK* = 0x00008CA5 + +{.pop.} \ No newline at end of file diff --git a/tests/manyloc/keineschweine/lib/glu.nim b/tests/manyloc/keineschweine/lib/glu.nim new file mode 100644 index 0000000000..e00120d83b --- /dev/null +++ b/tests/manyloc/keineschweine/lib/glu.nim @@ -0,0 +1,335 @@ +# +# +# Adaption of the delphi3d.net OpenGL units to FreePascal +# Sebastian Guenther (sg@freepascal.org) in 2002 +# These units are free to use +#****************************************************************************** +# Converted to Delphi by Tom Nuydens (tom@delphi3d.net) +# For the latest updates, visit Delphi3D: http://www.delphi3d.net +#****************************************************************************** + +import + GL + +when defined(windows): + {.push, callconv: stdcall.} +else: + {.push, callconv: cdecl.} + +when defined(windows): + const + dllname = "glu32.dll" +elif defined(macosx): + const + dllname = "/System/Library/Frameworks/OpenGL.framework/Libraries/libGLU.dylib" +else: + const + dllname = "libGLU.so.1" +type + TViewPortArray* = array[0..3, TGLint] + T16dArray* = array[0..15, TGLdouble] + TCallBack* = proc () + T3dArray* = array[0..2, TGLdouble] + T4pArray* = array[0..3, Pointer] + T4fArray* = array[0..3, TGLfloat] + PPointer* = ptr Pointer + +type + GLUnurbs*{.final.} = object + PGLUnurbs* = ptr GLUnurbs + GLUquadric*{.final.} = object + PGLUquadric* = ptr GLUquadric + GLUtesselator*{.final.} = object + PGLUtesselator* = ptr GLUtesselator # backwards compatibility: + GLUnurbsObj* = GLUnurbs + PGLUnurbsObj* = PGLUnurbs + GLUquadricObj* = GLUquadric + PGLUquadricObj* = PGLUquadric + GLUtesselatorObj* = GLUtesselator + PGLUtesselatorObj* = PGLUtesselator + GLUtriangulatorObj* = GLUtesselator + PGLUtriangulatorObj* = PGLUtesselator + TGLUnurbs* = GLUnurbs + TGLUquadric* = GLUquadric + TGLUtesselator* = GLUtesselator + TGLUnurbsObj* = GLUnurbsObj + TGLUquadricObj* = GLUquadricObj + TGLUtesselatorObj* = GLUtesselatorObj + TGLUtriangulatorObj* = GLUtriangulatorObj + +proc gluErrorString*(errCode: TGLenum): cstring{.dynlib: dllname, + importc: "gluErrorString".} +proc gluErrorUnicodeStringEXT*(errCode: TGLenum): ptr int16{.dynlib: dllname, + importc: "gluErrorUnicodeStringEXT".} +proc gluGetString*(name: TGLenum): cstring{.dynlib: dllname, + importc: "gluGetString".} +proc gluOrtho2D*(left, right, bottom, top: TGLdouble){.dynlib: dllname, + importc: "gluOrtho2D".} +proc gluPerspective*(fovy, aspect, zNear, zFar: TGLdouble){.dynlib: dllname, + importc: "gluPerspective".} +proc gluPickMatrix*(x, y, width, height: TGLdouble, viewport: var TViewPortArray){. + dynlib: dllname, importc: "gluPickMatrix".} +proc gluLookAt*(eyex, eyey, eyez, centerx, centery, centerz, upx, upy, upz: TGLdouble){. + dynlib: dllname, importc: "gluLookAt".} +proc gluProject*(objx, objy, objz: TGLdouble, + modelMatrix, projMatrix: var T16dArray, + viewport: var TViewPortArray, winx, winy, winz: PGLdouble): int{. + dynlib: dllname, importc: "gluProject".} +proc gluUnProject*(winx, winy, winz: TGLdouble, + modelMatrix, projMatrix: var T16dArray, + viewport: var TViewPortArray, objx, objy, objz: PGLdouble): int{. + dynlib: dllname, importc: "gluUnProject".} +proc gluScaleImage*(format: TGLenum, widthin, heightin: TGLint, typein: TGLenum, + datain: Pointer, widthout, heightout: TGLint, + typeout: TGLenum, dataout: Pointer): int{.dynlib: dllname, + importc: "gluScaleImage".} +proc gluBuild1DMipmaps*(target: TGLenum, components, width: TGLint, + format, atype: TGLenum, data: Pointer): int{. + dynlib: dllname, importc: "gluBuild1DMipmaps".} +proc gluBuild2DMipmaps*(target: TGLenum, components, width, height: TGLint, + format, atype: TGLenum, data: Pointer): int{. + dynlib: dllname, importc: "gluBuild2DMipmaps".} +proc gluNewQuadric*(): PGLUquadric{.dynlib: dllname, importc: "gluNewQuadric".} +proc gluDeleteQuadric*(state: PGLUquadric){.dynlib: dllname, + importc: "gluDeleteQuadric".} +proc gluQuadricNormals*(quadObject: PGLUquadric, normals: TGLenum){. + dynlib: dllname, importc: "gluQuadricNormals".} +proc gluQuadricTexture*(quadObject: PGLUquadric, textureCoords: TGLboolean){. + dynlib: dllname, importc: "gluQuadricTexture".} +proc gluQuadricOrientation*(quadObject: PGLUquadric, orientation: TGLenum){. + dynlib: dllname, importc: "gluQuadricOrientation".} +proc gluQuadricDrawStyle*(quadObject: PGLUquadric, drawStyle: TGLenum){. + dynlib: dllname, importc: "gluQuadricDrawStyle".} +proc gluCylinder*(qobj: PGLUquadric, baseRadius, topRadius, height: TGLdouble, + slices, stacks: TGLint){.dynlib: dllname, + importc: "gluCylinder".} +proc gluDisk*(qobj: PGLUquadric, innerRadius, outerRadius: TGLdouble, + slices, loops: TGLint){.dynlib: dllname, importc: "gluDisk".} +proc gluPartialDisk*(qobj: PGLUquadric, innerRadius, outerRadius: TGLdouble, + slices, loops: TGLint, startAngle, sweepAngle: TGLdouble){. + dynlib: dllname, importc: "gluPartialDisk".} +proc gluSphere*(qobj: PGLuquadric, radius: TGLdouble, slices, stacks: TGLint){. + dynlib: dllname, importc: "gluSphere".} +proc gluQuadricCallback*(qobj: PGLUquadric, which: TGLenum, fn: TCallBack){. + dynlib: dllname, importc: "gluQuadricCallback".} +proc gluNewTess*(): PGLUtesselator{.dynlib: dllname, importc: "gluNewTess".} +proc gluDeleteTess*(tess: PGLUtesselator){.dynlib: dllname, + importc: "gluDeleteTess".} +proc gluTessBeginPolygon*(tess: PGLUtesselator, polygon_data: Pointer){. + dynlib: dllname, importc: "gluTessBeginPolygon".} +proc gluTessBeginContour*(tess: PGLUtesselator){.dynlib: dllname, + importc: "gluTessBeginContour".} +proc gluTessVertex*(tess: PGLUtesselator, coords: var T3dArray, data: Pointer){. + dynlib: dllname, importc: "gluTessVertex".} +proc gluTessEndContour*(tess: PGLUtesselator){.dynlib: dllname, + importc: "gluTessEndContour".} +proc gluTessEndPolygon*(tess: PGLUtesselator){.dynlib: dllname, + importc: "gluTessEndPolygon".} +proc gluTessProperty*(tess: PGLUtesselator, which: TGLenum, value: TGLdouble){. + dynlib: dllname, importc: "gluTessProperty".} +proc gluTessNormal*(tess: PGLUtesselator, x, y, z: TGLdouble){.dynlib: dllname, + importc: "gluTessNormal".} +proc gluTessCallback*(tess: PGLUtesselator, which: TGLenum, fn: TCallBack){. + dynlib: dllname, importc: "gluTessCallback".} +proc gluGetTessProperty*(tess: PGLUtesselator, which: TGLenum, value: PGLdouble){. + dynlib: dllname, importc: "gluGetTessProperty".} +proc gluNewNurbsRenderer*(): PGLUnurbs{.dynlib: dllname, + importc: "gluNewNurbsRenderer".} +proc gluDeleteNurbsRenderer*(nobj: PGLUnurbs){.dynlib: dllname, + importc: "gluDeleteNurbsRenderer".} +proc gluBeginSurface*(nobj: PGLUnurbs){.dynlib: dllname, + importc: "gluBeginSurface".} +proc gluBeginCurve*(nobj: PGLUnurbs){.dynlib: dllname, importc: "gluBeginCurve".} +proc gluEndCurve*(nobj: PGLUnurbs){.dynlib: dllname, importc: "gluEndCurve".} +proc gluEndSurface*(nobj: PGLUnurbs){.dynlib: dllname, importc: "gluEndSurface".} +proc gluBeginTrim*(nobj: PGLUnurbs){.dynlib: dllname, importc: "gluBeginTrim".} +proc gluEndTrim*(nobj: PGLUnurbs){.dynlib: dllname, importc: "gluEndTrim".} +proc gluPwlCurve*(nobj: PGLUnurbs, count: TGLint, aarray: PGLfloat, + stride: TGLint, atype: TGLenum){.dynlib: dllname, + importc: "gluPwlCurve".} +proc gluNurbsCurve*(nobj: PGLUnurbs, nknots: TGLint, knot: PGLfloat, + stride: TGLint, ctlarray: PGLfloat, order: TGLint, + atype: TGLenum){.dynlib: dllname, importc: "gluNurbsCurve".} +proc gluNurbsSurface*(nobj: PGLUnurbs, sknot_count: TGLint, sknot: PGLfloat, + tknot_count: TGLint, tknot: PGLfloat, + s_stride, t_stride: TGLint, ctlarray: PGLfloat, + sorder, torder: TGLint, atype: TGLenum){.dynlib: dllname, + importc: "gluNurbsSurface".} +proc gluLoadSamplingMatrices*(nobj: PGLUnurbs, + modelMatrix, projMatrix: var T16dArray, + viewport: var TViewPortArray){.dynlib: dllname, + importc: "gluLoadSamplingMatrices".} +proc gluNurbsProperty*(nobj: PGLUnurbs, aproperty: TGLenum, value: TGLfloat){. + dynlib: dllname, importc: "gluNurbsProperty".} +proc gluGetNurbsProperty*(nobj: PGLUnurbs, aproperty: TGLenum, value: PGLfloat){. + dynlib: dllname, importc: "gluGetNurbsProperty".} +proc gluNurbsCallback*(nobj: PGLUnurbs, which: TGLenum, fn: TCallBack){. + dynlib: dllname, importc: "gluNurbsCallback".} + #*** Callback function prototypes *** +type # gluQuadricCallback + GLUquadricErrorProc* = proc (p: TGLenum) # gluTessCallback + GLUtessBeginProc* = proc (p: TGLenum) + GLUtessEdgeFlagProc* = proc (p: TGLboolean) + GLUtessVertexProc* = proc (p: Pointer) + GLUtessEndProc* = proc () + GLUtessErrorProc* = proc (p: TGLenum) + GLUtessCombineProc* = proc (p1: var T3dArray, p2: T4pArray, p3: T4fArray, + p4: PPointer) + GLUtessBeginDataProc* = proc (p1: TGLenum, p2: Pointer) + GLUtessEdgeFlagDataProc* = proc (p1: TGLboolean, p2: Pointer) + GLUtessVertexDataProc* = proc (p1, p2: Pointer) + GLUtessEndDataProc* = proc (p: Pointer) + GLUtessErrorDataProc* = proc (p1: TGLenum, p2: Pointer) + GLUtessCombineDataProc* = proc (p1: var T3dArray, p2: var T4pArray, + p3: var T4fArray, p4: PPointer, p5: Pointer) # + # + # gluNurbsCallback + GLUnurbsErrorProc* = proc (p: TGLenum) #*** Generic constants ****/ + +const # Version + GLU_VERSION_1_1* = 1 + GLU_VERSION_1_2* = 1 # Errors: (return value 0 = no error) + GLU_INVALID_ENUM* = 100900 + GLU_INVALID_VALUE* = 100901 + GLU_OUT_OF_MEMORY* = 100902 + GLU_INCOMPATIBLE_GL_VERSION* = 100903 # StringName + GLU_VERSION* = 100800 + GLU_EXTENSIONS* = 100801 # Boolean + GLU_TRUE* = GL_TRUE + GLU_FALSE* = GL_FALSE #*** Quadric constants ****/ + # QuadricNormal + GLU_SMOOTH* = 100000 + GLU_FLAT* = 100001 + GLU_NONE* = 100002 # QuadricDrawStyle + GLU_POINT* = 100010 + GLU_LINE* = 100011 + GLU_FILL* = 100012 + GLU_SILHOUETTE* = 100013 # QuadricOrientation + GLU_OUTSIDE* = 100020 + GLU_INSIDE* = 100021 # Callback types: + # GLU_ERROR = 100103; + #*** Tesselation constants ****/ + GLU_TESS_MAX_COORD* = 1.00000e+150 # TessProperty + GLU_TESS_WINDING_RULE* = 100140 + GLU_TESS_BOUNDARY_ONLY* = 100141 + GLU_TESS_TOLERANCE* = 100142 # TessWinding + GLU_TESS_WINDING_ODD* = 100130 + GLU_TESS_WINDING_NONZERO* = 100131 + GLU_TESS_WINDING_POSITIVE* = 100132 + GLU_TESS_WINDING_NEGATIVE* = 100133 + GLU_TESS_WINDING_ABS_GEQ_TWO* = 100134 # TessCallback + GLU_TESS_BEGIN* = 100100 # void (CALLBACK*)(TGLenum type) + constGLU_TESS_VERTEX* = 100101 # void (CALLBACK*)(void *data) + GLU_TESS_END* = 100102 # void (CALLBACK*)(void) + GLU_TESS_ERROR* = 100103 # void (CALLBACK*)(TGLenum errno) + GLU_TESS_EDGE_FLAG* = 100104 # void (CALLBACK*)(TGLboolean boundaryEdge) + GLU_TESS_COMBINE* = 100105 # void (CALLBACK*)(TGLdouble coords[3], + # void *data[4], + # TGLfloat weight[4], + # void **dataOut) + GLU_TESS_BEGIN_DATA* = 100106 # void (CALLBACK*)(TGLenum type, + # void *polygon_data) + GLU_TESS_VERTEX_DATA* = 100107 # void (CALLBACK*)(void *data, + # void *polygon_data) + GLU_TESS_END_DATA* = 100108 # void (CALLBACK*)(void *polygon_data) + GLU_TESS_ERROR_DATA* = 100109 # void (CALLBACK*)(TGLenum errno, + # void *polygon_data) + GLU_TESS_EDGE_FLAG_DATA* = 100110 # void (CALLBACK*)(TGLboolean boundaryEdge, + # void *polygon_data) + GLU_TESS_COMBINE_DATA* = 100111 # void (CALLBACK*)(TGLdouble coords[3], + # void *data[4], + # TGLfloat weight[4], + # void **dataOut, + # void *polygon_data) + # TessError + GLU_TESS_ERROR1* = 100151 + GLU_TESS_ERROR2* = 100152 + GLU_TESS_ERROR3* = 100153 + GLU_TESS_ERROR4* = 100154 + GLU_TESS_ERROR5* = 100155 + GLU_TESS_ERROR6* = 100156 + GLU_TESS_ERROR7* = 100157 + GLU_TESS_ERROR8* = 100158 + GLU_TESS_MISSING_BEGIN_POLYGON* = GLU_TESS_ERROR1 + GLU_TESS_MISSING_BEGIN_CONTOUR* = GLU_TESS_ERROR2 + GLU_TESS_MISSING_END_POLYGON* = GLU_TESS_ERROR3 + GLU_TESS_MISSING_END_CONTOUR* = GLU_TESS_ERROR4 + GLU_TESS_COORD_TOO_LARGE* = GLU_TESS_ERROR5 + GLU_TESS_NEED_COMBINE_CALLBACK* = GLU_TESS_ERROR6 #*** NURBS constants ****/ + # NurbsProperty + GLU_AUTO_LOAD_MATRIX* = 100200 + GLU_CULLING* = 100201 + GLU_SAMPLING_TOLERANCE* = 100203 + GLU_DISPLAY_MODE* = 100204 + GLU_PARAMETRIC_TOLERANCE* = 100202 + GLU_SAMPLING_METHOD* = 100205 + GLU_U_STEP* = 100206 + GLU_V_STEP* = 100207 # NurbsSampling + GLU_PATH_LENGTH* = 100215 + GLU_PARAMETRIC_ERROR* = 100216 + GLU_DOMAIN_DISTANCE* = 100217 # NurbsTrim + GLU_MAP1_TRIM_2* = 100210 + GLU_MAP1_TRIM_3* = 100211 # NurbsDisplay + # GLU_FILL = 100012; + GLU_OUTLINE_POLYGON* = 100240 + GLU_OUTLINE_PATCH* = 100241 # NurbsCallback + # GLU_ERROR = 100103; + # NurbsErrors + GLU_NURBS_ERROR1* = 100251 + GLU_NURBS_ERROR2* = 100252 + GLU_NURBS_ERROR3* = 100253 + GLU_NURBS_ERROR4* = 100254 + GLU_NURBS_ERROR5* = 100255 + GLU_NURBS_ERROR6* = 100256 + GLU_NURBS_ERROR7* = 100257 + GLU_NURBS_ERROR8* = 100258 + GLU_NURBS_ERROR9* = 100259 + GLU_NURBS_ERROR10* = 100260 + GLU_NURBS_ERROR11* = 100261 + GLU_NURBS_ERROR12* = 100262 + GLU_NURBS_ERROR13* = 100263 + GLU_NURBS_ERROR14* = 100264 + GLU_NURBS_ERROR15* = 100265 + GLU_NURBS_ERROR16* = 100266 + GLU_NURBS_ERROR17* = 100267 + GLU_NURBS_ERROR18* = 100268 + GLU_NURBS_ERROR19* = 100269 + GLU_NURBS_ERROR20* = 100270 + GLU_NURBS_ERROR21* = 100271 + GLU_NURBS_ERROR22* = 100272 + GLU_NURBS_ERROR23* = 100273 + GLU_NURBS_ERROR24* = 100274 + GLU_NURBS_ERROR25* = 100275 + GLU_NURBS_ERROR26* = 100276 + GLU_NURBS_ERROR27* = 100277 + GLU_NURBS_ERROR28* = 100278 + GLU_NURBS_ERROR29* = 100279 + GLU_NURBS_ERROR30* = 100280 + GLU_NURBS_ERROR31* = 100281 + GLU_NURBS_ERROR32* = 100282 + GLU_NURBS_ERROR33* = 100283 + GLU_NURBS_ERROR34* = 100284 + GLU_NURBS_ERROR35* = 100285 + GLU_NURBS_ERROR36* = 100286 + GLU_NURBS_ERROR37* = 100287 #*** Backwards compatibility for old tesselator ****/ + +proc gluBeginPolygon*(tess: PGLUtesselator){.dynlib: dllname, + importc: "gluBeginPolygon".} +proc gluNextContour*(tess: PGLUtesselator, atype: TGLenum){.dynlib: dllname, + importc: "gluNextContour".} +proc gluEndPolygon*(tess: PGLUtesselator){.dynlib: dllname, + importc: "gluEndPolygon".} +const # Contours types -- obsolete! + GLU_CW* = 100120 + GLU_CCW* = 100121 + GLU_INTERIOR* = 100122 + GLU_EXTERIOR* = 100123 + GLU_UNKNOWN* = 100124 # Names without "TESS_" prefix + GLU_BEGIN* = GLU_TESS_BEGIN + GLU_VERTEX* = constGLU_TESS_VERTEX + GLU_END* = GLU_TESS_END + GLU_ERROR* = GLU_TESS_ERROR + GLU_EDGE_FLAG* = GLU_TESS_EDGE_FLAG + +{.pop.} +# implementation diff --git a/tests/manyloc/keineschweine/lib/glut.nim b/tests/manyloc/keineschweine/lib/glut.nim new file mode 100644 index 0000000000..ff157c3273 --- /dev/null +++ b/tests/manyloc/keineschweine/lib/glut.nim @@ -0,0 +1,438 @@ +# +# +# Adaption of the delphi3d.net OpenGL units to FreePascal +# Sebastian Guenther (sg@freepascal.org) in 2002 +# These units are free to use +# + +# Copyright (c) Mark J. Kilgard, 1994, 1995, 1996. +# This program is freely distributable without licensing fees and is +# provided without guarantee or warrantee expressed or implied. This +# program is -not- in the public domain. +#****************************************************************************** +# Converted to Delphi by Tom Nuydens (tom@delphi3d.net) +# Contributions by Igor Karpov (glygrik@hotbox.ru) +# For the latest updates, visit Delphi3D: http://www.delphi3d.net +#****************************************************************************** + +import + GL + +when defined(windows): + const + dllname = "glut32.dll" +elif defined(macosx): + const + dllname = "/System/Library/Frameworks/GLUT.framework/GLUT" +else: + const + dllname = "libglut.so.3" +type + TGlutVoidCallback* = proc (){.cdecl.} + TGlut1IntCallback* = proc (value: cint){.cdecl.} + TGlut2IntCallback* = proc (v1, v2: cint){.cdecl.} + TGlut3IntCallback* = proc (v1, v2, v3: cint){.cdecl.} + TGlut4IntCallback* = proc (v1, v2, v3, v4: cint){.cdecl.} + TGlut1Char2IntCallback* = proc (c: int8, v1, v2: cint){.cdecl.} + TGlut1UInt3IntCallback* = proc (u, v1, v2, v3: cint){.cdecl.} + +const + GLUT_API_VERSION* = 3 + GLUT_XLIB_IMPLEMENTATION* = 12 # Display mode bit masks. + GLUT_RGB* = 0 + GLUT_RGBA* = GLUT_RGB + GLUT_INDEX* = 1 + GLUT_SINGLE* = 0 + GLUT_DOUBLE* = 2 + GLUT_ACCUM* = 4 + GLUT_ALPHA* = 8 + GLUT_DEPTH* = 16 + GLUT_STENCIL* = 32 + GLUT_MULTISAMPLE* = 128 + GLUT_STEREO* = 256 + GLUT_LUMINANCE* = 512 # Mouse buttons. + GLUT_LEFT_BUTTON* = 0 + GLUT_MIDDLE_BUTTON* = 1 + GLUT_RIGHT_BUTTON* = 2 # Mouse button state. + GLUT_DOWN* = 0 + GLUT_UP* = 1 # function keys + GLUT_KEY_F1* = 1 + GLUT_KEY_F2* = 2 + GLUT_KEY_F3* = 3 + GLUT_KEY_F4* = 4 + GLUT_KEY_F5* = 5 + GLUT_KEY_F6* = 6 + GLUT_KEY_F7* = 7 + GLUT_KEY_F8* = 8 + GLUT_KEY_F9* = 9 + GLUT_KEY_F10* = 10 + GLUT_KEY_F11* = 11 + GLUT_KEY_F12* = 12 # directional keys + GLUT_KEY_LEFT* = 100 + GLUT_KEY_UP* = 101 + GLUT_KEY_RIGHT* = 102 + GLUT_KEY_DOWN* = 103 + GLUT_KEY_PAGE_UP* = 104 + GLUT_KEY_PAGE_DOWN* = 105 + GLUT_KEY_HOME* = 106 + GLUT_KEY_END* = 107 + GLUT_KEY_INSERT* = 108 # Entry/exit state. + GLUT_LEFT* = 0 + GLUT_ENTERED* = 1 # Menu usage state. + GLUT_MENU_NOT_IN_USE* = 0 + GLUT_MENU_IN_USE* = 1 # Visibility state. + GLUT_NOT_VISIBLE* = 0 + GLUT_VISIBLE* = 1 # Window status state. + GLUT_HIDDEN* = 0 + GLUT_FULLY_RETAINED* = 1 + GLUT_PARTIALLY_RETAINED* = 2 + GLUT_FULLY_COVERED* = 3 # Color index component selection values. + GLUT_RED* = 0 + GLUT_GREEN* = 1 + GLUT_BLUE* = 2 # Layers for use. + GLUT_NORMAL* = 0 + GLUT_OVERLAY* = 1 + +when defined(Windows): + const # Stroke font constants (use these in GLUT program). + GLUT_STROKE_ROMAN* = cast[Pointer](0) + GLUT_STROKE_MONO_ROMAN* = cast[Pointer](1) # Bitmap font constants (use these in GLUT program). + GLUT_BITMAP_9_BY_15* = cast[Pointer](2) + GLUT_BITMAP_8_BY_13* = cast[Pointer](3) + GLUT_BITMAP_TIMES_ROMAN_10* = cast[Pointer](4) + GLUT_BITMAP_TIMES_ROMAN_24* = cast[Pointer](5) + GLUT_BITMAP_HELVETICA_10* = cast[Pointer](6) + GLUT_BITMAP_HELVETICA_12* = cast[Pointer](7) + GLUT_BITMAP_HELVETICA_18* = cast[Pointer](8) +else: + var # Stroke font constants (use these in GLUT program). + GLUT_STROKE_ROMAN*: Pointer + GLUT_STROKE_MONO_ROMAN*: Pointer # Bitmap font constants (use these in GLUT program). + GLUT_BITMAP_9_BY_15*: Pointer + GLUT_BITMAP_8_BY_13*: Pointer + GLUT_BITMAP_TIMES_ROMAN_10*: Pointer + GLUT_BITMAP_TIMES_ROMAN_24*: Pointer + GLUT_BITMAP_HELVETICA_10*: Pointer + GLUT_BITMAP_HELVETICA_12*: Pointer + GLUT_BITMAP_HELVETICA_18*: Pointer +const # glutGet parameters. + GLUT_WINDOW_X* = 100 + GLUT_WINDOW_Y* = 101 + GLUT_WINDOW_WIDTH* = 102 + GLUT_WINDOW_HEIGHT* = 103 + GLUT_WINDOW_BUFFER_SIZE* = 104 + GLUT_WINDOW_STENCIL_SIZE* = 105 + GLUT_WINDOW_DEPTH_SIZE* = 106 + GLUT_WINDOW_RED_SIZE* = 107 + GLUT_WINDOW_GREEN_SIZE* = 108 + GLUT_WINDOW_BLUE_SIZE* = 109 + GLUT_WINDOW_ALPHA_SIZE* = 110 + GLUT_WINDOW_ACCUM_RED_SIZE* = 111 + GLUT_WINDOW_ACCUM_GREEN_SIZE* = 112 + GLUT_WINDOW_ACCUM_BLUE_SIZE* = 113 + GLUT_WINDOW_ACCUM_ALPHA_SIZE* = 114 + GLUT_WINDOW_DOUBLEBUFFER* = 115 + GLUT_WINDOW_RGBA* = 116 + GLUT_WINDOW_PARENT* = 117 + GLUT_WINDOW_NUM_CHILDREN* = 118 + GLUT_WINDOW_COLORMAP_SIZE* = 119 + GLUT_WINDOW_NUM_SAMPLES* = 120 + GLUT_WINDOW_STEREO* = 121 + GLUT_WINDOW_CURSOR* = 122 + GLUT_SCREEN_WIDTH* = 200 + GLUT_SCREEN_HEIGHT* = 201 + GLUT_SCREEN_WIDTH_MM* = 202 + GLUT_SCREEN_HEIGHT_MM* = 203 + GLUT_MENU_NUM_ITEMS* = 300 + GLUT_DISPLAY_MODE_POSSIBLE* = 400 + GLUT_INIT_WINDOW_X* = 500 + GLUT_INIT_WINDOW_Y* = 501 + GLUT_INIT_WINDOW_WIDTH* = 502 + GLUT_INIT_WINDOW_HEIGHT* = 503 + constGLUT_INIT_DISPLAY_MODE* = 504 + GLUT_ELAPSED_TIME* = 700 + GLUT_WINDOW_FORMAT_ID* = 123 # glutDeviceGet parameters. + GLUT_HAS_KEYBOARD* = 600 + GLUT_HAS_MOUSE* = 601 + GLUT_HAS_SPACEBALL* = 602 + GLUT_HAS_DIAL_AND_BUTTON_BOX* = 603 + GLUT_HAS_TABLET* = 604 + GLUT_NUM_MOUSE_BUTTONS* = 605 + GLUT_NUM_SPACEBALL_BUTTONS* = 606 + GLUT_NUM_BUTTON_BOX_BUTTONS* = 607 + GLUT_NUM_DIALS* = 608 + GLUT_NUM_TABLET_BUTTONS* = 609 + GLUT_DEVICE_IGNORE_KEY_REPEAT* = 610 + GLUT_DEVICE_KEY_REPEAT* = 611 + GLUT_HAS_JOYSTICK* = 612 + GLUT_OWNS_JOYSTICK* = 613 + GLUT_JOYSTICK_BUTTONS* = 614 + GLUT_JOYSTICK_AXES* = 615 + GLUT_JOYSTICK_POLL_RATE* = 616 # glutLayerGet parameters. + GLUT_OVERLAY_POSSIBLE* = 800 + GLUT_LAYER_IN_USE* = 801 + GLUT_HAS_OVERLAY* = 802 + GLUT_TRANSPARENT_INDEX* = 803 + GLUT_NORMAL_DAMAGED* = 804 + GLUT_OVERLAY_DAMAGED* = 805 # glutVideoResizeGet parameters. + GLUT_VIDEO_RESIZE_POSSIBLE* = 900 + GLUT_VIDEO_RESIZE_IN_USE* = 901 + GLUT_VIDEO_RESIZE_X_DELTA* = 902 + GLUT_VIDEO_RESIZE_Y_DELTA* = 903 + GLUT_VIDEO_RESIZE_WIDTH_DELTA* = 904 + GLUT_VIDEO_RESIZE_HEIGHT_DELTA* = 905 + GLUT_VIDEO_RESIZE_X* = 906 + GLUT_VIDEO_RESIZE_Y* = 907 + GLUT_VIDEO_RESIZE_WIDTH* = 908 + GLUT_VIDEO_RESIZE_HEIGHT* = 909 # glutGetModifiers return mask. + GLUT_ACTIVE_SHIFT* = 1 + GLUT_ACTIVE_CTRL* = 2 + GLUT_ACTIVE_ALT* = 4 # glutSetCursor parameters. + # Basic arrows. + GLUT_CURSOR_RIGHT_ARROW* = 0 + GLUT_CURSOR_LEFT_ARROW* = 1 # Symbolic cursor shapes. + GLUT_CURSOR_INFO* = 2 + GLUT_CURSOR_DESTROY* = 3 + GLUT_CURSOR_HELP* = 4 + GLUT_CURSOR_CYCLE* = 5 + GLUT_CURSOR_SPRAY* = 6 + GLUT_CURSOR_WAIT* = 7 + GLUT_CURSOR_TEXT* = 8 + GLUT_CURSOR_CROSSHAIR* = 9 # Directional cursors. + GLUT_CURSOR_UP_DOWN* = 10 + GLUT_CURSOR_LEFT_RIGHT* = 11 # Sizing cursors. + GLUT_CURSOR_TOP_SIDE* = 12 + GLUT_CURSOR_BOTTOM_SIDE* = 13 + GLUT_CURSOR_LEFT_SIDE* = 14 + GLUT_CURSOR_RIGHT_SIDE* = 15 + GLUT_CURSOR_TOP_LEFT_CORNER* = 16 + GLUT_CURSOR_TOP_RIGHT_CORNER* = 17 + GLUT_CURSOR_BOTTOM_RIGHT_CORNER* = 18 + GLUT_CURSOR_BOTTOM_LEFT_CORNER* = 19 # Inherit from parent window. + GLUT_CURSOR_INHERIT* = 100 # Blank cursor. + GLUT_CURSOR_NONE* = 101 # Fullscreen crosshair (if available). + GLUT_CURSOR_FULL_CROSSHAIR* = 102 # GLUT device control sub-API. + # glutSetKeyRepeat modes. + GLUT_KEY_REPEAT_OFF* = 0 + GLUT_KEY_REPEAT_ON* = 1 + GLUT_KEY_REPEAT_DEFAULT* = 2 # Joystick button masks. + GLUT_JOYSTICK_BUTTON_A* = 1 + GLUT_JOYSTICK_BUTTON_B* = 2 + GLUT_JOYSTICK_BUTTON_C* = 4 + GLUT_JOYSTICK_BUTTON_D* = 8 # GLUT game mode sub-API. + # glutGameModeGet. + GLUT_GAME_MODE_ACTIVE* = 0 + GLUT_GAME_MODE_POSSIBLE* = 1 + GLUT_GAME_MODE_WIDTH* = 2 + GLUT_GAME_MODE_HEIGHT* = 3 + GLUT_GAME_MODE_PIXEL_DEPTH* = 4 + GLUT_GAME_MODE_REFRESH_RATE* = 5 + GLUT_GAME_MODE_DISPLAY_CHANGED* = 6 # GLUT initialization sub-API. + +proc glutInit*(argcp: ptr cint, argv: pointer){.dynlib: dllname, + importc: "glutInit".} + +proc glutInit*() = + ## version that passes `argc` and `argc` implicitely. + var + cmdLine {.importc: "cmdLine".}: array[0..255, cstring] + cmdCount {.importc: "cmdCount".}: cint + glutInit(addr(cmdCount), addr(cmdLine)) + +proc glutInitDisplayMode*(mode: int16){.dynlib: dllname, + importc: "glutInitDisplayMode".} +proc glutInitDisplayString*(str: cstring){.dynlib: dllname, + importc: "glutInitDisplayString".} +proc glutInitWindowPosition*(x, y: int){.dynlib: dllname, + importc: "glutInitWindowPosition".} +proc glutInitWindowSize*(width, height: int){.dynlib: dllname, + importc: "glutInitWindowSize".} +proc glutMainLoop*(){.dynlib: dllname, importc: "glutMainLoop".} + # GLUT window sub-API. +proc glutCreateWindow*(title: cstring): int{.dynlib: dllname, + importc: "glutCreateWindow".} +proc glutCreateSubWindow*(win, x, y, width, height: int): int{.dynlib: dllname, + importc: "glutCreateSubWindow".} +proc glutDestroyWindow*(win: int){.dynlib: dllname, importc: "glutDestroyWindow".} +proc glutPostRedisplay*(){.dynlib: dllname, importc: "glutPostRedisplay".} +proc glutPostWindowRedisplay*(win: int){.dynlib: dllname, + importc: "glutPostWindowRedisplay".} +proc glutSwapBuffers*(){.dynlib: dllname, importc: "glutSwapBuffers".} +proc glutGetWindow*(): int{.dynlib: dllname, importc: "glutGetWindow".} +proc glutSetWindow*(win: int){.dynlib: dllname, importc: "glutSetWindow".} +proc glutSetWindowTitle*(title: cstring){.dynlib: dllname, + importc: "glutSetWindowTitle".} +proc glutSetIconTitle*(title: cstring){.dynlib: dllname, + importc: "glutSetIconTitle".} +proc glutPositionWindow*(x, y: int){.dynlib: dllname, + importc: "glutPositionWindow".} +proc glutReshapeWindow*(width, height: int){.dynlib: dllname, + importc: "glutReshapeWindow".} +proc glutPopWindow*(){.dynlib: dllname, importc: "glutPopWindow".} +proc glutPushWindow*(){.dynlib: dllname, importc: "glutPushWindow".} +proc glutIconifyWindow*(){.dynlib: dllname, importc: "glutIconifyWindow".} +proc glutShowWindow*(){.dynlib: dllname, importc: "glutShowWindow".} +proc glutHideWindow*(){.dynlib: dllname, importc: "glutHideWindow".} +proc glutFullScreen*(){.dynlib: dllname, importc: "glutFullScreen".} +proc glutSetCursor*(cursor: int){.dynlib: dllname, importc: "glutSetCursor".} +proc glutWarpPointer*(x, y: int){.dynlib: dllname, importc: "glutWarpPointer".} + # GLUT overlay sub-API. +proc glutEstablishOverlay*(){.dynlib: dllname, importc: "glutEstablishOverlay".} +proc glutRemoveOverlay*(){.dynlib: dllname, importc: "glutRemoveOverlay".} +proc glutUseLayer*(layer: TGLenum){.dynlib: dllname, importc: "glutUseLayer".} +proc glutPostOverlayRedisplay*(){.dynlib: dllname, + importc: "glutPostOverlayRedisplay".} +proc glutPostWindowOverlayRedisplay*(win: int){.dynlib: dllname, + importc: "glutPostWindowOverlayRedisplay".} +proc glutShowOverlay*(){.dynlib: dllname, importc: "glutShowOverlay".} +proc glutHideOverlay*(){.dynlib: dllname, importc: "glutHideOverlay".} + # GLUT menu sub-API. +proc glutCreateMenu*(callback: TGlut1IntCallback): int{.dynlib: dllname, + importc: "glutCreateMenu".} +proc glutDestroyMenu*(menu: int){.dynlib: dllname, importc: "glutDestroyMenu".} +proc glutGetMenu*(): int{.dynlib: dllname, importc: "glutGetMenu".} +proc glutSetMenu*(menu: int){.dynlib: dllname, importc: "glutSetMenu".} +proc glutAddMenuEntry*(caption: cstring, value: int){.dynlib: dllname, + importc: "glutAddMenuEntry".} +proc glutAddSubMenu*(caption: cstring, submenu: int){.dynlib: dllname, + importc: "glutAddSubMenu".} +proc glutChangeToMenuEntry*(item: int, caption: cstring, value: int){. + dynlib: dllname, importc: "glutChangeToMenuEntry".} +proc glutChangeToSubMenu*(item: int, caption: cstring, submenu: int){. + dynlib: dllname, importc: "glutChangeToSubMenu".} +proc glutRemoveMenuItem*(item: int){.dynlib: dllname, + importc: "glutRemoveMenuItem".} +proc glutAttachMenu*(button: int){.dynlib: dllname, importc: "glutAttachMenu".} +proc glutDetachMenu*(button: int){.dynlib: dllname, importc: "glutDetachMenu".} + # GLUT window callback sub-API. +proc glutDisplayFunc*(f: TGlutVoidCallback){.dynlib: dllname, + importc: "glutDisplayFunc".} +proc glutReshapeFunc*(f: TGlut2IntCallback){.dynlib: dllname, + importc: "glutReshapeFunc".} +proc glutKeyboardFunc*(f: TGlut1Char2IntCallback){.dynlib: dllname, + importc: "glutKeyboardFunc".} +proc glutMouseFunc*(f: TGlut4IntCallback){.dynlib: dllname, + importc: "glutMouseFunc".} +proc glutMotionFunc*(f: TGlut2IntCallback){.dynlib: dllname, + importc: "glutMotionFunc".} +proc glutPassiveMotionFunc*(f: TGlut2IntCallback){.dynlib: dllname, + importc: "glutPassiveMotionFunc".} +proc glutEntryFunc*(f: TGlut1IntCallback){.dynlib: dllname, + importc: "glutEntryFunc".} +proc glutVisibilityFunc*(f: TGlut1IntCallback){.dynlib: dllname, + importc: "glutVisibilityFunc".} +proc glutIdleFunc*(f: TGlutVoidCallback){.dynlib: dllname, + importc: "glutIdleFunc".} +proc glutTimerFunc*(millis: int16, f: TGlut1IntCallback, value: int){. + dynlib: dllname, importc: "glutTimerFunc".} +proc glutMenuStateFunc*(f: TGlut1IntCallback){.dynlib: dllname, + importc: "glutMenuStateFunc".} +proc glutSpecialFunc*(f: TGlut3IntCallback){.dynlib: dllname, + importc: "glutSpecialFunc".} +proc glutSpaceballMotionFunc*(f: TGlut3IntCallback){.dynlib: dllname, + importc: "glutSpaceballMotionFunc".} +proc glutSpaceballRotateFunc*(f: TGlut3IntCallback){.dynlib: dllname, + importc: "glutSpaceballRotateFunc".} +proc glutSpaceballButtonFunc*(f: TGlut2IntCallback){.dynlib: dllname, + importc: "glutSpaceballButtonFunc".} +proc glutButtonBoxFunc*(f: TGlut2IntCallback){.dynlib: dllname, + importc: "glutButtonBoxFunc".} +proc glutDialsFunc*(f: TGlut2IntCallback){.dynlib: dllname, + importc: "glutDialsFunc".} +proc glutTabletMotionFunc*(f: TGlut2IntCallback){.dynlib: dllname, + importc: "glutTabletMotionFunc".} +proc glutTabletButtonFunc*(f: TGlut4IntCallback){.dynlib: dllname, + importc: "glutTabletButtonFunc".} +proc glutMenuStatusFunc*(f: TGlut3IntCallback){.dynlib: dllname, + importc: "glutMenuStatusFunc".} +proc glutOverlayDisplayFunc*(f: TGlutVoidCallback){.dynlib: dllname, + importc: "glutOverlayDisplayFunc".} +proc glutWindowStatusFunc*(f: TGlut1IntCallback){.dynlib: dllname, + importc: "glutWindowStatusFunc".} +proc glutKeyboardUpFunc*(f: TGlut1Char2IntCallback){.dynlib: dllname, + importc: "glutKeyboardUpFunc".} +proc glutSpecialUpFunc*(f: TGlut3IntCallback){.dynlib: dllname, + importc: "glutSpecialUpFunc".} +proc glutJoystickFunc*(f: TGlut1UInt3IntCallback, pollInterval: int){. + dynlib: dllname, importc: "glutJoystickFunc".} + # GLUT color index sub-API. +proc glutSetColor*(cell: int, red, green, blue: TGLfloat){.dynlib: dllname, + importc: "glutSetColor".} +proc glutGetColor*(ndx, component: int): TGLfloat{.dynlib: dllname, + importc: "glutGetColor".} +proc glutCopyColormap*(win: int){.dynlib: dllname, importc: "glutCopyColormap".} + # GLUT state retrieval sub-API. +proc glutGet*(t: TGLenum): int{.dynlib: dllname, importc: "glutGet".} +proc glutDeviceGet*(t: TGLenum): int{.dynlib: dllname, importc: "glutDeviceGet".} + # GLUT extension support sub-API +proc glutExtensionSupported*(name: cstring): int{.dynlib: dllname, + importc: "glutExtensionSupported".} +proc glutGetModifiers*(): int{.dynlib: dllname, importc: "glutGetModifiers".} +proc glutLayerGet*(t: TGLenum): int{.dynlib: dllname, importc: "glutLayerGet".} + # GLUT font sub-API +proc glutBitmapCharacter*(font: pointer, character: int){.dynlib: dllname, + importc: "glutBitmapCharacter".} +proc glutBitmapWidth*(font: pointer, character: int): int{.dynlib: dllname, + importc: "glutBitmapWidth".} +proc glutStrokeCharacter*(font: pointer, character: int){.dynlib: dllname, + importc: "glutStrokeCharacter".} +proc glutStrokeWidth*(font: pointer, character: int): int{.dynlib: dllname, + importc: "glutStrokeWidth".} +proc glutBitmapLength*(font: pointer, str: cstring): int{.dynlib: dllname, + importc: "glutBitmapLength".} +proc glutStrokeLength*(font: pointer, str: cstring): int{.dynlib: dllname, + importc: "glutStrokeLength".} + # GLUT pre-built models sub-API +proc glutWireSphere*(radius: TGLdouble, slices, stacks: TGLint){. + dynlib: dllname, importc: "glutWireSphere".} +proc glutSolidSphere*(radius: TGLdouble, slices, stacks: TGLint){. + dynlib: dllname, importc: "glutSolidSphere".} +proc glutWireCone*(base, height: TGLdouble, slices, stacks: TGLint){. + dynlib: dllname, importc: "glutWireCone".} +proc glutSolidCone*(base, height: TGLdouble, slices, stacks: TGLint){. + dynlib: dllname, importc: "glutSolidCone".} +proc glutWireCube*(size: TGLdouble){.dynlib: dllname, importc: "glutWireCube".} +proc glutSolidCube*(size: TGLdouble){.dynlib: dllname, importc: "glutSolidCube".} +proc glutWireTorus*(innerRadius, outerRadius: TGLdouble, sides, rings: TGLint){. + dynlib: dllname, importc: "glutWireTorus".} +proc glutSolidTorus*(innerRadius, outerRadius: TGLdouble, sides, rings: TGLint){. + dynlib: dllname, importc: "glutSolidTorus".} +proc glutWireDodecahedron*(){.dynlib: dllname, importc: "glutWireDodecahedron".} +proc glutSolidDodecahedron*(){.dynlib: dllname, importc: "glutSolidDodecahedron".} +proc glutWireTeapot*(size: TGLdouble){.dynlib: dllname, + importc: "glutWireTeapot".} +proc glutSolidTeapot*(size: TGLdouble){.dynlib: dllname, + importc: "glutSolidTeapot".} +proc glutWireOctahedron*(){.dynlib: dllname, importc: "glutWireOctahedron".} +proc glutSolidOctahedron*(){.dynlib: dllname, importc: "glutSolidOctahedron".} +proc glutWireTetrahedron*(){.dynlib: dllname, importc: "glutWireTetrahedron".} +proc glutSolidTetrahedron*(){.dynlib: dllname, importc: "glutSolidTetrahedron".} +proc glutWireIcosahedron*(){.dynlib: dllname, importc: "glutWireIcosahedron".} +proc glutSolidIcosahedron*(){.dynlib: dllname, importc: "glutSolidIcosahedron".} + # GLUT video resize sub-API. +proc glutVideoResizeGet*(param: TGLenum): int{.dynlib: dllname, + importc: "glutVideoResizeGet".} +proc glutSetupVideoResizing*(){.dynlib: dllname, + importc: "glutSetupVideoResizing".} +proc glutStopVideoResizing*(){.dynlib: dllname, importc: "glutStopVideoResizing".} +proc glutVideoResize*(x, y, width, height: int){.dynlib: dllname, + importc: "glutVideoResize".} +proc glutVideoPan*(x, y, width, height: int){.dynlib: dllname, + importc: "glutVideoPan".} + # GLUT debugging sub-API. +proc glutReportErrors*(){.dynlib: dllname, importc: "glutReportErrors".} + # GLUT device control sub-API. +proc glutIgnoreKeyRepeat*(ignore: int){.dynlib: dllname, + importc: "glutIgnoreKeyRepeat".} +proc glutSetKeyRepeat*(repeatMode: int){.dynlib: dllname, + importc: "glutSetKeyRepeat".} +proc glutForceJoystickFunc*(){.dynlib: dllname, importc: "glutForceJoystickFunc".} + # GLUT game mode sub-API. + #example glutGameModeString('1280x1024:32@75'); +proc glutGameModeString*(AString: cstring){.dynlib: dllname, + importc: "glutGameModeString".} +proc glutEnterGameMode*(): int{.dynlib: dllname, importc: "glutEnterGameMode".} +proc glutLeaveGameMode*(){.dynlib: dllname, importc: "glutLeaveGameMode".} +proc glutGameModeGet*(mode: TGLenum): int{.dynlib: dllname, + importc: "glutGameModeGet".} +# implementation diff --git a/tests/manyloc/keineschweine/lib/glx.nim b/tests/manyloc/keineschweine/lib/glx.nim new file mode 100644 index 0000000000..76c052d70a --- /dev/null +++ b/tests/manyloc/keineschweine/lib/glx.nim @@ -0,0 +1,153 @@ +# +# +# Translation of the Mesa GLX headers for FreePascal +# Copyright (C) 1999 Sebastian Guenther +# +# +# Mesa 3-D graphics library +# Version: 3.0 +# Copyright (C) 1995-1998 Brian Paul +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Library General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Library General Public License for more details. +# +# You should have received a copy of the GNU Library General Public +# License along with this library; if not, write to the Free +# Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# + +import + X, XLib, XUtil, gl + +when defined(windows): + const + dllname = "GL.dll" +elif defined(macosx): + const + dllname = "/usr/X11R6/lib/libGL.dylib" +else: + const + dllname = "libGL.so" +const + GLX_USE_GL* = 1 + GLX_BUFFER_SIZE* = 2 + GLX_LEVEL* = 3 + GLX_RGBA* = 4 + GLX_DOUBLEBUFFER* = 5 + GLX_STEREO* = 6 + GLX_AUX_BUFFERS* = 7 + GLX_RED_SIZE* = 8 + GLX_GREEN_SIZE* = 9 + GLX_BLUE_SIZE* = 10 + GLX_ALPHA_SIZE* = 11 + GLX_DEPTH_SIZE* = 12 + GLX_STENCIL_SIZE* = 13 + GLX_ACCUM_RED_SIZE* = 14 + GLX_ACCUM_GREEN_SIZE* = 15 + GLX_ACCUM_BLUE_SIZE* = 16 + GLX_ACCUM_ALPHA_SIZE* = 17 # GLX_EXT_visual_info extension + GLX_X_VISUAL_TYPE_EXT* = 0x00000022 + GLX_TRANSPARENT_TYPE_EXT* = 0x00000023 + GLX_TRANSPARENT_INDEX_VALUE_EXT* = 0x00000024 + GLX_TRANSPARENT_RED_VALUE_EXT* = 0x00000025 + GLX_TRANSPARENT_GREEN_VALUE_EXT* = 0x00000026 + GLX_TRANSPARENT_BLUE_VALUE_EXT* = 0x00000027 + GLX_TRANSPARENT_ALPHA_VALUE_EXT* = 0x00000028 # Error codes returned by glXGetConfig: + GLX_BAD_SCREEN* = 1 + GLX_BAD_ATTRIBUTE* = 2 + GLX_NO_EXTENSION* = 3 + GLX_BAD_VISUAL* = 4 + GLX_BAD_CONTEXT* = 5 + GLX_BAD_VALUE* = 6 + GLX_BAD_ENUM* = 7 # GLX 1.1 and later: + GLX_VENDOR* = 1 + GLX_VERSION* = 2 + GLX_EXTENSIONS* = 3 # GLX_visual_info extension + GLX_TRUE_COLOR_EXT* = 0x00008002 + GLX_DIRECT_COLOR_EXT* = 0x00008003 + GLX_PSEUDO_COLOR_EXT* = 0x00008004 + GLX_STATIC_COLOR_EXT* = 0x00008005 + GLX_GRAY_SCALE_EXT* = 0x00008006 + GLX_STATIC_GRAY_EXT* = 0x00008007 + GLX_NONE_EXT* = 0x00008000 + GLX_TRANSPARENT_RGB_EXT* = 0x00008008 + GLX_TRANSPARENT_INDEX_EXT* = 0x00008009 + +type # From XLib: + XPixmap* = TXID + XFont* = TXID + XColormap* = TXID + GLXContext* = Pointer + GLXPixmap* = TXID + GLXDrawable* = TXID + GLXContextID* = TXID + TXPixmap* = XPixmap + TXFont* = XFont + TXColormap* = XColormap + TGLXContext* = GLXContext + TGLXPixmap* = GLXPixmap + TGLXDrawable* = GLXDrawable + TGLXContextID* = GLXContextID + +proc glXChooseVisual*(dpy: PDisplay, screen: int, attribList: ptr int32): PXVisualInfo{. + cdecl, dynlib: dllname, importc: "glXChooseVisual".} +proc glXCreateContext*(dpy: PDisplay, vis: PXVisualInfo, shareList: GLXContext, + direct: bool): GLXContext{.cdecl, dynlib: dllname, + importc: "glXCreateContext".} +proc glXDestroyContext*(dpy: PDisplay, ctx: GLXContext){.cdecl, dynlib: dllname, + importc: "glXDestroyContext".} +proc glXMakeCurrent*(dpy: PDisplay, drawable: GLXDrawable, ctx: GLXContext): bool{. + cdecl, dynlib: dllname, importc: "glXMakeCurrent".} +proc glXCopyContext*(dpy: PDisplay, src, dst: GLXContext, mask: int32){.cdecl, + dynlib: dllname, importc: "glXCopyContext".} +proc glXSwapBuffers*(dpy: PDisplay, drawable: GLXDrawable){.cdecl, + dynlib: dllname, importc: "glXSwapBuffers".} +proc glXCreateGLXPixmap*(dpy: PDisplay, visual: PXVisualInfo, pixmap: XPixmap): GLXPixmap{. + cdecl, dynlib: dllname, importc: "glXCreateGLXPixmap".} +proc glXDestroyGLXPixmap*(dpy: PDisplay, pixmap: GLXPixmap){.cdecl, + dynlib: dllname, importc: "glXDestroyGLXPixmap".} +proc glXQueryExtension*(dpy: PDisplay, errorb, event: var int): bool{.cdecl, + dynlib: dllname, importc: "glXQueryExtension".} +proc glXQueryVersion*(dpy: PDisplay, maj, min: var int): bool{.cdecl, + dynlib: dllname, importc: "glXQueryVersion".} +proc glXIsDirect*(dpy: PDisplay, ctx: GLXContext): bool{.cdecl, dynlib: dllname, + importc: "glXIsDirect".} +proc glXGetConfig*(dpy: PDisplay, visual: PXVisualInfo, attrib: int, + value: var int): int{.cdecl, dynlib: dllname, + importc: "glXGetConfig".} +proc glXGetCurrentContext*(): GLXContext{.cdecl, dynlib: dllname, + importc: "glXGetCurrentContext".} +proc glXGetCurrentDrawable*(): GLXDrawable{.cdecl, dynlib: dllname, + importc: "glXGetCurrentDrawable".} +proc glXWaitGL*(){.cdecl, dynlib: dllname, importc: "glXWaitGL".} +proc glXWaitX*(){.cdecl, dynlib: dllname, importc: "glXWaitX".} +proc glXUseXFont*(font: XFont, first, count, list: int){.cdecl, dynlib: dllname, + importc: "glXUseXFont".} + # GLX 1.1 and later +proc glXQueryExtensionsString*(dpy: PDisplay, screen: int): cstring{.cdecl, + dynlib: dllname, importc: "glXQueryExtensionsString".} +proc glXQueryServerString*(dpy: PDisplay, screen, name: int): cstring{.cdecl, + dynlib: dllname, importc: "glXQueryServerString".} +proc glXGetClientString*(dpy: PDisplay, name: int): cstring{.cdecl, + dynlib: dllname, importc: "glXGetClientString".} + # Mesa GLX Extensions +proc glXCreateGLXPixmapMESA*(dpy: PDisplay, visual: PXVisualInfo, + pixmap: XPixmap, cmap: XColormap): GLXPixmap{. + cdecl, dynlib: dllname, importc: "glXCreateGLXPixmapMESA".} +proc glXReleaseBufferMESA*(dpy: PDisplay, d: GLXDrawable): bool{.cdecl, + dynlib: dllname, importc: "glXReleaseBufferMESA".} +proc glXCopySubBufferMESA*(dpy: PDisplay, drawbale: GLXDrawable, + x, y, width, height: int){.cdecl, dynlib: dllname, + importc: "glXCopySubBufferMESA".} +proc glXGetVideoSyncSGI*(counter: var int32): int{.cdecl, dynlib: dllname, + importc: "glXGetVideoSyncSGI".} +proc glXWaitVideoSyncSGI*(divisor, remainder: int, count: var int32): int{. + cdecl, dynlib: dllname, importc: "glXWaitVideoSyncSGI".} +# implementation diff --git a/tests/manyloc/keineschweine/lib/wingl.nim b/tests/manyloc/keineschweine/lib/wingl.nim new file mode 100644 index 0000000000..7ed78f9707 --- /dev/null +++ b/tests/manyloc/keineschweine/lib/wingl.nim @@ -0,0 +1,368 @@ +import + gl, windows + +proc wglGetExtensionsStringARB*(hdc: HDC): cstring{.dynlib: dllname, + importc: "wglGetExtensionsStringARB".} +const + WGL_FRONT_COLOR_BUFFER_BIT_ARB* = 0x00000001 + WGL_BACK_COLOR_BUFFER_BIT_ARB* = 0x00000002 + WGL_DEPTH_BUFFER_BIT_ARB* = 0x00000004 + WGL_STENCIL_BUFFER_BIT_ARB* = 0x00000008 + +proc WinChoosePixelFormat*(DC: HDC, p2: PPixelFormatDescriptor): int{. + dynlib: "gdi32", importc: "ChoosePixelFormat".} +proc wglCreateBufferRegionARB*(hDC: HDC, iLayerPlane: TGLint, uType: TGLuint): THandle{. + dynlib: dllname, importc: "wglCreateBufferRegionARB".} +proc wglDeleteBufferRegionARB*(hRegion: THandle){.dynlib: dllname, + importc: "wglDeleteBufferRegionARB".} +proc wglSaveBufferRegionARB*(hRegion: THandle, x: TGLint, y: TGLint, + width: TGLint, height: TGLint): BOOL{. + dynlib: dllname, importc: "wglSaveBufferRegionARB".} +proc wglRestoreBufferRegionARB*(hRegion: THandle, x: TGLint, y: TGLint, + width: TGLint, height: TGLint, xSrc: TGLint, + ySrc: TGLint): BOOL{.dynlib: dllname, + importc: "wglRestoreBufferRegionARB".} +proc wglAllocateMemoryNV*(size: TGLsizei, readFrequency: TGLfloat, + writeFrequency: TGLfloat, priority: TGLfloat): PGLvoid{. + dynlib: dllname, importc: "wglAllocateMemoryNV".} +proc wglFreeMemoryNV*(pointer: PGLvoid){.dynlib: dllname, + importc: "wglFreeMemoryNV".} +const + WGL_IMAGE_BUFFER_MIN_ACCESS_I3D* = 0x00000001 + WGL_IMAGE_BUFFER_LOCK_I3D* = 0x00000002 + +proc wglCreateImageBufferI3D*(hDC: HDC, dwSize: DWORD, uFlags: UINT): PGLvoid{. + dynlib: dllname, importc: "wglCreateImageBufferI3D".} +proc wglDestroyImageBufferI3D*(hDC: HDC, pAddress: PGLvoid): BOOL{. + dynlib: dllname, importc: "wglDestroyImageBufferI3D".} +proc wglAssociateImageBufferEventsI3D*(hdc: HDC, pEvent: PHandle, + pAddress: PGLvoid, pSize: PDWORD, + count: UINT): BOOL{.dynlib: dllname, + importc: "wglAssociateImageBufferEventsI3D".} +proc wglReleaseImageBufferEventsI3D*(hdc: HDC, pAddress: PGLvoid, count: UINT): BOOL{. + dynlib: dllname, importc: "wglReleaseImageBufferEventsI3D".} +proc wglEnableFrameLockI3D*(): BOOL{.dynlib: dllname, + importc: "wglEnableFrameLockI3D".} +proc wglDisableFrameLockI3D*(): BOOL{.dynlib: dllname, + importc: "wglDisableFrameLockI3D".} +proc wglIsEnabledFrameLockI3D*(pFlag: PBOOL): BOOL{.dynlib: dllname, + importc: "wglIsEnabledFrameLockI3D".} +proc wglQueryFrameLockMasterI3D*(pFlag: PBOOL): BOOL{.dynlib: dllname, + importc: "wglQueryFrameLockMasterI3D".} +proc wglGetFrameUsageI3D*(pUsage: PGLfloat): BOOL{.dynlib: dllname, + importc: "wglGetFrameUsageI3D".} +proc wglBeginFrameTrackingI3D*(): BOOL{.dynlib: dllname, + importc: "wglBeginFrameTrackingI3D".} +proc wglEndFrameTrackingI3D*(): BOOL{.dynlib: dllname, + importc: "wglEndFrameTrackingI3D".} +proc wglQueryFrameTrackingI3D*(pFrameCount: PDWORD, pMissedFrames: PDWORD, + pLastMissedUsage: PGLfloat): BOOL{. + dynlib: dllname, importc: "wglQueryFrameTrackingI3D".} +const + WGL_NUMBER_PIXEL_FORMATS_ARB* = 0x00002000 + WGL_DRAW_TO_WINDOW_ARB* = 0x00002001 + WGL_DRAW_TO_BITMAP_ARB* = 0x00002002 + WGL_ACCELERATION_ARB* = 0x00002003 + WGL_NEED_PALETTE_ARB* = 0x00002004 + WGL_NEED_SYSTEM_PALETTE_ARB* = 0x00002005 + WGL_SWAP_LAYER_BUFFERS_ARB* = 0x00002006 + WGL_SWAP_METHOD_ARB* = 0x00002007 + WGL_NUMBER_OVERLAYS_ARB* = 0x00002008 + WGL_NUMBER_UNDERLAYS_ARB* = 0x00002009 + WGL_TRANSPARENT_ARB* = 0x0000200A + WGL_TRANSPARENT_RED_VALUE_ARB* = 0x00002037 + WGL_TRANSPARENT_GREEN_VALUE_ARB* = 0x00002038 + WGL_TRANSPARENT_BLUE_VALUE_ARB* = 0x00002039 + WGL_TRANSPARENT_ALPHA_VALUE_ARB* = 0x0000203A + WGL_TRANSPARENT_INDEX_VALUE_ARB* = 0x0000203B + WGL_SHARE_DEPTH_ARB* = 0x0000200C + WGL_SHARE_STENCIL_ARB* = 0x0000200D + WGL_SHARE_ACCUM_ARB* = 0x0000200E + WGL_SUPPORT_GDI_ARB* = 0x0000200F + WGL_SUPPORT_OPENGL_ARB* = 0x00002010 + WGL_DOUBLE_BUFFER_ARB* = 0x00002011 + WGL_STEREO_ARB* = 0x00002012 + WGL_PIXEL_TYPE_ARB* = 0x00002013 + WGL_COLOR_BITS_ARB* = 0x00002014 + WGL_RED_BITS_ARB* = 0x00002015 + WGL_RED_SHIFT_ARB* = 0x00002016 + WGL_GREEN_BITS_ARB* = 0x00002017 + WGL_GREEN_SHIFT_ARB* = 0x00002018 + WGL_BLUE_BITS_ARB* = 0x00002019 + WGL_BLUE_SHIFT_ARB* = 0x0000201A + WGL_ALPHA_BITS_ARB* = 0x0000201B + WGL_ALPHA_SHIFT_ARB* = 0x0000201C + WGL_ACCUM_BITS_ARB* = 0x0000201D + WGL_ACCUM_RED_BITS_ARB* = 0x0000201E + WGL_ACCUM_GREEN_BITS_ARB* = 0x0000201F + WGL_ACCUM_BLUE_BITS_ARB* = 0x00002020 + WGL_ACCUM_ALPHA_BITS_ARB* = 0x00002021 + WGL_DEPTH_BITS_ARB* = 0x00002022 + WGL_STENCIL_BITS_ARB* = 0x00002023 + WGL_AUX_BUFFERS_ARB* = 0x00002024 + WGL_NO_ACCELERATION_ARB* = 0x00002025 + WGL_GENERIC_ACCELERATION_ARB* = 0x00002026 + WGL_FULL_ACCELERATION_ARB* = 0x00002027 + WGL_SWAP_EXCHANGE_ARB* = 0x00002028 + WGL_SWAP_COPY_ARB* = 0x00002029 + WGL_SWAP_UNDEFINED_ARB* = 0x0000202A + WGL_TYPE_RGBA_ARB* = 0x0000202B + WGL_TYPE_COLORINDEX_ARB* = 0x0000202C + +proc wglGetPixelFormatAttribivARB*(hdc: HDC, iPixelFormat: TGLint, + iLayerPlane: TGLint, nAttributes: TGLuint, + piAttributes: PGLint, piValues: PGLint): BOOL{. + dynlib: dllname, importc: "wglGetPixelFormatAttribivARB".} +proc wglGetPixelFormatAttribfvARB*(hdc: HDC, iPixelFormat: TGLint, + iLayerPlane: TGLint, nAttributes: TGLuint, + piAttributes: PGLint, pfValues: PGLfloat): BOOL{. + dynlib: dllname, importc: "wglGetPixelFormatAttribfvARB".} +proc wglChoosePixelFormatARB*(hdc: HDC, piAttribIList: PGLint, + pfAttribFList: PGLfloat, nMaxFormats: TGLuint, + piFormats: PGLint, nNumFormats: PGLuint): BOOL{. + dynlib: dllname, importc: "wglChoosePixelFormatARB".} +const + WGL_ERROR_INVALID_PIXEL_TYPE_ARB* = 0x00002043 + WGL_ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB* = 0x00002054 + +proc wglMakeContextCurrentARB*(hDrawDC: HDC, hReadDC: HDC, hglrc: HGLRC): BOOL{. + dynlib: dllname, importc: "wglMakeContextCurrentARB".} +proc wglGetCurrentReadDCARB*(): HDC{.dynlib: dllname, + importc: "wglGetCurrentReadDCARB".} +const + WGL_DRAW_TO_PBUFFER_ARB* = 0x0000202D # WGL_DRAW_TO_PBUFFER_ARB { already defined } + WGL_MAX_PBUFFER_PIXELS_ARB* = 0x0000202E + WGL_MAX_PBUFFER_WIDTH_ARB* = 0x0000202F + WGL_MAX_PBUFFER_HEIGHT_ARB* = 0x00002030 + WGL_PBUFFER_LARGEST_ARB* = 0x00002033 + WGL_PBUFFER_WIDTH_ARB* = 0x00002034 + WGL_PBUFFER_HEIGHT_ARB* = 0x00002035 + WGL_PBUFFER_LOST_ARB* = 0x00002036 + +proc wglCreatePbufferARB*(hDC: HDC, iPixelFormat: TGLint, iWidth: TGLint, + iHeight: TGLint, piAttribList: PGLint): THandle{. + dynlib: dllname, importc: "wglCreatePbufferARB".} +proc wglGetPbufferDCARB*(hPbuffer: THandle): HDC{.dynlib: dllname, + importc: "wglGetPbufferDCARB".} +proc wglReleasePbufferDCARB*(hPbuffer: THandle, hDC: HDC): TGLint{. + dynlib: dllname, importc: "wglReleasePbufferDCARB".} +proc wglDestroyPbufferARB*(hPbuffer: THandle): BOOL{.dynlib: dllname, + importc: "wglDestroyPbufferARB".} +proc wglQueryPbufferARB*(hPbuffer: THandle, iAttribute: TGLint, piValue: PGLint): BOOL{. + dynlib: dllname, importc: "wglQueryPbufferARB".} +proc wglSwapIntervalEXT*(interval: TGLint): BOOL{.dynlib: dllname, + importc: "wglSwapIntervalEXT".} +proc wglGetSwapIntervalEXT*(): TGLint{.dynlib: dllname, + importc: "wglGetSwapIntervalEXT".} +const + WGL_BIND_TO_TEXTURE_RGB_ARB* = 0x00002070 + WGL_BIND_TO_TEXTURE_RGBA_ARB* = 0x00002071 + WGL_TEXTURE_FORMAT_ARB* = 0x00002072 + WGL_TEXTURE_TARGET_ARB* = 0x00002073 + WGL_MIPMAP_TEXTURE_ARB* = 0x00002074 + WGL_TEXTURE_RGB_ARB* = 0x00002075 + WGL_TEXTURE_RGBA_ARB* = 0x00002076 + WGL_NO_TEXTURE_ARB* = 0x00002077 + WGL_TEXTURE_CUBE_MAP_ARB* = 0x00002078 + WGL_TEXTURE_1D_ARB* = 0x00002079 + WGL_TEXTURE_2D_ARB* = 0x0000207A # WGL_NO_TEXTURE_ARB { already defined } + WGL_MIPMAP_LEVEL_ARB* = 0x0000207B + WGL_CUBE_MAP_FACE_ARB* = 0x0000207C + WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB* = 0x0000207D + WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB* = 0x0000207E + WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB* = 0x0000207F + WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB* = 0x00002080 + WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB* = 0x00002081 + WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB* = 0x00002082 + WGL_FRONT_LEFT_ARB* = 0x00002083 + WGL_FRONT_RIGHT_ARB* = 0x00002084 + WGL_BACK_LEFT_ARB* = 0x00002085 + WGL_BACK_RIGHT_ARB* = 0x00002086 + WGL_AUX0_ARB* = 0x00002087 + WGL_AUX1_ARB* = 0x00002088 + WGL_AUX2_ARB* = 0x00002089 + WGL_AUX3_ARB* = 0x0000208A + WGL_AUX4_ARB* = 0x0000208B + WGL_AUX5_ARB* = 0x0000208C + WGL_AUX6_ARB* = 0x0000208D + WGL_AUX7_ARB* = 0x0000208E + WGL_AUX8_ARB* = 0x0000208F + WGL_AUX9_ARB* = 0x00002090 + +proc wglBindTexImageARB*(hPbuffer: THandle, iBuffer: TGLint): BOOL{. + dynlib: dllname, importc: "wglBindTexImageARB".} +proc wglReleaseTexImageARB*(hPbuffer: THandle, iBuffer: TGLint): BOOL{. + dynlib: dllname, importc: "wglReleaseTexImageARB".} +proc wglSetPbufferAttribARB*(hPbuffer: THandle, piAttribList: PGLint): BOOL{. + dynlib: dllname, importc: "wglSetPbufferAttribARB".} +proc wglGetExtensionsStringEXT*(): cstring{.dynlib: dllname, + importc: "wglGetExtensionsStringEXT".} +proc wglMakeContextCurrentEXT*(hDrawDC: HDC, hReadDC: HDC, hglrc: HGLRC): BOOL{. + dynlib: dllname, importc: "wglMakeContextCurrentEXT".} +proc wglGetCurrentReadDCEXT*(): HDC{.dynlib: dllname, + importc: "wglGetCurrentReadDCEXT".} +const + WGL_DRAW_TO_PBUFFER_EXT* = 0x0000202D + WGL_MAX_PBUFFER_PIXELS_EXT* = 0x0000202E + WGL_MAX_PBUFFER_WIDTH_EXT* = 0x0000202F + WGL_MAX_PBUFFER_HEIGHT_EXT* = 0x00002030 + WGL_OPTIMAL_PBUFFER_WIDTH_EXT* = 0x00002031 + WGL_OPTIMAL_PBUFFER_HEIGHT_EXT* = 0x00002032 + WGL_PBUFFER_LARGEST_EXT* = 0x00002033 + WGL_PBUFFER_WIDTH_EXT* = 0x00002034 + WGL_PBUFFER_HEIGHT_EXT* = 0x00002035 + +proc wglCreatePbufferEXT*(hDC: HDC, iPixelFormat: TGLint, iWidth: TGLint, + iHeight: TGLint, piAttribList: PGLint): THandle{. + dynlib: dllname, importc: "wglCreatePbufferEXT".} +proc wglGetPbufferDCEXT*(hPbuffer: THandle): HDC{.dynlib: dllname, + importc: "wglGetPbufferDCEXT".} +proc wglReleasePbufferDCEXT*(hPbuffer: THandle, hDC: HDC): TGLint{. + dynlib: dllname, importc: "wglReleasePbufferDCEXT".} +proc wglDestroyPbufferEXT*(hPbuffer: THandle): BOOL{.dynlib: dllname, + importc: "wglDestroyPbufferEXT".} +proc wglQueryPbufferEXT*(hPbuffer: THandle, iAttribute: TGLint, piValue: PGLint): BOOL{. + dynlib: dllname, importc: "wglQueryPbufferEXT".} +const + WGL_NUMBER_PIXEL_FORMATS_EXT* = 0x00002000 + WGL_DRAW_TO_WINDOW_EXT* = 0x00002001 + WGL_DRAW_TO_BITMAP_EXT* = 0x00002002 + WGL_ACCELERATION_EXT* = 0x00002003 + WGL_NEED_PALETTE_EXT* = 0x00002004 + WGL_NEED_SYSTEM_PALETTE_EXT* = 0x00002005 + WGL_SWAP_LAYER_BUFFERS_EXT* = 0x00002006 + WGL_SWAP_METHOD_EXT* = 0x00002007 + WGL_NUMBER_OVERLAYS_EXT* = 0x00002008 + WGL_NUMBER_UNDERLAYS_EXT* = 0x00002009 + WGL_TRANSPARENT_EXT* = 0x0000200A + WGL_TRANSPARENT_VALUE_EXT* = 0x0000200B + WGL_SHARE_DEPTH_EXT* = 0x0000200C + WGL_SHARE_STENCIL_EXT* = 0x0000200D + WGL_SHARE_ACCUM_EXT* = 0x0000200E + WGL_SUPPORT_GDI_EXT* = 0x0000200F + WGL_SUPPORT_OPENGL_EXT* = 0x00002010 + WGL_DOUBLE_BUFFER_EXT* = 0x00002011 + WGL_STEREO_EXT* = 0x00002012 + WGL_PIXEL_TYPE_EXT* = 0x00002013 + WGL_COLOR_BITS_EXT* = 0x00002014 + WGL_RED_BITS_EXT* = 0x00002015 + WGL_RED_SHIFT_EXT* = 0x00002016 + WGL_GREEN_BITS_EXT* = 0x00002017 + WGL_GREEN_SHIFT_EXT* = 0x00002018 + WGL_BLUE_BITS_EXT* = 0x00002019 + WGL_BLUE_SHIFT_EXT* = 0x0000201A + WGL_ALPHA_BITS_EXT* = 0x0000201B + WGL_ALPHA_SHIFT_EXT* = 0x0000201C + WGL_ACCUM_BITS_EXT* = 0x0000201D + WGL_ACCUM_RED_BITS_EXT* = 0x0000201E + WGL_ACCUM_GREEN_BITS_EXT* = 0x0000201F + WGL_ACCUM_BLUE_BITS_EXT* = 0x00002020 + WGL_ACCUM_ALPHA_BITS_EXT* = 0x00002021 + WGL_DEPTH_BITS_EXT* = 0x00002022 + WGL_STENCIL_BITS_EXT* = 0x00002023 + WGL_AUX_BUFFERS_EXT* = 0x00002024 + WGL_NO_ACCELERATION_EXT* = 0x00002025 + WGL_GENERIC_ACCELERATION_EXT* = 0x00002026 + WGL_FULL_ACCELERATION_EXT* = 0x00002027 + WGL_SWAP_EXCHANGE_EXT* = 0x00002028 + WGL_SWAP_COPY_EXT* = 0x00002029 + WGL_SWAP_UNDEFINED_EXT* = 0x0000202A + WGL_TYPE_RGBA_EXT* = 0x0000202B + WGL_TYPE_COLORINDEX_EXT* = 0x0000202C + +proc wglGetPixelFormatAttribivEXT*(hdc: HDC, iPixelFormat: TGLint, + iLayerPlane: TGLint, nAttributes: TGLuint, + piAttributes: PGLint, piValues: PGLint): BOOL{. + dynlib: dllname, importc: "wglGetPixelFormatAttribivEXT".} +proc wglGetPixelFormatAttribfvEXT*(hdc: HDC, iPixelFormat: TGLint, + iLayerPlane: TGLint, nAttributes: TGLuint, + piAttributes: PGLint, pfValues: PGLfloat): BOOL{. + dynlib: dllname, importc: "wglGetPixelFormatAttribfvEXT".} +proc wglChoosePixelFormatEXT*(hdc: HDC, piAttribIList: PGLint, + pfAttribFList: PGLfloat, nMaxFormats: TGLuint, + piFormats: PGLint, nNumFormats: PGLuint): BOOL{. + dynlib: dllname, importc: "wglChoosePixelFormatEXT".} +const + WGL_DIGITAL_VIDEO_CURSOR_ALPHA_FRAMEBUFFER_I3D* = 0x00002050 + WGL_DIGITAL_VIDEO_CURSOR_ALPHA_VALUE_I3D* = 0x00002051 + WGL_DIGITAL_VIDEO_CURSOR_INCLUDED_I3D* = 0x00002052 + WGL_DIGITAL_VIDEO_GAMMA_CORRECTED_I3D* = 0x00002053 + +proc wglGetDigitalVideoParametersI3D*(hDC: HDC, iAttribute: TGLint, + piValue: PGLint): BOOL{.dynlib: dllname, + importc: "wglGetDigitalVideoParametersI3D".} +proc wglSetDigitalVideoParametersI3D*(hDC: HDC, iAttribute: TGLint, + piValue: PGLint): BOOL{.dynlib: dllname, + importc: "wglSetDigitalVideoParametersI3D".} +const + WGL_GAMMA_TABLE_SIZE_I3D* = 0x0000204E + WGL_GAMMA_EXCLUDE_DESKTOP_I3D* = 0x0000204F + +proc wglGetGammaTableParametersI3D*(hDC: HDC, iAttribute: TGLint, + piValue: PGLint): BOOL{.dynlib: dllname, + importc: "wglGetGammaTableParametersI3D".} +proc wglSetGammaTableParametersI3D*(hDC: HDC, iAttribute: TGLint, + piValue: PGLint): BOOL{.dynlib: dllname, + importc: "wglSetGammaTableParametersI3D".} +proc wglGetGammaTableI3D*(hDC: HDC, iEntries: TGLint, puRed: PGLUSHORT, + puGreen: PGLUSHORT, puBlue: PGLUSHORT): BOOL{. + dynlib: dllname, importc: "wglGetGammaTableI3D".} +proc wglSetGammaTableI3D*(hDC: HDC, iEntries: TGLint, puRed: PGLUSHORT, + puGreen: PGLUSHORT, puBlue: PGLUSHORT): BOOL{. + dynlib: dllname, importc: "wglSetGammaTableI3D".} +const + WGL_GENLOCK_SOURCE_MULTIVIEW_I3D* = 0x00002044 + WGL_GENLOCK_SOURCE_EXTERNAL_SYNC_I3D* = 0x00002045 + WGL_GENLOCK_SOURCE_EXTERNAL_FIELD_I3D* = 0x00002046 + WGL_GENLOCK_SOURCE_EXTERNAL_TTL_I3D* = 0x00002047 + WGL_GENLOCK_SOURCE_DIGITAL_SYNC_I3D* = 0x00002048 + WGL_GENLOCK_SOURCE_DIGITAL_FIELD_I3D* = 0x00002049 + WGL_GENLOCK_SOURCE_EDGE_FALLING_I3D* = 0x0000204A + WGL_GENLOCK_SOURCE_EDGE_RISING_I3D* = 0x0000204B + WGL_GENLOCK_SOURCE_EDGE_BOTH_I3D* = 0x0000204C + WGL_FLOAT_COMPONENTS_NV* = 0x000020B0 + WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_R_NV* = 0x000020B1 + WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RG_NV* = 0x000020B2 + WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV* = 0x000020B3 + WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGBA_NV* = 0x000020B4 + WGL_TEXTURE_FLOAT_R_NV* = 0x000020B5 + WGL_TEXTURE_FLOAT_RG_NV* = 0x000020B6 + WGL_TEXTURE_FLOAT_RGB_NV* = 0x000020B7 + WGL_TEXTURE_FLOAT_RGBA_NV* = 0x000020B8 + +proc wglEnableGenlockI3D*(hDC: HDC): BOOL{.dynlib: dllname, + importc: "wglEnableGenlockI3D".} +proc wglDisableGenlockI3D*(hDC: HDC): BOOL{.dynlib: dllname, + importc: "wglDisableGenlockI3D".} +proc wglIsEnabledGenlockI3D*(hDC: HDC, pFlag: PBOOL): BOOL{.dynlib: dllname, + importc: "wglIsEnabledGenlockI3D".} +proc wglGenlockSourceI3D*(hDC: HDC, uSource: TGLuint): BOOL{.dynlib: dllname, + importc: "wglGenlockSourceI3D".} +proc wglGetGenlockSourceI3D*(hDC: HDC, uSource: PGLUINT): BOOL{.dynlib: dllname, + importc: "wglGetGenlockSourceI3D".} +proc wglGenlockSourceEdgeI3D*(hDC: HDC, uEdge: TGLuint): BOOL{.dynlib: dllname, + importc: "wglGenlockSourceEdgeI3D".} +proc wglGetGenlockSourceEdgeI3D*(hDC: HDC, uEdge: PGLUINT): BOOL{. + dynlib: dllname, importc: "wglGetGenlockSourceEdgeI3D".} +proc wglGenlockSampleRateI3D*(hDC: HDC, uRate: TGLuint): BOOL{.dynlib: dllname, + importc: "wglGenlockSampleRateI3D".} +proc wglGetGenlockSampleRateI3D*(hDC: HDC, uRate: PGLUINT): BOOL{. + dynlib: dllname, importc: "wglGetGenlockSampleRateI3D".} +proc wglGenlockSourceDelayI3D*(hDC: HDC, uDelay: TGLuint): BOOL{. + dynlib: dllname, importc: "wglGenlockSourceDelayI3D".} +proc wglGetGenlockSourceDelayI3D*(hDC: HDC, uDelay: PGLUINT): BOOL{. + dynlib: dllname, importc: "wglGetGenlockSourceDelayI3D".} +proc wglQueryGenlockMaxSourceDelayI3D*(hDC: HDC, uMaxLineDelay: PGLUINT, + uMaxPixelDelay: PGLUINT): BOOL{. + dynlib: dllname, importc: "wglQueryGenlockMaxSourceDelayI3D".} +const + WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV* = 0x000020A0 + WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV* = 0x000020A1 + WGL_TEXTURE_RECTANGLE_NV* = 0x000020A2 + +const + WGL_RGBA_FLOAT_MODE_ATI* = 0x00008820 + WGL_COLOR_CLEAR_UNCLAMPED_VALUE_ATI* = 0x00008835 + WGL_TYPE_RGBA_FLOAT_ATI* = 0x000021A0 + +# implementation diff --git a/tests/manyloc/packages/package1/p1.babel b/tests/manyloc/packages/package1/p1.babel new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/manyloc/packages/package2/p2.babel b/tests/manyloc/packages/package2/p2.babel new file mode 100644 index 0000000000..e69de29bb2 From 79586487be202ffb7499a8917ac33024ce9c3a16 Mon Sep 17 00:00:00 2001 From: Araq Date: Fri, 27 Jun 2014 16:08:09 +0200 Subject: [PATCH 008/234] compiles again --- compiler/lowerings.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/lowerings.nim b/compiler/lowerings.nim index e7b5cd9870..74690ac0cd 100644 --- a/compiler/lowerings.nim +++ b/compiler/lowerings.nim @@ -114,7 +114,7 @@ proc indirectAccess*(a: PNode, b: string, info: TLineInfo): PNode = #if field == nil: # debug deref.typ # echo deref.typ.id - internalAssert field != nil, b + internalAssert field != nil addSon(deref, a) result = newNodeI(nkDotExpr, info) addSon(result, deref) From f59ca2736dac0e544c11aaca431408931d3e21de Mon Sep 17 00:00:00 2001 From: Felix Krause Date: Fri, 27 Jun 2014 16:57:01 +0200 Subject: [PATCH 009/234] Fixed `==` for PTables, added test. --- lib/pure/collections/tables.nim | 7 +++++-- tests/table/ptables.nim | 9 +++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/lib/pure/collections/tables.nim b/lib/pure/collections/tables.nim index ce9df09e10..146cb76c9a 100644 --- a/lib/pure/collections/tables.nim +++ b/lib/pure/collections/tables.nim @@ -246,7 +246,8 @@ template equalsImpl() = # different insertion orders mean different 'data' seqs, so we have # to use the slow route here: for key, val in s: - if not hasKey(t, key): return false + # prefix notation leads to automatic dereference in case of PTable + if not t.hasKey(key): return false if t[key] != val: return false return true @@ -332,7 +333,9 @@ proc `$`*[A, B](t: PTable[A, B]): string = dollarImpl() proc `==`*[A, B](s, t: PTable[A, B]): bool = - equalsImpl() + if isNil(s): result = isNil(t) + elif isNil(t): result = false + else: equalsImpl() proc newTableFrom*[A, B, C](collection: A, index: proc(x: B): C): PTable[C, B] = ## Index the collection with the proc provided. diff --git a/tests/table/ptables.nim b/tests/table/ptables.nim index ec52d08c33..79a9aab171 100644 --- a/tests/table/ptables.nim +++ b/tests/table/ptables.nim @@ -104,6 +104,15 @@ block countTableTest1: block SyntaxTest: var x = newTable[int, string]({:}) +block nilTest: + var i, j: PTable[int, int] = nil + assert i == j + j = newTable[int, int]() + assert i != j + assert j != i + i = newTable[int, int]() + assert i == j + proc orderedTableSortTest() = var t = newOrderedTable[string, int](2) for key, val in items(data): t[key] = val From 59f61bae05047a0f110ca419272dbe3d53a412a6 Mon Sep 17 00:00:00 2001 From: Araq Date: Sat, 28 Jun 2014 01:03:07 +0200 Subject: [PATCH 010/234] new jester compiles --- compiler/lambdalifting.nim | 24 ++++++++++++++++-------- compiler/lowerings.nim | 10 ++++++++++ tests/closure/tjester.nim | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 8 deletions(-) create mode 100644 tests/closure/tjester.nim diff --git a/compiler/lambdalifting.nim b/compiler/lambdalifting.nim index 402ad7d3de..ee380b305d 100644 --- a/compiler/lambdalifting.nim +++ b/compiler/lambdalifting.nim @@ -240,9 +240,6 @@ proc newEnv(o: POuterContext; up: PEnv, n: PNode; owner: PSym): PEnv = result.next = o.head o.head = result if owner.kind != skModule and (up == nil or up.fn != owner): - if owner.ast == nil: - debug owner - echo owner.name.s let param = getEnvParam(owner) if param != nil: result.obj = param.typ.sons[0] @@ -808,8 +805,9 @@ proc transformOuterProc(o: POuterContext, n: PNode; it: TIter): PNode = if it.fn.kind == skClosureIterator and interestingIterVar(local) and it.fn == local.owner: # every local goes through the closure: - if not containsOrIncl(o.capturedVars, local.id): - addField(it.obj, local) + #if not containsOrIncl(o.capturedVars, local.id): + # addField(it.obj, local) + addUniqueField(it.obj, local) return indirectAccess(newSymNode(it.closureParam), local, n.info) var closure = PEnv(idTableGet(o.lambdasToEnv, local)) @@ -853,10 +851,18 @@ proc transformOuterProc(o: POuterContext, n: PNode; it: TIter): PNode = of nkLambdaKinds, nkIteratorDef: if n.typ != nil: result = transformOuterProc(o, n.sons[namePos], it) - of nkProcDef, nkMethodDef, nkConverterDef, nkMacroDef, nkTemplateDef, - nkClosure: + of nkProcDef, nkMethodDef, nkConverterDef, nkMacroDef, nkTemplateDef: # don't recurse here: discard + of nkClosure: + if n.sons[0].kind == nkSym: + var local = n.sons[0].sym + if isInnerProc(local, o.fn) and o.processed.contains(local.id): + o.processed.excl(local.id) + let body = local.getBody + let newBody = transformOuterProcBody(o, body, initIter(local)) + if newBody != nil: + local.ast.sons[bodyPos] = newBody of nkHiddenStdConv, nkHiddenSubConv, nkConv: let x = transformOuterProc(o, n.sons[1], it) if x != nil: n.sons[1] = x @@ -878,6 +884,8 @@ proc liftLambdas*(fn: PSym, body: PNode): PNode = # ignore forward declaration: result = body else: + #if fn.name.s == "cbOuter": + # echo rendertree(fn.ast, {renderIds}) var o = newOuterContext(fn) let ex = closureCreationPoint(body) let env = newEnv(o, nil, ex, fn) @@ -890,7 +898,7 @@ proc liftLambdas*(fn: PSym, body: PNode): PNode = discard transformOuterProcBody(o, body, initIter(fn)) result = ex finishEnvironments(o) - #if fn.name.s == "cbOuter" or fn.name.s == "factory2": + #if fn.name.s == "cbOuter": # echo rendertree(result, {renderIds}) proc liftLambdasForTopLevel*(module: PSym, body: PNode): PNode = diff --git a/compiler/lowerings.nim b/compiler/lowerings.nim index 74690ac0cd..5b61a9cae9 100644 --- a/compiler/lowerings.nim +++ b/compiler/lowerings.nim @@ -90,6 +90,16 @@ proc addField*(obj: PType; s: PSym) = field.position = sonsLen(obj.n) addSon(obj.n, newSymNode(field)) +proc addUniqueField*(obj: PType; s: PSym) = + let fieldName = getIdent(s.name.s & $s.id) + if lookupInRecord(obj.n, fieldName) == nil: + var field = newSym(skField, fieldName, s.owner, s.info) + let t = skipIntLit(s.typ) + field.typ = t + assert t.kind != tyStmt + field.position = sonsLen(obj.n) + addSon(obj.n, newSymNode(field)) + proc newDotExpr(obj, b: PSym): PNode = result = newNodeI(nkDotExpr, obj.info) let field = getSymFromList(obj.typ.n, getIdent(b.name.s & $b.id)) diff --git a/tests/closure/tjester.nim b/tests/closure/tjester.nim new file mode 100644 index 0000000000..48e5186f03 --- /dev/null +++ b/tests/closure/tjester.nim @@ -0,0 +1,32 @@ +discard """ + output: '''baro0''' +""" + +type + Future[T] = ref object + data: T + callback: proc () {.closure.} + +proc cbOuter(response: string) {.closure, discardable.} = + iterator cbIter(): Future[int] {.closure.} = + for i in 0..7: + proc foo(): int = + iterator fooIter(): Future[int] {.closure.} = + echo response, i + yield Future[int](data: 17) + var iterVar = fooIter + iterVar().data + yield Future[int](data: foo()) + + var iterVar2 = cbIter + proc cb2() {.closure.} = + try: + if not finished(iterVar2): + let next = iterVar2() + if next != nil: + next.callback = cb2 + except: + echo "WTF" + cb2() + +cbOuter "baro" From 684865babbf8d86f9ef3fb87472aa8c7cb988759 Mon Sep 17 00:00:00 2001 From: Araq Date: Sat, 28 Jun 2014 13:56:05 +0200 Subject: [PATCH 011/234] minor changes to todo.txt --- todo.txt | 5 +++++ web/news.txt | 2 ++ 2 files changed, 7 insertions(+) diff --git a/todo.txt b/todo.txt index df18ff7e9e..9b96cec478 100644 --- a/todo.txt +++ b/todo.txt @@ -1,6 +1,11 @@ version 0.9.6 ============= +- move pas2nim into its own repository +- tester: .elf +- overloading of '='; general lift mechanism + + Concurrency ----------- diff --git a/web/news.txt b/web/news.txt index b7403a3c72..74a48493a4 100644 --- a/web/news.txt +++ b/web/news.txt @@ -12,6 +12,8 @@ News - ``spawn`` now uses an elaborate self-adapting thread pool and as such has been moved into its own module. So to use it, you now have to import ``threadpool``. + - ``c2nim`` moved into its own repository and is now a Babel package. + - ``pas2nim`` moved into its own repository and is now a Babel package. Library Additions From 5f8ab1653ad38faf395daf1b8a70249f6954b1ba Mon Sep 17 00:00:00 2001 From: Araq Date: Mon, 30 Jun 2014 10:40:49 +0200 Subject: [PATCH 012/234] c2nim is not part of the compiler anymore --- compiler/c2nim/c2nim.nim | 92 -- compiler/c2nim/clex.nim | 787 --------- compiler/c2nim/cparse.nim | 2272 -------------------------- compiler/c2nim/cpp.nim | 347 ---- compiler/c2nim/nimrod.cfg | 4 - compiler/c2nim/tests/enum.h | 40 - compiler/c2nim/tests/matrix.h | 240 --- compiler/c2nim/tests/struct_anonym.h | 27 - compiler/c2nim/tests/systest.c | 622 ------- compiler/c2nim/tests/systest2.c | 17 - compiler/c2nim/tests/vincent.c | 33 - compiler/c2nim/tests/vincent.h | 3 - compiler/pas2nim/nimrod.cfg | 4 - compiler/pas2nim/pas2nim.nim | 64 - compiler/pas2nim/paslex.nim | 570 ------- compiler/pas2nim/pasparse.nim | 1513 ----------------- doc/c2nim.txt | 295 ---- koch.nim | 3 +- todo.txt | 2 - web/nimrod.ini | 4 +- 20 files changed, 3 insertions(+), 6936 deletions(-) delete mode 100644 compiler/c2nim/c2nim.nim delete mode 100644 compiler/c2nim/clex.nim delete mode 100644 compiler/c2nim/cparse.nim delete mode 100644 compiler/c2nim/cpp.nim delete mode 100644 compiler/c2nim/nimrod.cfg delete mode 100644 compiler/c2nim/tests/enum.h delete mode 100644 compiler/c2nim/tests/matrix.h delete mode 100644 compiler/c2nim/tests/struct_anonym.h delete mode 100644 compiler/c2nim/tests/systest.c delete mode 100644 compiler/c2nim/tests/systest2.c delete mode 100644 compiler/c2nim/tests/vincent.c delete mode 100644 compiler/c2nim/tests/vincent.h delete mode 100644 compiler/pas2nim/nimrod.cfg delete mode 100644 compiler/pas2nim/pas2nim.nim delete mode 100644 compiler/pas2nim/paslex.nim delete mode 100644 compiler/pas2nim/pasparse.nim delete mode 100644 doc/c2nim.txt diff --git a/compiler/c2nim/c2nim.nim b/compiler/c2nim/c2nim.nim deleted file mode 100644 index 9b12b9e47f..0000000000 --- a/compiler/c2nim/c2nim.nim +++ /dev/null @@ -1,92 +0,0 @@ -# -# -# c2nim - C to Nimrod source converter -# (c) Copyright 2013 Andreas Rumpf -# -# See the file "copying.txt", included in this -# distribution, for details about the copyright. -# - -import - strutils, os, times, parseopt, llstream, ast, renderer, options, msgs, - clex, cparse - -const - Version = NimrodVersion - Usage = """ -c2nim - C to Nimrod source converter - (c) 2013 Andreas Rumpf -Usage: c2nim [options] inputfile [options] -Options: - -o, --out:FILE set output filename - --cpp process C++ input file - --dynlib:SYMBOL import from dynlib: SYMBOL will be used for the import - --header:HEADER_FILE import from a HEADER_FILE (discouraged!) - --cdecl annotate procs with ``{.cdecl.}`` - --stdcall annotate procs with ``{.stdcall.}`` - --ref convert typ* to ref typ (default: ptr typ) - --prefix:PREFIX strip prefix for the generated Nimrod identifiers - (multiple --prefix options are supported) - --suffix:SUFFIX strip suffix for the generated Nimrod identifiers - (multiple --suffix options are supported) - --skipinclude do not convert ``#include`` to ``import`` - --typeprefixes generate ``T`` and ``P`` type prefixes - --skipcomments do not copy comments - --ignoreRValueRefs translate C++'s ``T&&`` to ``T`` instead ``of var T`` - --keepBodies keep C++'s method bodies - --spliceHeader parse and emit header before source file - -v, --version write c2nim's version - -h, --help show this help -""" - -proc parse(infile: string, options: PParserOptions): PNode = - var stream = llStreamOpen(infile, fmRead) - if stream == nil: rawMessage(errCannotOpenFile, infile) - var p: TParser - openParser(p, infile, stream, options) - result = parseUnit(p) - closeParser(p) - -proc main(infile, outfile: string, options: PParserOptions, spliceHeader: bool) = - var start = getTime() - if spliceHeader and infile.splitFile.ext == ".c" and existsFile(infile.changeFileExt(".h")): - var header_module = parse(infile.changeFileExt(".h"), options) - var source_module = parse(infile, options) - for n in source_module: - addson(header_module, n) - renderModule(header_module, outfile) - else: - renderModule(parse(infile, options), outfile) - rawMessage(hintSuccessX, [$gLinesCompiled, $(getTime() - start), - formatSize(getTotalMem())]) - -var - infile = "" - outfile = "" - spliceHeader = false - parserOptions = newParserOptions() -for kind, key, val in getopt(): - case kind - of cmdArgument: infile = key - of cmdLongOption, cmdShortOption: - case key.toLower - of "help", "h": - stdout.write(Usage) - quit(0) - of "version", "v": - stdout.write(Version & "\n") - quit(0) - of "o", "out": outfile = val - of "spliceheader": spliceHeader = true - else: - if not parserOptions.setOption(key, val): - stdout.writeln("[Error] unknown option: " & key) - of cmdEnd: assert(false) -if infile.len == 0: - # no filename has been given, so we show the help: - stdout.write(Usage) -else: - if outfile.len == 0: - outfile = changeFileExt(infile, "nim") - infile = addFileExt(infile, "h") - main(infile, outfile, parserOptions, spliceHeader) diff --git a/compiler/c2nim/clex.nim b/compiler/c2nim/clex.nim deleted file mode 100644 index 3934eea63d..0000000000 --- a/compiler/c2nim/clex.nim +++ /dev/null @@ -1,787 +0,0 @@ -# -# -# c2nim - C to Nimrod source converter -# (c) Copyright 2012 Andreas Rumpf -# -# See the file "copying.txt", included in this -# distribution, for details about the copyright. -# - -# This module implements an Ansi C scanner. This is an adaption from -# the scanner module. Keywords are not handled here, but in the parser to make -# it more flexible. - - -import - options, msgs, strutils, platform, nimlexbase, llstream - -const - MaxLineLength* = 80 # lines longer than this lead to a warning - numChars*: TCharSet = {'0'..'9', 'a'..'z', 'A'..'Z'} - SymChars*: TCharSet = {'a'..'z', 'A'..'Z', '0'..'9', '_', '\x80'..'\xFF'} - SymStartChars*: TCharSet = {'a'..'z', 'A'..'Z', '_', '\x80'..'\xFF'} - -type - TTokKind* = enum - pxInvalid, pxEof, - pxMacroParam, # fake token: macro parameter (with its index) - pxStarComment, # /* */ comment - pxLineComment, # // comment - pxDirective, # #define, etc. - pxDirectiveParLe, # #define m( with parle (yes, C is that ugly!) - pxDirConc, # ## - pxNewLine, # newline: end of directive - pxAmp, # & - pxAmpAmp, # && - pxAmpAsgn, # &= - pxAmpAmpAsgn, # &&= - pxBar, # | - pxBarBar, # || - pxBarAsgn, # |= - pxBarBarAsgn, # ||= - pxNot, # ! - pxPlusPlus, # ++ - pxMinusMinus, # -- - pxPlus, # + - pxPlusAsgn, # += - pxMinus, # - - pxMinusAsgn, # -= - pxMod, # % - pxModAsgn, # %= - pxSlash, # / - pxSlashAsgn, # /= - pxStar, # * - pxStarAsgn, # *= - pxHat, # ^ - pxHatAsgn, # ^= - pxAsgn, # = - pxEquals, # == - pxDot, # . - pxDotDotDot, # ... - pxLe, # <= - pxLt, # < - pxGe, # >= - pxGt, # > - pxNeq, # != - pxConditional, # ? - pxShl, # << - pxShlAsgn, # <<= - pxShr, # >> - pxShrAsgn, # >>= - pxTilde, # ~ - pxTildeAsgn, # ~= - pxArrow, # -> - pxScope, # :: - - pxStrLit, - pxCharLit, - pxSymbol, # a symbol - pxIntLit, - pxInt64Lit, # long constant like 0x70fffffff or out of int range - pxFloatLit, - pxParLe, pxBracketLe, pxCurlyLe, # this order is important - pxParRi, pxBracketRi, pxCurlyRi, # for macro argument parsing! - pxComma, pxSemiColon, pxColon, - pxAngleRi # '>' but determined to be the end of a - # template's angle bracket - TTokKinds* = set[TTokKind] - -type - TNumericalBase* = enum base10, base2, base8, base16 - TToken* = object - xkind*: TTokKind # the type of the token - s*: string # parsed symbol, char or string literal - iNumber*: BiggestInt # the parsed integer literal; - # if xkind == pxMacroParam: parameter's position - fNumber*: BiggestFloat # the parsed floating point literal - base*: TNumericalBase # the numerical base; only valid for int - # or float literals - next*: ref TToken # for C we need arbitrary look-ahead :-( - - TLexer* = object of TBaseLexer - fileIdx*: int32 - inDirective: bool - -proc getTok*(L: var TLexer, tok: var TToken) -proc printTok*(tok: TToken) -proc `$`*(tok: TToken): string -# implementation - -var - gLinesCompiled*: int - -proc fillToken(L: var TToken) = - L.xkind = pxInvalid - L.iNumber = 0 - L.s = "" - L.fNumber = 0.0 - L.base = base10 - -proc openLexer*(lex: var TLexer, filename: string, inputstream: PLLStream) = - openBaseLexer(lex, inputstream) - lex.fileIdx = filename.fileInfoIdx - -proc closeLexer*(lex: var TLexer) = - inc(gLinesCompiled, lex.LineNumber) - closeBaseLexer(lex) - -proc getColumn*(L: TLexer): int = - result = getColNumber(L, L.bufPos) - -proc getLineInfo*(L: TLexer): TLineInfo = - result = newLineInfo(L.fileIdx, L.linenumber, getColNumber(L, L.bufpos)) - -proc lexMessage*(L: TLexer, msg: TMsgKind, arg = "") = - msgs.GlobalError(getLineInfo(L), msg, arg) - -proc lexMessagePos(L: var TLexer, msg: TMsgKind, pos: int, arg = "") = - var info = newLineInfo(L.fileIdx, L.linenumber, pos - L.lineStart) - msgs.GlobalError(info, msg, arg) - -proc tokKindToStr*(k: TTokKind): string = - case k - of pxEof: result = "[EOF]" - of pxInvalid: result = "[invalid]" - of pxMacroParam: result = "[macro param]" - of pxStarComment, pxLineComment: result = "[comment]" - of pxStrLit: result = "[string literal]" - of pxCharLit: result = "[char literal]" - - of pxDirective, pxDirectiveParLe: result = "#" # #define, etc. - of pxDirConc: result = "##" - of pxNewLine: result = "[NewLine]" - of pxAmp: result = "&" # & - of pxAmpAmp: result = "&&" # && - of pxAmpAsgn: result = "&=" # &= - of pxAmpAmpAsgn: result = "&&=" # &&= - of pxBar: result = "|" # | - of pxBarBar: result = "||" # || - of pxBarAsgn: result = "|=" # |= - of pxBarBarAsgn: result = "||=" # ||= - of pxNot: result = "!" # ! - of pxPlusPlus: result = "++" # ++ - of pxMinusMinus: result = "--" # -- - of pxPlus: result = "+" # + - of pxPlusAsgn: result = "+=" # += - of pxMinus: result = "-" # - - of pxMinusAsgn: result = "-=" # -= - of pxMod: result = "%" # % - of pxModAsgn: result = "%=" # %= - of pxSlash: result = "/" # / - of pxSlashAsgn: result = "/=" # /= - of pxStar: result = "*" # * - of pxStarAsgn: result = "*=" # *= - of pxHat: result = "^" # ^ - of pxHatAsgn: result = "^=" # ^= - of pxAsgn: result = "=" # = - of pxEquals: result = "==" # == - of pxDot: result = "." # . - of pxDotDotDot: result = "..." # ... - of pxLe: result = "<=" # <= - of pxLt: result = "<" # < - of pxGe: result = ">=" # >= - of pxGt: result = ">" # > - of pxNeq: result = "!=" # != - of pxConditional: result = "?" - of pxShl: result = "<<" - of pxShlAsgn: result = "<<=" - of pxShr: result = ">>" - of pxShrAsgn: result = ">>=" - of pxTilde: result = "~" - of pxTildeAsgn: result = "~=" - of pxArrow: result = "->" - of pxScope: result = "::" - - of pxSymbol: result = "[identifier]" - of pxIntLit, pxInt64Lit: result = "[integer literal]" - of pxFloatLit: result = "[floating point literal]" - of pxParLe: result = "(" - of pxParRi: result = ")" - of pxBracketLe: result = "[" - of pxBracketRi: result = "]" - of pxComma: result = "," - of pxSemiColon: result = ";" - of pxColon: result = ":" - of pxCurlyLe: result = "{" - of pxCurlyRi: result = "}" - of pxAngleRi: result = "> [end of template]" - -proc `$`(tok: TToken): string = - case tok.xkind - of pxSymbol, pxInvalid, pxStarComment, pxLineComment, pxStrLit: result = tok.s - of pxIntLit, pxInt64Lit: result = $tok.iNumber - of pxFloatLit: result = $tok.fNumber - else: result = tokKindToStr(tok.xkind) - -proc printTok(tok: TToken) = - writeln(stdout, $tok) - -proc matchUnderscoreChars(L: var TLexer, tok: var TToken, chars: TCharSet) = - # matches ([chars]_)* - var pos = L.bufpos # use registers for pos, buf - var buf = L.buf - while true: - if buf[pos] in chars: - add(tok.s, buf[pos]) - inc(pos) - else: - break - if buf[pos] == '_': - add(tok.s, '_') - inc(pos) - L.bufPos = pos - -proc isFloatLiteral(s: string): bool = - for i in countup(0, len(s)-1): - if s[i] in {'.', 'e', 'E'}: - return true - -proc getNumber2(L: var TLexer, tok: var TToken) = - var pos = L.bufpos + 2 # skip 0b - tok.base = base2 - var xi: BiggestInt = 0 - var bits = 0 - while true: - case L.buf[pos] - of 'A'..'Z', 'a'..'z': - # ignore type suffix: - inc(pos) - of '2'..'9', '.': - lexMessage(L, errInvalidNumber) - inc(pos) - of '_': - inc(pos) - of '0', '1': - xi = `shl`(xi, 1) or (ord(L.buf[pos]) - ord('0')) - inc(pos) - inc(bits) - else: break - tok.iNumber = xi - if (bits > 32): tok.xkind = pxInt64Lit - else: tok.xkind = pxIntLit - L.bufpos = pos - -proc getNumber8(L: var TLexer, tok: var TToken) = - var pos = L.bufpos + 1 # skip 0 - tok.base = base8 - var xi: BiggestInt = 0 - var bits = 0 - while true: - case L.buf[pos] - of 'A'..'Z', 'a'..'z': - # ignore type suffix: - inc(pos) - of '8'..'9', '.': - lexMessage(L, errInvalidNumber) - inc(pos) - of '_': - inc(pos) - of '0'..'7': - xi = `shl`(xi, 3) or (ord(L.buf[pos]) - ord('0')) - inc(pos) - inc(bits) - else: break - tok.iNumber = xi - if (bits > 12): tok.xkind = pxInt64Lit - else: tok.xkind = pxIntLit - L.bufpos = pos - -proc getNumber16(L: var TLexer, tok: var TToken) = - var pos = L.bufpos + 2 # skip 0x - tok.base = base16 - var xi: BiggestInt = 0 - var bits = 0 - while true: - case L.buf[pos] - of 'G'..'Z', 'g'..'z': - # ignore type suffix: - inc(pos) - of '_': inc(pos) - of '0'..'9': - xi = `shl`(xi, 4) or (ord(L.buf[pos]) - ord('0')) - inc(pos) - inc(bits, 4) - of 'a'..'f': - xi = `shl`(xi, 4) or (ord(L.buf[pos]) - ord('a') + 10) - inc(pos) - inc(bits, 4) - of 'A'..'F': - xi = `shl`(xi, 4) or (ord(L.buf[pos]) - ord('A') + 10) - inc(pos) - inc(bits, 4) - else: break - tok.iNumber = xi - if bits > 32: tok.xkind = pxInt64Lit - else: tok.xkind = pxIntLit - L.bufpos = pos - -proc getFloating(L: var TLexer, tok: var TToken) = - matchUnderscoreChars(L, tok, {'0'..'9'}) - if L.buf[L.bufpos] in {'e', 'E'}: - add(tok.s, L.buf[L.bufpos]) - inc(L.bufpos) - if L.buf[L.bufpos] in {'+', '-'}: - add(tok.s, L.buf[L.bufpos]) - inc(L.bufpos) - matchUnderscoreChars(L, tok, {'0'..'9'}) - -proc getNumber(L: var TLexer, tok: var TToken) = - tok.base = base10 - if L.buf[L.bufpos] == '.': - add(tok.s, "0.") - inc(L.bufpos) - getFloating(L, tok) - else: - matchUnderscoreChars(L, tok, {'0'..'9'}) - if L.buf[L.bufpos] == '.': - add(tok.s, '.') - inc(L.bufpos) - getFloating(L, tok) - try: - if isFloatLiteral(tok.s): - tok.fnumber = parseFloat(tok.s) - tok.xkind = pxFloatLit - else: - tok.iNumber = parseInt(tok.s) - if (tok.iNumber < low(int32)) or (tok.iNumber > high(int32)): - tok.xkind = pxInt64Lit - else: - tok.xkind = pxIntLit - except EInvalidValue: - lexMessage(L, errInvalidNumber, tok.s) - except EOverflow: - lexMessage(L, errNumberOutOfRange, tok.s) - # ignore type suffix: - while L.buf[L.bufpos] in {'A'..'Z', 'a'..'z'}: inc(L.bufpos) - -proc handleCRLF(L: var TLexer, pos: int): int = - case L.buf[pos] - of CR: result = nimlexbase.handleCR(L, pos) - of LF: result = nimlexbase.handleLF(L, pos) - else: result = pos - -proc escape(L: var TLexer, tok: var TToken, allowEmpty=false) = - inc(L.bufpos) # skip \ - case L.buf[L.bufpos] - of 'b', 'B': - add(tok.s, '\b') - inc(L.bufpos) - of 't', 'T': - add(tok.s, '\t') - inc(L.bufpos) - of 'n', 'N': - add(tok.s, '\L') - inc(L.bufpos) - of 'f', 'F': - add(tok.s, '\f') - inc(L.bufpos) - of 'r', 'R': - add(tok.s, '\r') - inc(L.bufpos) - of '\'': - add(tok.s, '\'') - inc(L.bufpos) - of '"': - add(tok.s, '"') - inc(L.bufpos) - of '\\': - add(tok.s, '\b') - inc(L.bufpos) - of '0'..'7': - var xi = ord(L.buf[L.bufpos]) - ord('0') - inc(L.bufpos) - if L.buf[L.bufpos] in {'0'..'7'}: - xi = (xi shl 3) or (ord(L.buf[L.bufpos]) - ord('0')) - inc(L.bufpos) - if L.buf[L.bufpos] in {'0'..'7'}: - xi = (xi shl 3) or (ord(L.buf[L.bufpos]) - ord('0')) - inc(L.bufpos) - add(tok.s, chr(xi)) - of 'x': - var xi = 0 - inc(L.bufpos) - while true: - case L.buf[L.bufpos] - of '0'..'9': - xi = `shl`(xi, 4) or (ord(L.buf[L.bufpos]) - ord('0')) - inc(L.bufpos) - of 'a'..'f': - xi = `shl`(xi, 4) or (ord(L.buf[L.bufpos]) - ord('a') + 10) - inc(L.bufpos) - of 'A'..'F': - xi = `shl`(xi, 4) or (ord(L.buf[L.bufpos]) - ord('A') + 10) - inc(L.bufpos) - else: - break - add(tok.s, chr(xi)) - elif not allowEmpty: - lexMessage(L, errInvalidCharacterConstant) - -proc getCharLit(L: var TLexer, tok: var TToken) = - inc(L.bufpos) # skip ' - if L.buf[L.bufpos] == '\\': - escape(L, tok) - else: - add(tok.s, L.buf[L.bufpos]) - inc(L.bufpos) - if L.buf[L.bufpos] == '\'': - inc(L.bufpos) - else: - lexMessage(L, errMissingFinalQuote) - tok.xkind = pxCharLit - -proc getString(L: var TLexer, tok: var TToken) = - var pos = L.bufPos + 1 # skip " - var buf = L.buf # put `buf` in a register - var line = L.linenumber # save linenumber for better error message - while true: - case buf[pos] - of '\"': - inc(pos) - break - of CR: - pos = nimlexbase.HandleCR(L, pos) - buf = L.buf - of LF: - pos = nimlexbase.HandleLF(L, pos) - buf = L.buf - of nimlexbase.EndOfFile: - var line2 = L.linenumber - L.LineNumber = line - lexMessagePos(L, errClosingQuoteExpected, L.lineStart) - L.LineNumber = line2 - break - of '\\': - # we allow an empty \ for line concatenation, but we don't require it - # for line concatenation - L.bufpos = pos - escape(L, tok, allowEmpty=true) - pos = L.bufpos - else: - add(tok.s, buf[pos]) - inc(pos) - L.bufpos = pos - tok.xkind = pxStrLit - -proc getSymbol(L: var TLexer, tok: var TToken) = - var pos = L.bufpos - var buf = L.buf - while true: - var c = buf[pos] - if c notin SymChars: break - add(tok.s, c) - inc(pos) - L.bufpos = pos - tok.xkind = pxSymbol - -proc scanLineComment(L: var TLexer, tok: var TToken) = - var pos = L.bufpos - var buf = L.buf - # a comment ends if the next line does not start with the // on the same - # column after only whitespace - tok.xkind = pxLineComment - var col = getColNumber(L, pos) - while true: - inc(pos, 2) # skip // - add(tok.s, '#') - while not (buf[pos] in {CR, LF, nimlexbase.EndOfFile}): - add(tok.s, buf[pos]) - inc(pos) - pos = handleCRLF(L, pos) - buf = L.buf - var indent = 0 - while buf[pos] == ' ': - inc(pos) - inc(indent) - if (col == indent) and (buf[pos] == '/') and (buf[pos + 1] == '/'): - add(tok.s, "\n") - else: - break - L.bufpos = pos - -proc scanStarComment(L: var TLexer, tok: var TToken) = - var pos = L.bufpos - var buf = L.buf - tok.s = "#" - tok.xkind = pxStarComment - while true: - case buf[pos] - of CR, LF: - pos = handleCRLF(L, pos) - buf = L.buf - add(tok.s, "\n#") - # skip annoying stars as line prefix: (eg. - # /* - # * ugly comment <-- this star - # */ - while buf[pos] in {' ', '\t'}: - add(tok.s, ' ') - inc(pos) - if buf[pos] == '*' and buf[pos+1] != '/': inc(pos) - of '*': - inc(pos) - if buf[pos] == '/': - inc(pos) - break - else: - add(tok.s, '*') - of nimlexbase.EndOfFile: - lexMessage(L, errTokenExpected, "*/") - else: - add(tok.s, buf[pos]) - inc(pos) - L.bufpos = pos - -proc skip(L: var TLexer, tok: var TToken) = - var pos = L.bufpos - var buf = L.buf - while true: - case buf[pos] - of '\\': - # Ignore \ line continuation characters when not inDirective - inc(pos) - if L.inDirective: - while buf[pos] in {' ', '\t'}: inc(pos) - if buf[pos] in {CR, LF}: - pos = handleCRLF(L, pos) - buf = L.buf - of ' ', Tabulator: - inc(pos) # newline is special: - of CR, LF: - pos = handleCRLF(L, pos) - buf = L.buf - if L.inDirective: - tok.xkind = pxNewLine - L.inDirective = false - else: - break # EndOfFile also leaves the loop - L.bufpos = pos - -proc getDirective(L: var TLexer, tok: var TToken) = - var pos = L.bufpos + 1 - var buf = L.buf - while buf[pos] in {' ', '\t'}: inc(pos) - while buf[pos] in SymChars: - add(tok.s, buf[pos]) - inc(pos) - # a HACK: we need to distinguish - # #define x (...) - # from: - # #define x(...) - # - L.bufpos = pos - # look ahead: - while buf[pos] in {' ', '\t'}: inc(pos) - while buf[pos] in SymChars: inc(pos) - if buf[pos] == '(': tok.xkind = pxDirectiveParLe - else: tok.xkind = pxDirective - L.inDirective = true - -proc getTok(L: var TLexer, tok: var TToken) = - tok.xkind = pxInvalid - fillToken(tok) - skip(L, tok) - if tok.xkind == pxNewLine: return - var c = L.buf[L.bufpos] - if c in SymStartChars: - getSymbol(L, tok) - elif c == '0': - case L.buf[L.bufpos+1] - of 'x', 'X': getNumber16(L, tok) - of 'b', 'B': getNumber2(L, tok) - of '1'..'7': getNumber8(L, tok) - else: getNumber(L, tok) - elif c in {'1'..'9'} or (c == '.' and L.buf[L.bufpos+1] in {'0'..'9'}): - getNumber(L, tok) - else: - case c - of ';': - tok.xkind = pxSemicolon - inc(L.bufpos) - of '/': - if L.buf[L.bufpos + 1] == '/': - scanLineComment(L, tok) - elif L.buf[L.bufpos+1] == '*': - inc(L.bufpos, 2) - scanStarComment(L, tok) - elif L.buf[L.bufpos+1] == '=': - inc(L.bufpos, 2) - tok.xkind = pxSlashAsgn - else: - tok.xkind = pxSlash - inc(L.bufpos) - of ',': - tok.xkind = pxComma - inc(L.bufpos) - of '(': - inc(L.bufpos) - tok.xkind = pxParLe - of '*': - inc(L.bufpos) - if L.buf[L.bufpos] == '=': - inc(L.bufpos) - tok.xkind = pxStarAsgn - else: - tok.xkind = pxStar - of ')': - inc(L.bufpos) - tok.xkind = pxParRi - of '[': - inc(L.bufpos) - tok.xkind = pxBracketLe - of ']': - inc(L.bufpos) - tok.xkind = pxBracketRi - of '.': - inc(L.bufpos) - if L.buf[L.bufpos] == '.' and L.buf[L.bufpos+1] == '.': - tok.xkind = pxDotDotDot - inc(L.bufpos, 2) - else: - tok.xkind = pxDot - of '{': - inc(L.bufpos) - tok.xkind = pxCurlyLe - of '}': - inc(L.bufpos) - tok.xkind = pxCurlyRi - of '+': - inc(L.bufpos) - if L.buf[L.bufpos] == '=': - tok.xkind = pxPlusAsgn - inc(L.bufpos) - elif L.buf[L.bufpos] == '+': - tok.xkind = pxPlusPlus - inc(L.bufpos) - else: - tok.xkind = pxPlus - of '-': - inc(L.bufpos) - case L.buf[L.bufpos] - of '>': - tok.xkind = pxArrow - inc(L.bufpos) - of '=': - tok.xkind = pxMinusAsgn - inc(L.bufpos) - of '-': - tok.xkind = pxMinusMinus - inc(L.bufpos) - else: - tok.xkind = pxMinus - of '?': - inc(L.bufpos) - tok.xkind = pxConditional - of ':': - inc(L.bufpos) - if L.buf[L.bufpos] == ':': - tok.xkind = pxScope - inc(L.bufpos) - else: - tok.xkind = pxColon - of '!': - inc(L.bufpos) - if L.buf[L.bufpos] == '=': - tok.xkind = pxNeq - inc(L.bufpos) - else: - tok.xkind = pxNot - of '<': - inc(L.bufpos) - if L.buf[L.bufpos] == '=': - inc(L.bufpos) - tok.xkind = pxLe - elif L.buf[L.bufpos] == '<': - inc(L.bufpos) - if L.buf[L.bufpos] == '=': - inc(L.bufpos) - tok.xkind = pxShlAsgn - else: - tok.xkind = pxShl - else: - tok.xkind = pxLt - of '>': - inc(L.bufpos) - if L.buf[L.bufpos] == '=': - inc(L.bufpos) - tok.xkind = pxGe - elif L.buf[L.bufpos] == '>': - inc(L.bufpos) - if L.buf[L.bufpos] == '=': - inc(L.bufpos) - tok.xkind = pxShrAsgn - else: - tok.xkind = pxShr - else: - tok.xkind = pxGt - of '=': - inc(L.bufpos) - if L.buf[L.bufpos] == '=': - tok.xkind = pxEquals - inc(L.bufpos) - else: - tok.xkind = pxAsgn - of '&': - inc(L.bufpos) - if L.buf[L.bufpos] == '=': - tok.xkind = pxAmpAsgn - inc(L.bufpos) - elif L.buf[L.bufpos] == '&': - inc(L.bufpos) - if L.buf[L.bufpos] == '=': - inc(L.bufpos) - tok.xkind = pxAmpAmpAsgn - else: - tok.xkind = pxAmpAmp - else: - tok.xkind = pxAmp - of '|': - inc(L.bufpos) - if L.buf[L.bufpos] == '=': - tok.xkind = pxBarAsgn - inc(L.bufpos) - elif L.buf[L.bufpos] == '|': - inc(L.bufpos) - if L.buf[L.bufpos] == '=': - inc(L.bufpos) - tok.xkind = pxBarBarAsgn - else: - tok.xkind = pxBarBar - else: - tok.xkind = pxBar - of '^': - inc(L.bufpos) - if L.buf[L.bufpos] == '=': - tok.xkind = pxHatAsgn - inc(L.bufpos) - else: - tok.xkind = pxHat - of '%': - inc(L.bufpos) - if L.buf[L.bufpos] == '=': - tok.xkind = pxModAsgn - inc(L.bufpos) - else: - tok.xkind = pxMod - of '~': - inc(L.bufpos) - if L.buf[L.bufpos] == '=': - tok.xkind = pxTildeAsgn - inc(L.bufpos) - else: - tok.xkind = pxTilde - of '#': - if L.buf[L.bufpos+1] == '#': - inc(L.bufpos, 2) - tok.xkind = pxDirConc - else: - getDirective(L, tok) - of '"': getString(L, tok) - of '\'': getCharLit(L, tok) - of nimlexbase.EndOfFile: - tok.xkind = pxEof - else: - tok.s = $c - tok.xkind = pxInvalid - lexMessage(L, errInvalidToken, c & " (\\" & $(ord(c)) & ')') - inc(L.bufpos) diff --git a/compiler/c2nim/cparse.nim b/compiler/c2nim/cparse.nim deleted file mode 100644 index 2e31af5285..0000000000 --- a/compiler/c2nim/cparse.nim +++ /dev/null @@ -1,2272 +0,0 @@ -# -# -# c2nim - C to Nimrod source converter -# (c) Copyright 2013 Andreas Rumpf -# -# See the file "copying.txt", included in this -# distribution, for details about the copyright. -# - -## This module implements an Ansi C parser. -## It translates a C source file into a Nimrod AST. Then the renderer can be -## used to convert the AST to its text representation. - -# TODO -# - document 'cpp' mode -# - implement handling of '::': function declarations -# - C++'s "operator" still needs some love -# - support '#if' in classes - -import - os, llstream, renderer, clex, idents, strutils, pegs, ast, astalgo, msgs, - options, strtabs, hashes, algorithm - -type - TParserFlag = enum - pfRefs, ## use "ref" instead of "ptr" for C's typ* - pfCDecl, ## annotate procs with cdecl - pfStdCall, ## annotate procs with stdcall - pfSkipInclude, ## skip all ``#include`` - pfTypePrefixes, ## all generated types start with 'T' or 'P' - pfSkipComments, ## do not generate comments - pfCpp, ## process C++ - pfIgnoreRValueRefs, ## transform C++'s 'T&&' to 'T' - pfKeepBodies ## do not skip C++ method bodies - - TMacro = object - name: string - params: int # number of parameters - body: seq[ref TToken] # can contain pxMacroParam tokens - - TParserOptions = object - flags: set[TParserFlag] - prefixes, suffixes: seq[string] - mangleRules: seq[tuple[pattern: TPeg, frmt: string]] - privateRules: seq[TPeg] - dynlibSym, header: string - macros: seq[TMacro] - toMangle: PStringTable - classes: PStringTable - PParserOptions* = ref TParserOptions - - TParser* = object - lex: TLexer - tok: ref TToken # current token - options: PParserOptions - backtrack: seq[ref TToken] - inTypeDef: int - scopeCounter: int - hasDeadCodeElimPragma: bool - currentClass: PNode # type that needs to be added as 'this' parameter - - TReplaceTuple* = array[0..1, string] - - ERetryParsing = object of ESynch - - - -proc addTypeDef(section, name, t: PNode) -proc parseStruct(p: var TParser, stmtList: PNode, isUnion: bool): PNode -proc parseStructBody(p: var TParser, stmtList: PNode, isUnion: bool, - kind: TNodeKind = nkRecList): PNode - - - -proc newParserOptions*(): PParserOptions = - new(result) - result.prefixes = @[] - result.suffixes = @[] - result.macros = @[] - result.mangleRules = @[] - result.privateRules = @[] - result.flags = {} - result.dynlibSym = "" - result.header = "" - result.toMangle = newStringTable(modeCaseSensitive) - result.classes = newStringTable(modeCaseSensitive) - -proc setOption*(parserOptions: PParserOptions, key: string, val=""): bool = - result = true - case key.normalize - of "ref": incl(parserOptions.flags, pfRefs) - of "dynlib": parserOptions.dynlibSym = val - of "header": parserOptions.header = val - of "cdecl": incl(parserOptions.flags, pfCdecl) - of "stdcall": incl(parserOptions.flags, pfStdCall) - of "prefix": parserOptions.prefixes.add(val) - of "suffix": parserOptions.suffixes.add(val) - of "skipinclude": incl(parserOptions.flags, pfSkipInclude) - of "typeprefixes": incl(parserOptions.flags, pfTypePrefixes) - of "skipcomments": incl(parserOptions.flags, pfSkipComments) - of "cpp": incl(parserOptions.flags, pfCpp) - of "keepbodies": incl(parserOptions.flags, pfKeepBodies) - of "ignorervaluerefs": incl(parserOptions.flags, pfIgnoreRValueRefs) - of "class": parserOptions.classes[val] = "true" - else: result = false - -proc parseUnit*(p: var TParser): PNode -proc openParser*(p: var TParser, filename: string, inputStream: PLLStream, - options = newParserOptions()) -proc closeParser*(p: var TParser) - -# implementation - -proc openParser(p: var TParser, filename: string, - inputStream: PLLStream, options = newParserOptions()) = - openLexer(p.lex, filename, inputStream) - p.options = options - p.backtrack = @[] - new(p.tok) - -proc parMessage(p: TParser, msg: TMsgKind, arg = "") = - #assert false - lexMessage(p.lex, msg, arg) - -proc closeParser(p: var TParser) = closeLexer(p.lex) -proc saveContext(p: var TParser) = p.backtrack.add(p.tok) -proc closeContext(p: var TParser) = discard p.backtrack.pop() -proc backtrackContext(p: var TParser) = p.tok = p.backtrack.pop() - -proc rawGetTok(p: var TParser) = - if p.tok.next != nil: - p.tok = p.tok.next - elif p.backtrack.len == 0: - p.tok.next = nil - getTok(p.lex, p.tok[]) - else: - # We need the next token and must be able to backtrack. So we need to - # allocate a new token. - var t: ref TToken - new(t) - getTok(p.lex, t[]) - p.tok.next = t - p.tok = t - -proc insertAngleRi(currentToken: ref TToken) = - var t: ref TToken - new(t) - t.xkind = pxAngleRi - t.next = currentToken.next - currentToken.next = t - -proc findMacro(p: TParser): int = - for i in 0..high(p.options.macros): - if p.tok.s == p.options.macros[i].name: return i - return -1 - -proc rawEat(p: var TParser, xkind: TTokKind) = - if p.tok.xkind == xkind: rawGetTok(p) - else: parMessage(p, errTokenExpected, tokKindToStr(xkind)) - -proc parseMacroArguments(p: var TParser): seq[seq[ref TToken]] = - result = @[] - result.add(@[]) - var i: array[pxParLe..pxCurlyLe, int] - var L = 0 - saveContext(p) - while true: - var kind = p.tok.xkind - case kind - of pxEof: rawEat(p, pxParRi) - of pxParLe, pxBracketLe, pxCurlyLe: - inc(i[kind]) - result[L].add(p.tok) - of pxParRi: - # end of arguments? - if i[pxParLe] == 0 and i[pxBracketLe] == 0 and i[pxCurlyLe] == 0: break - if i[pxParLe] > 0: dec(i[pxParLe]) - result[L].add(p.tok) - of pxBracketRi, pxCurlyRi: - kind = pred(kind, 3) - if i[kind] > 0: dec(i[kind]) - result[L].add(p.tok) - of pxComma: - if i[pxParLe] == 0 and i[pxBracketLe] == 0 and i[pxCurlyLe] == 0: - # next argument: comma is not part of the argument - result.add(@[]) - inc(L) - else: - # comma does not separate different arguments: - result[L].add(p.tok) - else: - result[L].add(p.tok) - rawGetTok(p) - closeContext(p) - -proc expandMacro(p: var TParser, m: TMacro) = - rawGetTok(p) # skip macro name - var arguments: seq[seq[ref TToken]] - if m.params > 0: - rawEat(p, pxParLe) - arguments = parseMacroArguments(p) - if arguments.len != m.params: parMessage(p, errWrongNumberOfArguments) - rawEat(p, pxParRi) - # insert into the token list: - if m.body.len > 0: - var newList: ref TToken - new(newList) - var lastTok = newList - for tok in items(m.body): - if tok.xkind == pxMacroParam: - for t in items(arguments[int(tok.iNumber)]): - #echo "t: ", t^ - lastTok.next = t - lastTok = t - else: - #echo "tok: ", tok^ - lastTok.next = tok - lastTok = tok - lastTok.next = p.tok - p.tok = newList.next - -proc getTok(p: var TParser) = - rawGetTok(p) - if p.tok.xkind == pxSymbol: - var idx = findMacro(p) - if idx >= 0: - expandMacro(p, p.options.macros[idx]) - -proc parLineInfo(p: TParser): TLineInfo = - result = getLineInfo(p.lex) - -proc skipComAux(p: var TParser, n: PNode) = - if n != nil and n.kind != nkEmpty: - if pfSkipComments notin p.options.flags: - if n.comment == nil: n.comment = p.tok.s - else: add(n.comment, "\n" & p.tok.s) - else: - parMessage(p, warnCommentXIgnored, p.tok.s) - getTok(p) - -proc skipCom(p: var TParser, n: PNode) = - while p.tok.xkind in {pxLineComment, pxStarComment}: skipComAux(p, n) - -proc skipStarCom(p: var TParser, n: PNode) = - while p.tok.xkind == pxStarComment: skipComAux(p, n) - -proc getTok(p: var TParser, n: PNode) = - getTok(p) - skipCom(p, n) - -proc expectIdent(p: TParser) = - if p.tok.xkind != pxSymbol: parMessage(p, errIdentifierExpected, $(p.tok[])) - -proc eat(p: var TParser, xkind: TTokKind, n: PNode) = - if p.tok.xkind == xkind: getTok(p, n) - else: parMessage(p, errTokenExpected, tokKindToStr(xkind)) - -proc eat(p: var TParser, xkind: TTokKind) = - if p.tok.xkind == xkind: getTok(p) - else: parMessage(p, errTokenExpected, tokKindToStr(xkind)) - -proc eat(p: var TParser, tok: string, n: PNode) = - if p.tok.s == tok: getTok(p, n) - else: parMessage(p, errTokenExpected, tok) - -proc opt(p: var TParser, xkind: TTokKind, n: PNode) = - if p.tok.xkind == xkind: getTok(p, n) - -proc addSon(father, a, b: PNode) = - addSon(father, a) - addSon(father, b) - -proc addSon(father, a, b, c: PNode) = - addSon(father, a) - addSon(father, b) - addSon(father, c) - -proc newNodeP(kind: TNodeKind, p: TParser): PNode = - result = newNodeI(kind, getLineInfo(p.lex)) - -proc newIntNodeP(kind: TNodeKind, intVal: BiggestInt, p: TParser): PNode = - result = newNodeP(kind, p) - result.intVal = intVal - -proc newFloatNodeP(kind: TNodeKind, floatVal: BiggestFloat, - p: TParser): PNode = - result = newNodeP(kind, p) - result.floatVal = floatVal - -proc newStrNodeP(kind: TNodeKind, strVal: string, p: TParser): PNode = - result = newNodeP(kind, p) - result.strVal = strVal - -proc newIdentNodeP(ident: PIdent, p: TParser): PNode = - result = newNodeP(nkIdent, p) - result.ident = ident - -proc newIdentNodeP(ident: string, p: TParser): PNode = - result = newIdentNodeP(getIdent(ident), p) - -proc mangleRules(s: string, p: TParser): string = - block mangle: - for pattern, frmt in items(p.options.mangleRules): - if s.match(pattern): - result = s.replacef(pattern, frmt) - break mangle - block prefixes: - for prefix in items(p.options.prefixes): - if s.startsWith(prefix): - result = s.substr(prefix.len) - break prefixes - result = s - block suffixes: - for suffix in items(p.options.suffixes): - if result.endsWith(suffix): - setLen(result, result.len - suffix.len) - break suffixes - -proc mangleName(s: string, p: TParser): string = - if p.options.toMangle.hasKey(s): result = p.options.toMangle[s] - else: result = mangleRules(s, p) - -proc isPrivate(s: string, p: TParser): bool = - for pattern in items(p.options.privateRules): - if s.match(pattern): return true - -proc mangledIdent(ident: string, p: TParser): PNode = - result = newNodeP(nkIdent, p) - result.ident = getIdent(mangleName(ident, p)) - -proc newIdentPair(a, b: string, p: TParser): PNode = - result = newNodeP(nkExprColonExpr, p) - addSon(result, newIdentNodeP(a, p)) - addSon(result, newIdentNodeP(b, p)) - -proc newIdentStrLitPair(a, b: string, p: TParser): PNode = - result = newNodeP(nkExprColonExpr, p) - addSon(result, newIdentNodeP(a, p)) - addSon(result, newStrNodeP(nkStrLit, b, p)) - -proc addImportToPragma(pragmas: PNode, ident: string, p: TParser) = - addSon(pragmas, newIdentStrLitPair("importc", ident, p)) - if p.options.dynlibSym.len > 0: - addSon(pragmas, newIdentPair("dynlib", p.options.dynlibSym, p)) - else: - addSon(pragmas, newIdentStrLitPair("header", p.options.header, p)) - -proc exportSym(p: TParser, i: PNode, origName: string): PNode = - assert i.kind == nkIdent - if p.scopeCounter == 0 and not isPrivate(origName, p): - result = newNodeI(nkPostfix, i.info) - addSon(result, newIdentNode(getIdent("*"), i.info), i) - else: - result = i - -proc varIdent(ident: string, p: TParser): PNode = - result = exportSym(p, mangledIdent(ident, p), ident) - if p.scopeCounter > 0: return - if p.options.dynlibSym.len > 0 or p.options.header.len > 0: - var a = result - result = newNodeP(nkPragmaExpr, p) - var pragmas = newNodeP(nkPragma, p) - addSon(result, a) - addSon(result, pragmas) - addImportToPragma(pragmas, ident, p) - -proc fieldIdent(ident: string, p: TParser): PNode = - result = exportSym(p, mangledIdent(ident, p), ident) - if p.scopeCounter > 0: return - if p.options.header.len > 0: - var a = result - result = newNodeP(nkPragmaExpr, p) - var pragmas = newNodeP(nkPragma, p) - addSon(result, a) - addSon(result, pragmas) - addSon(pragmas, newIdentStrLitPair("importc", ident, p)) - -proc doImport(ident: string, pragmas: PNode, p: TParser) = - if p.options.dynlibSym.len > 0 or p.options.header.len > 0: - addImportToPragma(pragmas, ident, p) - -proc doImportCpp(ident: string, pragmas: PNode, p: TParser) = - if p.options.dynlibSym.len > 0 or p.options.header.len > 0: - addSon(pragmas, newIdentStrLitPair("importcpp", ident, p)) - if p.options.dynlibSym.len > 0: - addSon(pragmas, newIdentPair("dynlib", p.options.dynlibSym, p)) - else: - addSon(pragmas, newIdentStrLitPair("header", p.options.header, p)) - -proc newBinary(opr: string, a, b: PNode, p: TParser): PNode = - result = newNodeP(nkInfix, p) - addSon(result, newIdentNodeP(getIdent(opr), p)) - addSon(result, a) - addSon(result, b) - -proc skipIdent(p: var TParser): PNode = - expectIdent(p) - result = mangledIdent(p.tok.s, p) - getTok(p, result) - -proc skipIdentExport(p: var TParser): PNode = - expectIdent(p) - result = exportSym(p, mangledIdent(p.tok.s, p), p.tok.s) - getTok(p, result) - -proc skipTypeIdentExport(p: var TParser, prefix='T'): PNode = - expectIdent(p) - var n = prefix & mangleName(p.tok.s, p) - p.options.toMangle[p.tok.s] = n - var i = newNodeP(nkIdent, p) - i.ident = getIdent(n) - result = exportSym(p, i, p.tok.s) - getTok(p, result) - -proc markTypeIdent(p: var TParser, typ: PNode) = - if pfTypePrefixes in p.options.flags: - var prefix = "" - if typ == nil or typ.kind == nkEmpty: - prefix = "T" - else: - var t = typ - while t != nil and t.kind in {nkVarTy, nkPtrTy, nkRefTy}: - prefix.add('P') - t = t.sons[0] - if prefix.len == 0: prefix.add('T') - expectIdent(p) - p.options.toMangle[p.tok.s] = prefix & mangleRules(p.tok.s, p) - -# --------------- parser ----------------------------------------------------- -# We use this parsing rule: If it looks like a declaration, it is one. This -# avoids to build a symbol table, which can't be done reliably anyway for our -# purposes. - -proc expression(p: var TParser, rbp: int = 0): PNode -proc constantExpression(p: var TParser): PNode = expression(p, 40) -proc assignmentExpression(p: var TParser): PNode = expression(p, 30) -proc compoundStatement(p: var TParser): PNode -proc statement(p: var TParser): PNode - -proc declKeyword(p: TParser, s: string): bool = - # returns true if it is a keyword that introduces a declaration - case s - of "extern", "static", "auto", "register", "const", "volatile", "restrict", - "inline", "__inline", "__cdecl", "__stdcall", "__syscall", "__fastcall", - "__safecall", "void", "struct", "union", "enum", "typedef", - "short", "int", "long", "float", "double", "signed", "unsigned", "char": - result = true - of "class": - result = p.options.flags.contains(pfCpp) - -proc stmtKeyword(s: string): bool = - case s - of "if", "for", "while", "do", "switch", "break", "continue", "return", - "goto": - result = true - -# ------------------- type desc ----------------------------------------------- - -proc isIntType(s: string): bool = - case s - of "short", "int", "long", "float", "double", "signed", "unsigned": - result = true - -proc skipConst(p: var TParser) = - while p.tok.xkind == pxSymbol and - (p.tok.s == "const" or p.tok.s == "volatile" or p.tok.s == "restrict"): - getTok(p, nil) - -proc isTemplateAngleBracket(p: var TParser): bool = - if pfCpp notin p.options.flags: return false - saveContext(p) - getTok(p, nil) # skip "<" - var i: array[pxParLe..pxCurlyLe, int] - var angles = 0 - while true: - let kind = p.tok.xkind - case kind - of pxEof: break - of pxParLe, pxBracketLe, pxCurlyLe: inc(i[kind]) - of pxGt, pxAngleRi: - # end of arguments? - if i[pxParLe] == 0 and i[pxBracketLe] == 0 and i[pxCurlyLe] == 0 and - angles == 0: - # mark as end token: - p.tok.xkind = pxAngleRi - result = true; - break - if angles > 0: dec(angles) - of pxShr: - # >> can end a template too: - if i[pxParLe] == 0 and i[pxBracketLe] == 0 and i[pxCurlyLe] == 0 and - angles == 1: - p.tok.xkind = pxAngleRi - insertAngleRi(p.tok) - result = true - break - if angles > 1: dec(angles, 2) - of pxLt: inc(angles) - of pxParRi, pxBracketRi, pxCurlyRi: - let kind = pred(kind, 3) - if i[kind] > 0: dec(i[kind]) - else: break - of pxSemicolon: break - else: discard - getTok(p, nil) - backtrackContext(p) - -proc optAngle(p: var TParser, n: PNode): PNode = - if p.tok.xkind == pxLt and isTemplateAngleBracket(p): - getTok(p) - result = newNodeP(nkBracketExpr, p) - result.add(n) - while true: - let a = assignmentExpression(p) - if not a.isNil: result.add(a) - if p.tok.xkind != pxComma: break - getTok(p) - eat(p, pxAngleRi) - else: - result = n - -proc optScope(p: var TParser, n: PNode): PNode = - result = n - if pfCpp in p.options.flags: - while p.tok.xkind == pxScope: - let a = result - result = newNodeP(nkDotExpr, p) - result.add(a) - getTok(p, result) - expectIdent(p) - result.add(mangledIdent(p.tok.s, p)) - getTok(p, result) - -proc typeAtom(p: var TParser): PNode = - skipConst(p) - expectIdent(p) - case p.tok.s - of "void": - result = newNodeP(nkNilLit, p) # little hack - getTok(p, nil) - of "struct", "union", "enum": - getTok(p, nil) - result = skipIdent(p) - elif isIntType(p.tok.s): - var x = "" - #getTok(p, nil) - var isUnsigned = false - while p.tok.xkind == pxSymbol and (isIntType(p.tok.s) or p.tok.s == "char"): - if p.tok.s == "unsigned": - isUnsigned = true - elif p.tok.s == "signed" or p.tok.s == "int": - discard - else: - add(x, p.tok.s) - getTok(p, nil) - if x.len == 0: x = "int" - let xx = if isUnsigned: "cu" & x else: "c" & x - result = mangledIdent(xx, p) - else: - result = mangledIdent(p.tok.s, p) - getTok(p, result) - result = optScope(p, result) - result = optAngle(p, result) - -proc newPointerTy(p: TParser, typ: PNode): PNode = - if pfRefs in p.options.flags: - result = newNodeP(nkRefTy, p) - else: - result = newNodeP(nkPtrTy, p) - result.addSon(typ) - -proc pointer(p: var TParser, a: PNode): PNode = - result = a - var i = 0 - skipConst(p) - while true: - if p.tok.xkind == pxStar: - inc(i) - getTok(p, result) - skipConst(p) - result = newPointerTy(p, result) - elif p.tok.xkind == pxAmp and pfCpp in p.options.flags: - getTok(p, result) - skipConst(p) - let b = result - result = newNodeP(nkVarTy, p) - result.add(b) - elif p.tok.xkind == pxAmpAmp and pfCpp in p.options.flags: - getTok(p, result) - skipConst(p) - if pfIgnoreRvalueRefs notin p.options.flags: - let b = result - result = newNodeP(nkVarTy, p) - result.add(b) - else: break - if a.kind == nkIdent and a.ident.s == "char": - if i >= 2: - result = newIdentNodeP("cstringArray", p) - for j in 1..i-2: result = newPointerTy(p, result) - elif i == 1: result = newIdentNodeP("cstring", p) - elif a.kind == nkNilLit and i > 0: - result = newIdentNodeP("pointer", p) - for j in 1..i-1: result = newPointerTy(p, result) - -proc newProcPragmas(p: TParser): PNode = - result = newNodeP(nkPragma, p) - if pfCDecl in p.options.flags: - addSon(result, newIdentNodeP("cdecl", p)) - elif pfStdCall in p.options.flags: - addSon(result, newIdentNodeP("stdcall", p)) - -proc addPragmas(father, pragmas: PNode) = - if sonsLen(pragmas) > 0: addSon(father, pragmas) - else: addSon(father, ast.emptyNode) - -proc addReturnType(params, rettyp: PNode) = - if rettyp == nil: addSon(params, ast.emptyNode) - elif rettyp.kind != nkNilLit: addSon(params, rettyp) - else: addSon(params, ast.emptyNode) - -proc parseFormalParams(p: var TParser, params, pragmas: PNode) - -proc parseTypeSuffix(p: var TParser, typ: PNode): PNode = - result = typ - while true: - case p.tok.xkind - of pxBracketLe: - getTok(p, result) - skipConst(p) # POSIX contains: ``int [restrict]`` - if p.tok.xkind != pxBracketRi: - var tmp = result - var index = expression(p) - # array type: - result = newNodeP(nkBracketExpr, p) - addSon(result, newIdentNodeP("array", p)) - #var r = newNodeP(nkRange, p) - #addSon(r, newIntNodeP(nkIntLit, 0, p)) - #addSon(r, newBinary("-", index, newIntNodeP(nkIntLit, 1, p), p)) - #addSon(result, r) - addSon(result, index) - addSon(result, tmp) - else: - # pointer type: - var tmp = result - if pfRefs in p.options.flags: - result = newNodeP(nkRefTy, p) - else: - result = newNodeP(nkPtrTy, p) - result.addSon(tmp) - eat(p, pxBracketRi, result) - of pxParLe: - # function pointer: - var procType = newNodeP(nkProcTy, p) - var pragmas = newProcPragmas(p) - var params = newNodeP(nkFormalParams, p) - addReturnType(params, result) - parseFormalParams(p, params, pragmas) - addSon(procType, params) - addPragmas(procType, pragmas) - result = procType - else: break - -proc typeDesc(p: var TParser): PNode = - result = pointer(p, typeAtom(p)) - -proc abstractDeclarator(p: var TParser, a: PNode): PNode - -proc directAbstractDeclarator(p: var TParser, a: PNode): PNode = - if p.tok.xkind == pxParLe: - getTok(p, a) - if p.tok.xkind in {pxStar, pxAmp, pxAmpAmp}: - result = abstractDeclarator(p, a) - eat(p, pxParRi, result) - return parseTypeSuffix(p, a) - -proc abstractDeclarator(p: var TParser, a: PNode): PNode = - return directAbstractDeclarator(p, pointer(p, a)) - -proc typeName(p: var TParser): PNode = - return abstractDeclarator(p, typeAtom(p)) - -proc parseField(p: var TParser, kind: TNodeKind): PNode = - if p.tok.xkind == pxParLe: - getTok(p, nil) - while p.tok.xkind == pxStar: getTok(p, nil) - result = parseField(p, kind) - eat(p, pxParRi, result) - else: - expectIdent(p) - if kind == nkRecList: result = fieldIdent(p.tok.s, p) - else: result = mangledIdent(p.tok.s, p) - getTok(p, result) - -proc structPragmas(p: TParser, name: PNode, origName: string): PNode = - assert name.kind == nkIdent - result = newNodeP(nkPragmaExpr, p) - addSon(result, exportSym(p, name, origName)) - var pragmas = newNodeP(nkPragma, p) - #addSon(pragmas, newIdentNodeP("pure", p), newIdentNodeP("final", p)) - if p.options.header.len > 0: - addSon(pragmas, newIdentStrLitPair("importc", origName, p), - newIdentStrLitPair("header", p.options.header, p)) - if pragmas.len > 0: addSon(result, pragmas) - else: addSon(result, ast.emptyNode) - -proc hashPosition(p: TParser): string = - let lineInfo = parLineInfo(p) - let fileInfo = fileInfos[lineInfo.fileIndex] - result = $hash(fileInfo.shortName & "_" & $lineInfo.line & "_" & $lineInfo.col).uint - -proc parseInnerStruct(p: var TParser, stmtList: PNode, isUnion: bool): PNode = - getTok(p, nil) - if p.tok.xkind != pxCurlyLe: - parMessage(p, errUser, "Expected '{' but found '" & $(p.tok[]) & "'") - - let structName = if isUnion: "INNER_C_UNION_" & p.hashPosition - else: "INNER_C_STRUCT_" & p.hashPosition - let typeSection = newNodeP(nkTypeSection, p) - let newStruct = newNodeP(nkObjectTy, p) - var pragmas = ast.emptyNode - if isUnion: - pragmas = newNodeP(nkPragma, p) - addSon(pragmas, newIdentNodeP("union", p)) - addSon(newStruct, pragmas, ast.emptyNode) # no inheritance - result = newNodeP(nkIdent, p) - result.ident = getIdent(structName) - let struct = parseStructBody(p, stmtList, isUnion) - let defName = newNodeP(nkIdent, p) - defName.ident = getIdent(structName) - addSon(newStruct, struct) - addTypeDef(typeSection, structPragmas(p, defName, "no_name"), newStruct) - addSon(stmtList, typeSection) - -proc parseStructBody(p: var TParser, stmtList: PNode, isUnion: bool, - kind: TNodeKind = nkRecList): PNode = - result = newNodeP(kind, p) - eat(p, pxCurlyLe, result) - while p.tok.xkind notin {pxEof, pxCurlyRi}: - skipConst(p) - var baseTyp: PNode - if p.tok.xkind == pxSymbol and (p.tok.s == "struct" or p.tok.s == "union"): - let gotUnion = if p.tok.s == "union": true else: false - saveContext(p) - getTok(p, nil) - if p.tok.xkind == pxSymbol: - backtrackContext(p) - baseTyp = typeAtom(p) - else: - backtrackContext(p) - baseTyp = parseInnerStruct(p, stmtList, gotUnion) - if p.tok.xkind == pxSemiColon: - let def = newNodeP(nkIdentDefs, p) - var t = pointer(p, baseTyp) - let i = fieldIdent("ano_" & p.hashPosition, p) - t = parseTypeSuffix(p, t) - addSon(def, i, t, ast.emptyNode) - addSon(result, def) - getTok(p, nil) - continue - else: - baseTyp = typeAtom(p) - - while true: - var def = newNodeP(nkIdentDefs, p) - var t = pointer(p, baseTyp) - var i = parseField(p, kind) - t = parseTypeSuffix(p, t) - addSon(def, i, t, ast.emptyNode) - addSon(result, def) - if p.tok.xkind != pxComma: break - getTok(p, def) - eat(p, pxSemicolon, lastSon(result)) - eat(p, pxCurlyRi, result) - -proc enumPragmas(p: TParser, name: PNode): PNode = - result = newNodeP(nkPragmaExpr, p) - addSon(result, name) - var pragmas = newNodeP(nkPragma, p) - var e = newNodeP(nkExprColonExpr, p) - # HACK: sizeof(cint) should be constructed as AST - addSon(e, newIdentNodeP("size", p), newIdentNodeP("sizeof(cint)", p)) - addSon(pragmas, e) - addSon(result, pragmas) - -proc parseStruct(p: var TParser, stmtList: PNode, isUnion: bool): PNode = - result = newNodeP(nkObjectTy, p) - var pragmas = ast.emptyNode - if isUnion: - pragmas = newNodeP(nkPragma, p) - addSon(pragmas, newIdentNodeP("union", p)) - addSon(result, pragmas, ast.emptyNode) # no inheritance - if p.tok.xkind == pxCurlyLe: - addSon(result, parseStructBody(p, stmtList, isUnion)) - else: - addSon(result, newNodeP(nkRecList, p)) - -proc declarator(p: var TParser, a: PNode, ident: ptr PNode): PNode - -proc directDeclarator(p: var TParser, a: PNode, ident: ptr PNode): PNode = - case p.tok.xkind - of pxSymbol: - ident[] = skipIdent(p) - of pxParLe: - getTok(p, a) - if p.tok.xkind in {pxStar, pxAmp, pxAmpAmp, pxSymbol}: - result = declarator(p, a, ident) - eat(p, pxParRi, result) - else: - discard - return parseTypeSuffix(p, a) - -proc declarator(p: var TParser, a: PNode, ident: ptr PNode): PNode = - return directDeclarator(p, pointer(p, a), ident) - -# parameter-declaration -# declaration-specifiers declarator -# declaration-specifiers asbtract-declarator(opt) -proc parseParam(p: var TParser, params: PNode) = - var typ = typeDesc(p) - # support for ``(void)`` parameter list: - if typ.kind == nkNilLit and p.tok.xkind == pxParRi: return - var name: PNode - typ = declarator(p, typ, addr name) - if name == nil: - var idx = sonsLen(params)+1 - name = newIdentNodeP("a" & $idx, p) - var x = newNodeP(nkIdentDefs, p) - addSon(x, name, typ) - if p.tok.xkind == pxAsgn: - # we support default parameters for C++: - getTok(p, x) - addSon(x, assignmentExpression(p)) - else: - addSon(x, ast.emptyNode) - addSon(params, x) - -proc parseFormalParams(p: var TParser, params, pragmas: PNode) = - eat(p, pxParLe, params) - while p.tok.xkind notin {pxEof, pxParRi}: - if p.tok.xkind == pxDotDotDot: - addSon(pragmas, newIdentNodeP("varargs", p)) - getTok(p, pragmas) - break - parseParam(p, params) - if p.tok.xkind != pxComma: break - getTok(p, params) - eat(p, pxParRi, params) - -proc parseCallConv(p: var TParser, pragmas: PNode) = - while p.tok.xkind == pxSymbol: - case p.tok.s - of "inline", "__inline": addSon(pragmas, newIdentNodeP("inline", p)) - of "__cdecl": addSon(pragmas, newIdentNodeP("cdecl", p)) - of "__stdcall": addSon(pragmas, newIdentNodeP("stdcall", p)) - of "__syscall": addSon(pragmas, newIdentNodeP("syscall", p)) - of "__fastcall": addSon(pragmas, newIdentNodeP("fastcall", p)) - of "__safecall": addSon(pragmas, newIdentNodeP("safecall", p)) - else: break - getTok(p, nil) - -proc parseFunctionPointerDecl(p: var TParser, rettyp: PNode): PNode = - var procType = newNodeP(nkProcTy, p) - var pragmas = newProcPragmas(p) - var params = newNodeP(nkFormalParams, p) - eat(p, pxParLe, params) - addReturnType(params, rettyp) - parseCallConv(p, pragmas) - if p.tok.xkind == pxStar: getTok(p, params) - else: parMessage(p, errTokenExpected, "*") - if p.inTypeDef > 0: markTypeIdent(p, nil) - var name = skipIdentExport(p) - eat(p, pxParRi, name) - parseFormalParams(p, params, pragmas) - addSon(procType, params) - addPragmas(procType, pragmas) - - if p.inTypeDef == 0: - result = newNodeP(nkVarSection, p) - var def = newNodeP(nkIdentDefs, p) - addSon(def, name, procType, ast.emptyNode) - addSon(result, def) - else: - result = newNodeP(nkTypeDef, p) - addSon(result, name, ast.emptyNode, procType) - assert result != nil - -proc addTypeDef(section, name, t: PNode) = - var def = newNodeI(nkTypeDef, name.info) - addSon(def, name, ast.emptyNode, t) - addSon(section, def) - -proc otherTypeDef(p: var TParser, section, typ: PNode) = - var name: PNode - var t = typ - if p.tok.xkind in {pxStar, pxAmp, pxAmpAmp}: - t = pointer(p, t) - if p.tok.xkind == pxParLe: - # function pointer: typedef typ (*name)(); - var x = parseFunctionPointerDecl(p, t) - name = x[0] - t = x[2] - else: - # typedef typ name; - markTypeIdent(p, t) - name = skipIdentExport(p) - t = parseTypeSuffix(p, t) - addTypeDef(section, name, t) - -proc parseTrailingDefinedTypes(p: var TParser, section, typ: PNode) = - while p.tok.xkind == pxComma: - getTok(p, nil) - var newTyp = pointer(p, typ) - markTypeIdent(p, newTyp) - var newName = skipIdentExport(p) - newTyp = parseTypeSuffix(p, newTyp) - addTypeDef(section, newName, newTyp) - -proc createConst(name, typ, val: PNode, p: TParser): PNode = - result = newNodeP(nkConstDef, p) - addSon(result, name, typ, val) - -proc exprToNumber(n: PNode not nil): tuple[succ: bool, val: BiggestInt] = - result = (false, 0.BiggestInt) - case n.kind: - of nkPrefix: - # Check for negative/positive numbers -3 or +6 - if n.sons.len == 2 and n.sons[0].kind == nkIdent and n.sons[1].kind == nkIntLit: - let pre = n.sons[0] - let num = n.sons[1] - if pre.ident.s == "-": result = (true, - num.intVal) - elif pre.ident.s == "+": result = (true, num.intVal) - else: discard - -proc enumFields(p: var TParser, constList: PNode): PNode = - result = newNodeP(nkEnumTy, p) - addSon(result, ast.emptyNode) # enum does not inherit from anything - var i: BiggestInt = 0 - var field: tuple[id: BiggestInt, isNumber: bool, node: PNode] - var fields = newSeq[type(field)]() - while true: - var e = skipIdent(p) - if p.tok.xkind == pxAsgn: - getTok(p, e) - var c = constantExpression(p) - var a = e - e = newNodeP(nkEnumFieldDef, p) - addSon(e, a, c) - skipCom(p, e) - if c.kind == nkIntLit: - i = c.intVal - field.isNumber = true - else: - var (success, number) = exprToNumber(c) - if success: - i = number - field.isNumber = true - else: - field.isNumber = false - else: - inc(i) - field.isNumber = true - field.id = i - field.node = e - fields.add(field) - if p.tok.xkind != pxComma: break - getTok(p, e) - # allow trailing comma: - if p.tok.xkind == pxCurlyRi: break - fields.sort do (x, y: type(field)) -> int: - cmp(x.id, y.id) - var lastId: BiggestInt - var lastIdent: PNode - for count, f in fields: - if not f.isNumber: - addSon(result, f.node) - elif f.id == lastId and count > 0: - var currentIdent: PNode - case f.node.kind: - of nkEnumFieldDef: - if f.node.sons.len > 0 and f.node.sons[0].kind == nkIdent: - currentIdent = f.node.sons[0] - else: parMessage(p, errGenerated, "Warning: When sorting enum fields an expected nkIdent was not found. Check the fields!") - of nkIdent: currentIdent = f.node - else: parMessage(p, errGenerated, "Warning: When sorting enum fields an expected nkIdent was not found. Check the fields!") - var constant = createConst( currentIdent, ast.emptyNode, lastIdent, p) - constList.addSon(constant) - else: - addSon(result, f.node) - lastId = f.id - case f.node.kind: - of nkEnumFieldDef: - if f.node.sons.len > 0 and f.node.sons[0].kind == nkIdent: - lastIdent = f.node.sons[0] - else: parMessage(p, errGenerated, "Warning: When sorting enum fields an expected nkIdent was not found. Check the fields!") - of nkIdent: lastIdent = f.node - else: parMessage(p, errGenerated, "Warning: When sorting enum fields an expected nkIdent was not found. Check the fields!") - -proc parseTypedefStruct(p: var TParser, result: PNode, stmtList: PNode, isUnion: bool) = - getTok(p, result) - if p.tok.xkind == pxCurlyLe: - var t = parseStruct(p, stmtList, isUnion) - var origName = p.tok.s - markTypeIdent(p, nil) - var name = skipIdent(p) - addTypeDef(result, structPragmas(p, name, origName), t) - parseTrailingDefinedTypes(p, result, name) - elif p.tok.xkind == pxSymbol: - # name to be defined or type "struct a", we don't know yet: - markTypeIdent(p, nil) - var origName = p.tok.s - var nameOrType = skipIdent(p) - case p.tok.xkind - of pxCurlyLe: - var t = parseStruct(p, stmtList, isUnion) - if p.tok.xkind == pxSymbol: - # typedef struct tagABC {} abc, *pabc; - # --> abc is a better type name than tagABC! - markTypeIdent(p, nil) - var origName = p.tok.s - var name = skipIdent(p) - addTypeDef(result, structPragmas(p, name, origName), t) - parseTrailingDefinedTypes(p, result, name) - else: - addTypeDef(result, structPragmas(p, nameOrType, origName), t) - of pxSymbol: - # typedef struct a a? - if mangleName(p.tok.s, p) == nameOrType.ident.s: - # ignore the declaration: - getTok(p, nil) - else: - # typedef struct a b; or typedef struct a b[45]; - otherTypeDef(p, result, nameOrType) - else: - otherTypeDef(p, result, nameOrType) - else: - expectIdent(p) - -proc parseTypedefEnum(p: var TParser, result, constSection: PNode) = - getTok(p, result) - if p.tok.xkind == pxCurlyLe: - getTok(p, result) - var t = enumFields(p, constSection) - eat(p, pxCurlyRi, t) - var origName = p.tok.s - markTypeIdent(p, nil) - var name = skipIdent(p) - addTypeDef(result, enumPragmas(p, exportSym(p, name, origName)), t) - parseTrailingDefinedTypes(p, result, name) - elif p.tok.xkind == pxSymbol: - # name to be defined or type "enum a", we don't know yet: - markTypeIdent(p, nil) - var origName = p.tok.s - var nameOrType = skipIdent(p) - case p.tok.xkind - of pxCurlyLe: - getTok(p, result) - var t = enumFields(p, constSection) - eat(p, pxCurlyRi, t) - if p.tok.xkind == pxSymbol: - # typedef enum tagABC {} abc, *pabc; - # --> abc is a better type name than tagABC! - markTypeIdent(p, nil) - var origName = p.tok.s - var name = skipIdent(p) - addTypeDef(result, enumPragmas(p, exportSym(p, name, origName)), t) - parseTrailingDefinedTypes(p, result, name) - else: - addTypeDef(result, - enumPragmas(p, exportSym(p, nameOrType, origName)), t) - of pxSymbol: - # typedef enum a a? - if mangleName(p.tok.s, p) == nameOrType.ident.s: - # ignore the declaration: - getTok(p, nil) - else: - # typedef enum a b; or typedef enum a b[45]; - otherTypeDef(p, result, nameOrType) - else: - otherTypeDef(p, result, nameOrType) - else: - expectIdent(p) - -proc parseTypeDef(p: var TParser): PNode = - result = newNodeP(nkStmtList, p) - var typeSection = newNodeP(nkTypeSection, p) - var afterStatements = newNodeP(nkStmtList, p) - while p.tok.xkind == pxSymbol and p.tok.s == "typedef": - getTok(p, typeSection) - inc(p.inTypeDef) - expectIdent(p) - case p.tok.s - of "struct": parseTypedefStruct(p, typeSection, result, isUnion=false) - of "union": parseTypedefStruct(p, typeSection, result, isUnion=true) - of "enum": - var constSection = newNodeP(nkConstSection, p) - parseTypedefEnum(p, typeSection, constSection) - addSon(afterStatements, constSection) - of "class": - if pfCpp in p.options.flags: - parseTypedefStruct(p, typeSection, result, isUnion=false) - else: - var t = typeAtom(p) - otherTypeDef(p, typeSection, t) - else: - var t = typeAtom(p) - otherTypeDef(p, typeSection, t) - eat(p, pxSemicolon) - dec(p.inTypeDef) - - addSon(result, typeSection) - for s in afterStatements: - addSon(result, s) - -proc skipDeclarationSpecifiers(p: var TParser) = - while p.tok.xkind == pxSymbol: - case p.tok.s - of "extern", "static", "auto", "register", "const", "volatile": - getTok(p, nil) - else: break - -proc parseInitializer(p: var TParser): PNode = - if p.tok.xkind == pxCurlyLe: - result = newNodeP(nkBracket, p) - getTok(p, result) - while p.tok.xkind notin {pxEof, pxCurlyRi}: - addSon(result, parseInitializer(p)) - opt(p, pxComma, nil) - eat(p, pxCurlyRi, result) - else: - result = assignmentExpression(p) - -proc addInitializer(p: var TParser, def: PNode) = - if p.tok.xkind == pxAsgn: - getTok(p, def) - addSon(def, parseInitializer(p)) - else: - addSon(def, ast.emptyNode) - -proc parseVarDecl(p: var TParser, baseTyp, typ: PNode, - origName: string): PNode = - result = newNodeP(nkVarSection, p) - var def = newNodeP(nkIdentDefs, p) - addSon(def, varIdent(origName, p)) - addSon(def, parseTypeSuffix(p, typ)) - addInitializer(p, def) - addSon(result, def) - - while p.tok.xkind == pxComma: - getTok(p, def) - var t = pointer(p, baseTyp) - expectIdent(p) - def = newNodeP(nkIdentDefs, p) - addSon(def, varIdent(p.tok.s, p)) - getTok(p, def) - addSon(def, parseTypeSuffix(p, t)) - addInitializer(p, def) - addSon(result, def) - eat(p, pxSemicolon) - -proc declarationName(p: var TParser): string = - expectIdent(p) - result = p.tok.s - getTok(p) # skip identifier - while p.tok.xkind == pxScope and pfCpp in p.options.flags: - getTok(p) # skip "::" - expectIdent(p) - result.add("::") - result.add(p.tok.s) - getTok(p) - -proc declaration(p: var TParser): PNode = - result = newNodeP(nkProcDef, p) - var pragmas = newNodeP(nkPragma, p) - - skipDeclarationSpecifiers(p) - parseCallConv(p, pragmas) - skipDeclarationSpecifiers(p) - expectIdent(p) - var baseTyp = typeAtom(p) - var rettyp = pointer(p, baseTyp) - skipDeclarationSpecifiers(p) - parseCallConv(p, pragmas) - skipDeclarationSpecifiers(p) - - if p.tok.xkind == pxParLe: - # Function pointer declaration: This is of course only a heuristic, but the - # best we can do here. - result = parseFunctionPointerDecl(p, rettyp) - eat(p, pxSemicolon) - return - var origName = declarationName(p) - case p.tok.xkind - of pxParLe: - # really a function! - var name = mangledIdent(origName, p) - var params = newNodeP(nkFormalParams, p) - addReturnType(params, rettyp) - parseFormalParams(p, params, pragmas) - if pfCpp in p.options.flags and p.tok.xkind == pxSymbol and - p.tok.s == "const": - addSon(pragmas, newIdentNodeP("noSideEffect", p)) - getTok(p) - if pfCDecl in p.options.flags: - addSon(pragmas, newIdentNodeP("cdecl", p)) - elif pfStdcall in p.options.flags: - addSon(pragmas, newIdentNodeP("stdcall", p)) - # no pattern, no exceptions: - addSon(result, exportSym(p, name, origName), ast.emptyNode, ast.emptyNode) - addSon(result, params, pragmas, ast.emptyNode) # no exceptions - case p.tok.xkind - of pxSemicolon: - getTok(p) - addSon(result, ast.emptyNode) # nobody - if p.scopeCounter == 0: doImport(origName, pragmas, p) - of pxCurlyLe: - addSon(result, compoundStatement(p)) - else: - parMessage(p, errTokenExpected, ";") - if sonsLen(result.sons[pragmasPos]) == 0: - result.sons[pragmasPos] = ast.emptyNode - else: - result = parseVarDecl(p, baseTyp, rettyp, origName) - assert result != nil - -proc enumSpecifier(p: var TParser): PNode = - saveContext(p) - getTok(p, nil) # skip "enum" - case p.tok.xkind - of pxCurlyLe: - closeContext(p) - # make a const section out of it: - result = newNodeP(nkConstSection, p) - getTok(p, result) - var i = 0 - var hasUnknown = false - while true: - var name = skipIdentExport(p) - var val: PNode - if p.tok.xkind == pxAsgn: - getTok(p, name) - val = constantExpression(p) - if val.kind == nkIntLit: - i = int(val.intVal)+1 - hasUnknown = false - else: - hasUnknown = true - else: - if hasUnknown: - parMessage(p, warnUser, "computed const value may be wrong: " & - name.renderTree) - val = newIntNodeP(nkIntLit, i, p) - inc(i) - var c = createConst(name, ast.emptyNode, val, p) - addSon(result, c) - if p.tok.xkind != pxComma: break - getTok(p, c) - # allow trailing comma: - if p.tok.xkind == pxCurlyRi: break - eat(p, pxCurlyRi, result) - eat(p, pxSemicolon) - of pxSymbol: - var origName = p.tok.s - markTypeIdent(p, nil) - result = skipIdent(p) - case p.tok.xkind - of pxCurlyLe: - closeContext(p) - var name = result - # create a type section containing the enum - result = newNodeP(nkStmtList, p) - var tSection = newNodeP(nkTypeSection, p) - var t = newNodeP(nkTypeDef, p) - getTok(p, t) - var constSection = newNodeP(nkConstSection, p) - var e = enumFields(p, constSection) - addSon(t, exportSym(p, name, origName), ast.emptyNode, e) - addSon(tSection, t) - addSon(result, tSection) - addSon(result, constSection) - eat(p, pxCurlyRi, result) - eat(p, pxSemicolon) - of pxSemicolon: - # just ignore ``enum X;`` for now. - closeContext(p) - getTok(p, nil) - else: - backtrackContext(p) - result = declaration(p) - else: - closeContext(p) - parMessage(p, errTokenExpected, "{") - result = ast.emptyNode - -# Expressions - -proc setBaseFlags(n: PNode, base: TNumericalBase) = - case base - of base10: discard - of base2: incl(n.flags, nfBase2) - of base8: incl(n.flags, nfBase8) - of base16: incl(n.flags, nfBase16) - -proc startExpression(p : var TParser, tok : TToken) : PNode = - #echo "nud ", $tok - case tok.xkind: - of pxSymbol: - if tok.s == "NULL": - result = newNodeP(nkNilLit, p) - elif tok.s == "sizeof": - result = newNodeP(nkCall, p) - addSon(result, newIdentNodeP("sizeof", p)) - saveContext(p) - try: - addSon(result, expression(p, 139)) - closeContext(p) - except ERetryParsing: - backtrackContext(p) - eat(p, pxParLe) - addSon(result, typeName(p)) - eat(p, pxParRi) - elif (tok.s == "new" or tok.s == "delete") and pfCpp in p.options.flags: - var opr = tok.s - result = newNodeP(nkCall, p) - if p.tok.xkind == pxBracketLe: - getTok(p) - eat(p, pxBracketRi) - opr.add("Array") - addSon(result, newIdentNodeP(opr, p)) - if p.tok.xkind == pxParLe: - getTok(p, result) - addSon(result, typeDesc(p)) - eat(p, pxParRi, result) - else: - addSon(result, expression(p, 139)) - else: - result = mangledIdent(tok.s, p) - result = optScope(p, result) - result = optAngle(p, result) - of pxIntLit: - result = newIntNodeP(nkIntLit, tok.iNumber, p) - setBaseFlags(result, tok.base) - of pxInt64Lit: - result = newIntNodeP(nkInt64Lit, tok.iNumber, p) - setBaseFlags(result, tok.base) - of pxFloatLit: - result = newFloatNodeP(nkFloatLit, tok.fNumber, p) - setBaseFlags(result, tok.base) - of pxStrLit: - result = newStrNodeP(nkStrLit, tok.s, p) - while p.tok.xkind == pxStrLit: - add(result.strVal, p.tok.s) - getTok(p, result) - of pxCharLit: - result = newIntNodeP(nkCharLit, ord(tok.s[0]), p) - of pxParLe: - try: - saveContext(p) - result = newNodeP(nkPar, p) - addSon(result, expression(p, 0)) - if p.tok.xkind != pxParRi: - raise newException(ERetryParsing, "expected a ')'") - getTok(p, result) - if p.tok.xkind in {pxSymbol, pxIntLit, pxFloatLit, pxStrLit, pxCharLit}: - raise newException(ERetryParsing, "expected a non literal token") - closeContext(p) - except ERetryParsing: - backtrackContext(p) - result = newNodeP(nkCast, p) - addSon(result, typeName(p)) - eat(p, pxParRi, result) - addSon(result, expression(p, 139)) - of pxPlusPlus: - result = newNodeP(nkCall, p) - addSon(result, newIdentNodeP("inc", p)) - addSon(result, expression(p, 139)) - of pxMinusMinus: - result = newNodeP(nkCall, p) - addSon(result, newIdentNodeP("dec", p)) - addSon(result, expression(p, 139)) - of pxAmp: - result = newNodeP(nkAddr, p) - addSon(result, expression(p, 139)) - of pxStar: - result = newNodeP(nkBracketExpr, p) - addSon(result, expression(p, 139)) - of pxPlus: - result = newNodeP(nkPrefix, p) - addSon(result, newIdentNodeP("+", p)) - addSon(result, expression(p, 139)) - of pxMinus: - result = newNodeP(nkPrefix, p) - addSon(result, newIdentNodeP("-", p)) - addSon(result, expression(p, 139)) - of pxTilde: - result = newNodeP(nkPrefix, p) - addSon(result, newIdentNodeP("not", p)) - addSon(result, expression(p, 139)) - of pxNot: - result = newNodeP(nkPrefix, p) - addSon(result, newIdentNodeP("not", p)) - addSon(result, expression(p, 139)) - else: - # probably from a failed sub expression attempt, try a type cast - raise newException(ERetryParsing, "did not expect " & $tok) - -proc leftBindingPower(p : var TParser, tok : ref TToken) : int = - #echo "lbp ", $tok[] - case tok.xkind: - of pxComma: - return 10 - # throw == 20 - of pxAsgn, pxPlusAsgn, pxMinusAsgn, pxStarAsgn, pxSlashAsgn, pxModAsgn, - pxShlAsgn, pxShrAsgn, pxAmpAsgn, pxHatAsgn, pxBarAsgn: - return 30 - of pxConditional: - return 40 - of pxBarBar: - return 50 - of pxAmpAmp: - return 60 - of pxBar: - return 70 - of pxHat: - return 80 - of pxAmp: - return 90 - of pxEquals, pxNeq: - return 100 - of pxLt, pxLe, pxGt, pxGe: - return 110 - of pxShl, pxShr: - return 120 - of pxPlus, pxMinus: - return 130 - of pxStar, pxSlash, pxMod: - return 140 - # .* ->* == 150 - of pxPlusPlus, pxMinusMinus, pxParLe, pxDot, pxArrow, pxBracketLe: - return 160 - # :: == 170 - else: - return 0 - -proc buildStmtList(a: PNode): PNode - -proc leftExpression(p : var TParser, tok : TToken, left : PNode) : PNode = - #echo "led ", $tok - case tok.xkind: - of pxComma: # 10 - # not supported as an expression, turns into a statement list - result = buildStmtList(left) - addSon(result, expression(p, 0)) - # throw == 20 - of pxAsgn: # 30 - result = newNodeP(nkAsgn, p) - addSon(result, left, expression(p, 29)) - of pxPlusAsgn: # 30 - result = newNodeP(nkCall, p) - addSon(result, newIdentNodeP(getIdent("inc"), p), left, expression(p, 29)) - of pxMinusAsgn: # 30 - result = newNodeP(nkCall, p) - addSon(result, newIdentNodeP(getIdent("dec"), p), left, expression(p, 29)) - of pxStarAsgn: # 30 - result = newNodeP(nkAsgn, p) - var right = expression(p, 29) - addSon(result, left, newBinary("*", copyTree(left), right, p)) - of pxSlashAsgn: # 30 - result = newNodeP(nkAsgn, p) - var right = expression(p, 29) - addSon(result, left, newBinary("/", copyTree(left), right, p)) - of pxModAsgn: # 30 - result = newNodeP(nkAsgn, p) - var right = expression(p, 29) - addSon(result, left, newBinary("mod", copyTree(left), right, p)) - of pxShlAsgn: # 30 - result = newNodeP(nkAsgn, p) - var right = expression(p, 29) - addSon(result, left, newBinary("shl", copyTree(left), right, p)) - of pxShrAsgn: # 30 - result = newNodeP(nkAsgn, p) - var right = expression(p, 29) - addSon(result, left, newBinary("shr", copyTree(left), right, p)) - of pxAmpAsgn: # 30 - result = newNodeP(nkAsgn, p) - var right = expression(p, 29) - addSon(result, left, newBinary("and", copyTree(left), right, p)) - of pxHatAsgn: # 30 - result = newNodeP(nkAsgn, p) - var right = expression(p, 29) - addSon(result, left, newBinary("xor", copyTree(left), right, p)) - of pxBarAsgn: # 30 - result = newNodeP(nkAsgn, p) - var right = expression(p, 29) - addSon(result, left, newBinary("or", copyTree(left), right, p)) - of pxConditional: # 40 - var a = expression(p, 0) - eat(p, pxColon, a) - var b = expression(p, 39) - result = newNodeP(nkIfExpr, p) - var branch = newNodeP(nkElifExpr, p) - addSon(branch, left, a) - addSon(result, branch) - branch = newNodeP(nkElseExpr, p) - addSon(branch, b) - addSon(result, branch) - of pxBarBar: # 50 - result = newBinary("or", left, expression(p, 50), p) - of pxAmpAmp: # 60 - result = newBinary("and", left, expression(p, 60), p) - of pxBar: # 70 - result = newBinary("or", left, expression(p, 70), p) - of pxHat: # 80 - result = newBinary("^", left, expression(p, 80), p) - of pxAmp: # 90 - result = newBinary("and", left, expression(p, 90), p) - of pxEquals: # 100 - result = newBinary("==", left, expression(p, 100), p) - of pxNeq: # 100 - result = newBinary("!=", left, expression(p, 100), p) - of pxLt: # 110 - result = newBinary("<", left, expression(p, 110), p) - of pxLe: # 110 - result = newBinary("<=", left, expression(p, 110), p) - of pxGt: # 110 - result = newBinary(">", left, expression(p, 110), p) - of pxGe: # 110 - result = newBinary(">=", left, expression(p, 110), p) - of pxShl: # 120 - result = newBinary("shl", left, expression(p, 120), p) - of pxShr: # 120 - result = newBinary("shr", left, expression(p, 120), p) - of pxPlus: # 130 - result = newNodeP(nkInfix, p) - addSon(result, newIdentNodeP("+", p), left) - addSon(result, expression(p, 130)) - of pxMinus: # 130 - result = newNodeP(nkInfix, p) - addSon(result, newIdentNodeP("+", p), left) - addSon(result, expression(p, 130)) - of pxStar: # 140 - result = newNodeP(nkInfix, p) - addSon(result, newIdentNodeP("*", p), left) - addSon(result, expression(p, 140)) - of pxSlash: # 140 - result = newNodeP(nkInfix, p) - addSon(result, newIdentNodeP("div", p), left) - addSon(result, expression(p, 140)) - of pxMod: # 140 - result = newNodeP(nkInfix, p) - addSon(result, newIdentNodeP("mod", p), left) - addSon(result, expression(p, 140)) - # .* ->* == 150 - of pxPlusPlus: # 160 - result = newNodeP(nkCall, p) - addSon(result, newIdentNodeP("inc", p), left) - of pxMinusMinus: # 160 - result = newNodeP(nkCall, p) - addSon(result, newIdentNodeP("dec", p), left) - of pxParLe: # 160 - result = newNodeP(nkCall, p) - addSon(result, left) - while p.tok.xkind != pxParRi: - var a = expression(p, 29) - addSon(result, a) - while p.tok.xkind == pxComma: - getTok(p, a) - a = expression(p, 29) - addSon(result, a) - eat(p, pxParRi, result) - of pxDot: # 160 - result = newNodeP(nkDotExpr, p) - addSon(result, left) - addSon(result, skipIdent(p)) - of pxArrow: # 160 - result = newNodeP(nkDotExpr, p) - addSon(result, left) - addSon(result, skipIdent(p)) - of pxBracketLe: # 160 - result = newNodeP(nkBracketExpr, p) - addSon(result, left, expression(p)) - eat(p, pxBracketRi, result) - # :: == 170 - else: - result = left - -proc expression*(p : var TParser, rbp : int = 0) : PNode = - var tok : TToken - - tok = p.tok[] - getTok(p, result) - - result = startExpression(p, tok) - - while rbp < leftBindingPower(p, p.tok): - tok = p.tok[] - getTok(p, result) - result = leftExpression(p, tok, result) - -# Statements - -proc buildStmtList(a: PNode): PNode = - if a.kind == nkStmtList: result = a - else: - result = newNodeI(nkStmtList, a.info) - addSon(result, a) - -proc nestedStatement(p: var TParser): PNode = - # careful: We need to translate: - # if (x) if (y) stmt; - # into: - # if x: - # if x: - # stmt - # - # Nimrod requires complex statements to be nested in whitespace! - const - complexStmt = {nkProcDef, nkMethodDef, nkConverterDef, nkMacroDef, - nkTemplateDef, nkIteratorDef, nkIfStmt, - nkWhenStmt, nkForStmt, nkWhileStmt, nkCaseStmt, nkVarSection, - nkConstSection, nkTypeSection, nkTryStmt, nkBlockStmt, nkStmtList, - nkCommentStmt, nkStmtListExpr, nkBlockExpr, nkStmtListType, nkBlockType} - result = statement(p) - if result.kind in complexStmt: - result = buildStmtList(result) - -proc expressionStatement(p: var TParser): PNode = - # do not skip the comment after a semicolon to make a new nkCommentStmt - if p.tok.xkind == pxSemicolon: - getTok(p) - result = ast.emptyNode - else: - result = expression(p) - if p.tok.xkind == pxSemicolon: getTok(p) - else: parMessage(p, errTokenExpected, ";") - assert result != nil - -proc parseIf(p: var TParser): PNode = - # we parse additional "else if"s too here for better Nimrod code - result = newNodeP(nkIfStmt, p) - while true: - getTok(p) # skip ``if`` - var branch = newNodeP(nkElifBranch, p) - eat(p, pxParLe, branch) - addSon(branch, expression(p)) - eat(p, pxParRi, branch) - addSon(branch, nestedStatement(p)) - addSon(result, branch) - skipCom(p, branch) - if p.tok.s == "else": - getTok(p, result) - if p.tok.s != "if": - # ordinary else part: - branch = newNodeP(nkElse, p) - addSon(branch, nestedStatement(p)) - addSon(result, branch) - break - else: - break - -proc parseWhile(p: var TParser): PNode = - result = newNodeP(nkWhileStmt, p) - getTok(p, result) - eat(p, pxParLe, result) - addSon(result, expression(p)) - eat(p, pxParRi, result) - addSon(result, nestedStatement(p)) - -proc embedStmts(sl, a: PNode) - -proc parseDoWhile(p: var TParser): PNode = - # parsing - result = newNodeP(nkWhileStmt, p) - getTok(p, result) - var stm = nestedStatement(p) - eat(p, "while", result) - eat(p, pxParLe, result) - var exp = expression(p) - eat(p, pxParRi, result) - if p.tok.xkind == pxSemicolon: getTok(p) - - # while true: - # stmt - # if not expr: - # break - addSon(result, newIdentNodeP("true", p)) - - stm = buildStmtList(stm) - - # get the last exp if it is a stmtlist - var cleanedExp = exp - if exp.kind == nkStmtList: - cleanedExp = exp.sons[exp.len-1] - exp.sons = exp.sons[0..exp.len-2] - embedStmts(stm, exp) - - var notExp = newNodeP(nkPrefix, p) - addSon(notExp, newIdentNodeP("not", p)) - addSon(notExp, cleanedExp) - - var brkStm = newNodeP(nkBreakStmt, p) - addSon(brkStm, ast.emptyNode) - - var ifStm = newNodeP(nkIfStmt, p) - var ifBranch = newNodeP(nkElifBranch, p) - addSon(ifBranch, notExp) - addSon(ifBranch, brkStm) - addSon(ifStm, ifBranch) - - embedStmts(stm, ifStm) - - addSon(result, stm) - -proc declarationOrStatement(p: var TParser): PNode = - if p.tok.xkind != pxSymbol: - result = expressionStatement(p) - elif declKeyword(p, p.tok.s): - result = declaration(p) - else: - # ordinary identifier: - saveContext(p) - getTok(p) # skip identifier to look ahead - case p.tok.xkind - of pxSymbol, pxStar, pxLt, pxAmp, pxAmpAmp: - # we parse - # a b - # a * b - # always as declarations! This is of course not correct, but good - # enough for most real world C code out there. - backtrackContext(p) - result = declaration(p) - of pxColon: - # it is only a label: - closeContext(p) - getTok(p) - result = statement(p) - else: - backtrackContext(p) - result = expressionStatement(p) - assert result != nil - -proc parseTuple(p: var TParser, statements: PNode, isUnion: bool): PNode = - parseStructBody(p, statements, isUnion, nkTupleTy) - -proc parseTrailingDefinedIdents(p: var TParser, result, baseTyp: PNode) = - var varSection = newNodeP(nkVarSection, p) - while p.tok.xkind notin {pxEof, pxSemicolon}: - var t = pointer(p, baseTyp) - expectIdent(p) - var def = newNodeP(nkIdentDefs, p) - addSon(def, varIdent(p.tok.s, p)) - getTok(p, def) - addSon(def, parseTypeSuffix(p, t)) - addInitializer(p, def) - addSon(varSection, def) - if p.tok.xkind != pxComma: break - getTok(p, def) - eat(p, pxSemicolon) - if sonsLen(varSection) > 0: - addSon(result, varSection) - -proc parseStandaloneStruct(p: var TParser, isUnion: bool): PNode = - result = newNodeP(nkStmtList, p) - saveContext(p) - getTok(p, result) # skip "struct" or "union" - var origName = "" - if p.tok.xkind == pxSymbol: - markTypeIdent(p, nil) - origName = p.tok.s - getTok(p, result) - if p.tok.xkind in {pxCurlyLe, pxSemiColon}: - if origName.len > 0: - var name = mangledIdent(origName, p) - var t = parseStruct(p, result, isUnion) - var typeSection = newNodeP(nkTypeSection, p) - addTypeDef(typeSection, structPragmas(p, name, origName), t) - addSon(result, typeSection) - parseTrailingDefinedIdents(p, result, name) - else: - var t = parseTuple(p, result, isUnion) - parseTrailingDefinedIdents(p, result, t) - else: - backtrackContext(p) - result = declaration(p) - -proc parseFor(p: var TParser, result: PNode) = - # 'for' '(' expression_statement expression_statement expression? ')' - # statement - getTok(p, result) - eat(p, pxParLe, result) - var initStmt = declarationOrStatement(p) - if initStmt.kind != nkEmpty: - embedStmts(result, initStmt) - var w = newNodeP(nkWhileStmt, p) - var condition = expressionStatement(p) - if condition.kind == nkEmpty: condition = newIdentNodeP("true", p) - addSon(w, condition) - var step = if p.tok.xkind != pxParRi: expression(p) else: ast.emptyNode - eat(p, pxParRi, step) - var loopBody = nestedStatement(p) - if step.kind != nkEmpty: - loopBody = buildStmtList(loopBody) - embedStmts(loopBody, step) - addSon(w, loopBody) - addSon(result, w) - -proc switchStatement(p: var TParser): PNode = - result = newNodeP(nkStmtList, p) - while true: - if p.tok.xkind in {pxEof, pxCurlyRi}: break - case p.tok.s - of "break": - getTok(p, result) - eat(p, pxSemicolon, result) - break - of "return", "continue", "goto": - addSon(result, statement(p)) - break - of "case", "default": - break - else: discard - addSon(result, statement(p)) - if sonsLen(result) == 0: - # translate empty statement list to Nimrod's ``nil`` statement - result = newNodeP(nkNilLit, p) - -proc rangeExpression(p: var TParser): PNode = - # We support GCC's extension: ``case expr...expr:`` - result = constantExpression(p) - if p.tok.xkind == pxDotDotDot: - getTok(p, result) - var a = result - var b = constantExpression(p) - result = newNodeP(nkRange, p) - addSon(result, a) - addSon(result, b) - -proc parseSwitch(p: var TParser): PNode = - # We cannot support Duff's device or C's crazy switch syntax. We just support - # sane usages of switch. ;-) - result = newNodeP(nkCaseStmt, p) - getTok(p, result) - eat(p, pxParLe, result) - addSon(result, expression(p)) - eat(p, pxParRi, result) - eat(p, pxCurlyLe, result) - var b: PNode - while (p.tok.xkind != pxCurlyRi) and (p.tok.xkind != pxEof): - case p.tok.s - of "default": - b = newNodeP(nkElse, p) - getTok(p, b) - eat(p, pxColon, b) - of "case": - b = newNodeP(nkOfBranch, p) - while p.tok.xkind == pxSymbol and p.tok.s == "case": - getTok(p, b) - addSon(b, rangeExpression(p)) - eat(p, pxColon, b) - else: - parMessage(p, errXExpected, "case") - addSon(b, switchStatement(p)) - addSon(result, b) - if b.kind == nkElse: break - eat(p, pxCurlyRi) - -proc addStmt(sl, a: PNode) = - # merge type sections if possible: - if a.kind != nkTypeSection or sonsLen(sl) == 0 or - lastSon(sl).kind != nkTypeSection: - addSon(sl, a) - else: - var ts = lastSon(sl) - for i in 0..sonsLen(a)-1: addSon(ts, a.sons[i]) - -proc embedStmts(sl, a: PNode) = - if a.kind != nkStmtList: - addStmt(sl, a) - else: - for i in 0..sonsLen(a)-1: - if a[i].kind != nkEmpty: addStmt(sl, a[i]) - -proc compoundStatement(p: var TParser): PNode = - result = newNodeP(nkStmtList, p) - eat(p, pxCurlyLe) - inc(p.scopeCounter) - while p.tok.xkind notin {pxEof, pxCurlyRi}: - var a = statement(p) - if a.kind == nkEmpty: break - embedStmts(result, a) - if sonsLen(result) == 0: - # translate ``{}`` to Nimrod's ``discard`` statement - result = newNodeP(nkDiscardStmt, p) - result.add(ast.emptyNode) - dec(p.scopeCounter) - eat(p, pxCurlyRi) - -proc skipInheritKeyw(p: var TParser) = - if p.tok.xkind == pxSymbol and (p.tok.s == "private" or - p.tok.s == "protected" or - p.tok.s == "public"): - getTok(p) - -proc parseConstructor(p: var TParser, pragmas: PNode, - isDestructor=false): PNode = - var origName = p.tok.s - getTok(p) - - result = newNodeP(nkProcDef, p) - var rettyp = if isDestructor: newNodeP(nkNilLit, p) - else: mangledIdent(origName, p) - - let oname = if isDestructor: "destroy" & origName - else: "construct" & origName - var name = mangledIdent(oname, p) - var params = newNodeP(nkFormalParams, p) - addReturnType(params, rettyp) - if p.tok.xkind == pxParLe: - parseFormalParams(p, params, pragmas) - if p.tok.xkind == pxSymbol and p.tok.s == "const": - addSon(pragmas, newIdentNodeP("noSideEffect", p)) - if pfCDecl in p.options.flags: - addSon(pragmas, newIdentNodeP("cdecl", p)) - elif pfStdcall in p.options.flags: - addSon(pragmas, newIdentNodeP("stdcall", p)) - if p.tok.xkind == pxColon: - # skip initializer list: - while true: - getTok(p) - discard expression(p) - if p.tok.xkind != pxComma: break - # no pattern, no exceptions: - addSon(result, exportSym(p, name, origName), ast.emptyNode, ast.emptyNode) - addSon(result, params, pragmas, ast.emptyNode) # no exceptions - addSon(result, ast.emptyNode) # no body - case p.tok.xkind - of pxSemicolon: getTok(p) - of pxCurlyLe: - let body = compoundStatement(p) - if pfKeepBodies in p.options.flags: - result.sons[bodyPos] = body - else: - parMessage(p, errTokenExpected, ";") - if result.sons[bodyPos].kind == nkEmpty: - doImport((if isDestructor: "~" else: "") & origName, pragmas, p) - elif isDestructor: - addSon(pragmas, newIdentNodeP("destructor", p)) - if sonsLen(result.sons[pragmasPos]) == 0: - result.sons[pragmasPos] = ast.emptyNode - -proc parseMethod(p: var TParser, origName: string, rettyp, pragmas: PNode, - isStatic: bool): PNode = - result = newNodeP(nkProcDef, p) - var params = newNodeP(nkFormalParams, p) - addReturnType(params, rettyp) - var thisDef = newNodeP(nkIdentDefs, p) - if not isStatic: - # declare 'this': - var t = newNodeP(nkVarTy, p) - t.add(p.currentClass) - addSon(thisDef, newIdentNodeP("this", p), t, ast.emptyNode) - params.add(thisDef) - parseFormalParams(p, params, pragmas) - if p.tok.xkind == pxSymbol and p.tok.s == "const": - addSon(pragmas, newIdentNodeP("noSideEffect", p)) - getTok(p, result) - if not isStatic: - # fix the type of the 'this' parameter: - thisDef.sons[1] = thisDef.sons[1].sons[0] - if pfCDecl in p.options.flags: - addSon(pragmas, newIdentNodeP("cdecl", p)) - elif pfStdcall in p.options.flags: - addSon(pragmas, newIdentNodeP("stdcall", p)) - # no pattern, no exceptions: - let methodName = newIdentNodeP(origName, p) - addSon(result, exportSym(p, methodName, origName), - ast.emptyNode, ast.emptyNode) - addSon(result, params, pragmas, ast.emptyNode) # no exceptions - addSon(result, ast.emptyNode) # no body - case p.tok.xkind - of pxSemicolon: getTok(p) - of pxCurlyLe: - let body = compoundStatement(p) - if pfKeepBodies in p.options.flags: - result.sons[bodyPos] = body - else: - parMessage(p, errTokenExpected, ";") - if result.sons[bodyPos].kind == nkEmpty: - if isStatic: doImport(origName, pragmas, p) - else: doImportCpp(origName, pragmas, p) - if sonsLen(result.sons[pragmasPos]) == 0: - result.sons[pragmasPos] = ast.emptyNode - -proc parseStandaloneClass(p: var TParser, isStruct: bool): PNode - -proc followedByParLe(p: var TParser): bool = - saveContext(p) - getTok(p) # skip Identifier - result = p.tok.xkind == pxParLe - backtrackContext(p) - -proc parseOperator(p: var TParser, origName: var string): bool = - getTok(p) # skip 'operator' keyword - case p.tok.xkind - of pxAmp..pxArrow: - # ordinary operator symbol: - origName.add(tokKindToStr(p.tok.xkind)) - getTok(p) - of pxSymbol: - if p.tok.s == "new" or p.tok.s == "delete": - origName.add(p.tok.s) - getTok(p) - if p.tok.xkind == pxBracketLe: - getTok(p) - eat(p, pxBracketRi) - origName.add("[]") - else: - # type converter - let x = typeAtom(p) - if x.kind == nkIdent: - origName.add(x.ident.s) - else: - parMessage(p, errGenerated, "operator symbol expected") - result = true - of pxParLe: - getTok(p) - eat(p, pxParRi) - origName.add("()") - of pxBracketLe: - getTok(p) - eat(p, pxBracketRi) - origName.add("[]") - else: - parMessage(p, errGenerated, "operator symbol expected") - -proc parseClass(p: var TParser; isStruct: bool; stmtList: PNode): PNode = - result = newNodeP(nkObjectTy, p) - addSon(result, ast.emptyNode, ast.emptyNode) # no pragmas, no inheritance - - var recList = newNodeP(nkRecList, p) - addSon(result, recList) - if p.tok.xkind == pxColon: - getTok(p, result) - skipInheritKeyw(p) - var baseTyp = typeAtom(p) - var inh = newNodeP(nkOfInherit, p) - inh.add(baseTyp) - if p.tok.xkind == pxComma: - parMessage(p, errGenerated, "multiple inheritance is not supported") - while p.tok.xkind == pxComma: - getTok(p) - skipInheritKeyw(p) - discard typeAtom(p) - result.sons[0] = inh - - eat(p, pxCurlyLe, result) - var private = not isStruct - var pragmas = newNodeP(nkPragma, p) - while p.tok.xkind notin {pxEof, pxCurlyRi}: - skipCom(p, stmtList) - if p.tok.xkind == pxSymbol and (p.tok.s == "private" or - p.tok.s == "protected"): - getTok(p, result) - eat(p, pxColon, result) - private = true - elif p.tok.xkind == pxSymbol and p.tok.s == "public": - getTok(p, result) - eat(p, pxColon, result) - private = false - if p.tok.xkind == pxSymbol and (p.tok.s == "friend" or p.tok.s == "using"): - # we skip friend declarations: - while p.tok.xkind notin {pxEof, pxSemicolon}: getTok(p) - eat(p, pxSemicolon) - elif p.tok.xkind == pxSymbol and p.tok.s == "enum": - let x = enumSpecifier(p) - if not private or pfKeepBodies in p.options.flags: stmtList.add(x) - elif p.tok.xkind == pxSymbol and p.tok.s == "typedef": - let x = parseTypeDef(p) - if not private or pfKeepBodies in p.options.flags: stmtList.add(x) - elif p.tok.xkind == pxSymbol and(p.tok.s == "struct" or p.tok.s == "class"): - let x = parseStandaloneClass(p, isStruct=p.tok.s == "struct") - if not private or pfKeepBodies in p.options.flags: stmtList.add(x) - elif p.tok.xkind == pxSymbol and p.tok.s == "union": - let x = parseStandaloneStruct(p, isUnion=true) - if not private or pfKeepBodies in p.options.flags: stmtList.add(x) - else: - if pragmas.len != 0: pragmas = newNodeP(nkPragma, p) - parseCallConv(p, pragmas) - var isStatic = false - if p.tok.xkind == pxSymbol and p.tok.s == "virtual": - getTok(p, stmtList) - if p.tok.xkind == pxSymbol and p.tok.s == "explicit": - getTok(p, stmtList) - if p.tok.xkind == pxSymbol and p.tok.s == "static": - getTok(p, stmtList) - isStatic = true - parseCallConv(p, pragmas) - if p.tok.xkind == pxSymbol and p.tok.s == p.currentClass.ident.s and - followedByParLe(p): - # constructor - let cons = parseConstructor(p, pragmas) - if not private or pfKeepBodies in p.options.flags: stmtList.add(cons) - elif p.tok.xkind == pxTilde: - # destructor - getTok(p, stmtList) - if p.tok.xkind == pxSymbol and p.tok.s == p.currentClass.ident.s: - let des = parseConstructor(p, pragmas, isDestructor=true) - if not private or pfKeepBodies in p.options.flags: stmtList.add(des) - else: - parMessage(p, errGenerated, "invalid destructor") - else: - # field declaration or method: - var baseTyp = typeAtom(p) - while true: - var def = newNodeP(nkIdentDefs, p) - var t = pointer(p, baseTyp) - let canBeMethod = p.tok.xkind != pxParLe - var origName: string - if p.tok.xkind == pxSymbol: - origName = p.tok.s - if p.tok.s == "operator": - var isConverter = parseOperator(p, origName) - let meth = parseMethod(p, origName, t, pragmas, isStatic) - if not private or pfKeepBodies in p.options.flags: - if isConverter: meth.kind = nkConverterDef - stmtList.add(meth) - break - var i = parseField(p, nkRecList) - if canBeMethod and p.tok.xkind == pxParLe: - let meth = parseMethod(p, origName, t, pragmas, isStatic) - if not private or pfKeepBodies in p.options.flags: - stmtList.add(meth) - else: - t = parseTypeSuffix(p, t) - addSon(def, i, t, ast.emptyNode) - if not isStatic: addSon(recList, def) - if p.tok.xkind != pxComma: break - getTok(p, def) - if p.tok.xkind == pxSemicolon: - getTok(p, lastSon(recList)) - eat(p, pxCurlyRi, result) - -proc parseStandaloneClass(p: var TParser, isStruct: bool): PNode = - result = newNodeP(nkStmtList, p) - saveContext(p) - getTok(p, result) # skip "class" or "struct" - var origName = "" - let oldClass = p.currentClass - if p.tok.xkind == pxSymbol: - markTypeIdent(p, nil) - origName = p.tok.s - getTok(p, result) - p.currentClass = mangledIdent(origName, p) - else: - p.currentClass = nil - if p.tok.xkind in {pxCurlyLe, pxSemiColon, pxColon}: - if origName.len > 0: - p.options.classes[origName] = "true" - - var typeSection = newNodeP(nkTypeSection, p) - addSon(result, typeSection) - - var name = mangledIdent(origName, p) - var t = parseClass(p, isStruct, result) - addTypeDef(typeSection, structPragmas(p, name, origName), t) - parseTrailingDefinedIdents(p, result, name) - else: - var t = parseTuple(p, result, isUnion=false) - parseTrailingDefinedIdents(p, result, t) - else: - backtrackContext(p) - result = declaration(p) - p.currentClass = oldClass - -proc unwrap(a: PNode): PNode = - if a.kind == nkPar: - return a.sons[0] - return a - -include cpp - -proc statement(p: var TParser): PNode = - case p.tok.xkind - of pxSymbol: - case p.tok.s - of "if": result = parseIf(p) - of "switch": result = parseSwitch(p) - of "while": result = parseWhile(p) - of "do": result = parseDoWhile(p) - of "for": - result = newNodeP(nkStmtList, p) - parseFor(p, result) - of "goto": - # we cannot support "goto"; in hand-written C, "goto" is most often used - # to break a block, so we convert it to a break statement with label. - result = newNodeP(nkBreakStmt, p) - getTok(p) - addSon(result, skipIdent(p)) - eat(p, pxSemicolon) - of "continue": - result = newNodeP(nkContinueStmt, p) - getTok(p) - eat(p, pxSemicolon) - addSon(result, ast.emptyNode) - of "break": - result = newNodeP(nkBreakStmt, p) - getTok(p) - eat(p, pxSemicolon) - addSon(result, ast.emptyNode) - of "return": - result = newNodeP(nkReturnStmt, p) - getTok(p) - if p.tok.xkind == pxSemicolon: - addSon(result, ast.emptyNode) - else: - addSon(result, unwrap(expression(p))) - eat(p, pxSemicolon) - of "enum": result = enumSpecifier(p) - of "typedef": result = parseTypeDef(p) - of "union": result = parseStandaloneStruct(p, isUnion=true) - of "struct": - if pfCpp in p.options.flags: - result = parseStandaloneClass(p, isStruct=true) - else: - result = parseStandaloneStruct(p, isUnion=false) - of "class": - if pfCpp in p.options.flags: - result = parseStandaloneClass(p, isStruct=false) - else: - result = declarationOrStatement(p) - of "namespace": - if pfCpp in p.options.flags: - while p.tok.xkind notin {pxEof, pxCurlyLe}: getTok(p) - result = compoundStatement(p) - else: - result = declarationOrStatement(p) - of "using": - if pfCpp in p.options.flags: - while p.tok.xkind notin {pxEof, pxSemicolon}: getTok(p) - eat(p, pxSemicolon) - result = newNodeP(nkNilLit, p) - else: - result = declarationOrStatement(p) - else: result = declarationOrStatement(p) - of pxCurlyLe: - result = compoundStatement(p) - of pxDirective, pxDirectiveParLe: - result = parseDir(p) - of pxLineComment, pxStarComment: - result = newNodeP(nkCommentStmt, p) - skipCom(p, result) - of pxSemicolon: - # empty statement: - getTok(p) - if p.tok.xkind in {pxLineComment, pxStarComment}: - result = newNodeP(nkCommentStmt, p) - skipCom(p, result) - else: - result = newNodeP(nkNilLit, p) - else: - result = expressionStatement(p) - assert result != nil - -proc parseUnit(p: var TParser): PNode = - try: - result = newNodeP(nkStmtList, p) - getTok(p) # read first token - while p.tok.xkind != pxEof: - var s = statement(p) - if s.kind != nkEmpty: embedStmts(result, s) - except ERetryParsing: - parMessage(p, errGenerated, "Uncaught parsing exception raised") - diff --git a/compiler/c2nim/cpp.nim b/compiler/c2nim/cpp.nim deleted file mode 100644 index 84b4c4dfb6..0000000000 --- a/compiler/c2nim/cpp.nim +++ /dev/null @@ -1,347 +0,0 @@ -# -# -# c2nim - C to Nimrod source converter -# (c) Copyright 2012 Andreas Rumpf -# -# See the file "copying.txt", included in this -# distribution, for details about the copyright. -# - -# Preprocessor support - -const - c2nimSymbol = "C2NIM" - -proc eatNewLine(p: var TParser, n: PNode) = - if p.tok.xkind == pxLineComment: - skipCom(p, n) - if p.tok.xkind == pxNewLine: getTok(p) - elif p.tok.xkind == pxNewLine: - eat(p, pxNewLine) - -proc skipLine(p: var TParser) = - while p.tok.xkind notin {pxEof, pxNewLine, pxLineComment}: getTok(p) - eatNewLine(p, nil) - -proc parseDefineBody(p: var TParser, tmplDef: PNode): string = - if p.tok.xkind == pxCurlyLe or - (p.tok.xkind == pxSymbol and ( - declKeyword(p, p.tok.s) or stmtKeyword(p.tok.s))): - addSon(tmplDef, statement(p)) - result = "stmt" - elif p.tok.xkind in {pxLineComment, pxNewLine}: - addSon(tmplDef, buildStmtList(newNodeP(nkNilLit, p))) - result = "stmt" - else: - addSon(tmplDef, buildStmtList(expression(p))) - result = "expr" - -proc parseDefine(p: var TParser): PNode = - if p.tok.xkind == pxDirectiveParLe: - # a macro with parameters: - result = newNodeP(nkTemplateDef, p) - getTok(p) - addSon(result, skipIdentExport(p)) - addSon(result, ast.emptyNode) - eat(p, pxParLe) - var params = newNodeP(nkFormalParams, p) - # return type; not known yet: - addSon(params, ast.emptyNode) - if p.tok.xkind != pxParRi: - var identDefs = newNodeP(nkIdentDefs, p) - while p.tok.xkind != pxParRi: - addSon(identDefs, skipIdent(p)) - skipStarCom(p, nil) - if p.tok.xkind != pxComma: break - getTok(p) - addSon(identDefs, newIdentNodeP("expr", p)) - addSon(identDefs, ast.emptyNode) - addSon(params, identDefs) - eat(p, pxParRi) - - addSon(result, ast.emptyNode) # no generic parameters - addSon(result, params) - addSon(result, ast.emptyNode) # no pragmas - addSon(result, ast.emptyNode) - var kind = parseDefineBody(p, result) - params.sons[0] = newIdentNodeP(kind, p) - eatNewLine(p, result) - else: - # a macro without parameters: - result = newNodeP(nkConstSection, p) - while p.tok.xkind == pxDirective and p.tok.s == "define": - getTok(p) # skip #define - var c = newNodeP(nkConstDef, p) - addSon(c, skipIdentExport(p)) - addSon(c, ast.emptyNode) - skipStarCom(p, c) - if p.tok.xkind in {pxLineComment, pxNewLine, pxEof}: - addSon(c, newIdentNodeP("true", p)) - else: - addSon(c, expression(p)) - addSon(result, c) - eatNewLine(p, c) - assert result != nil - -proc parseDefBody(p: var TParser, m: var TMacro, params: seq[string]) = - m.body = @[] - # A little hack: We safe the context, so that every following token will be - # put into a newly allocated TToken object. Thus we can just save a - # reference to the token in the macro's body. - saveContext(p) - while p.tok.xkind notin {pxEof, pxNewLine, pxLineComment}: - case p.tok.xkind - of pxSymbol: - # is it a parameter reference? - var tok = p.tok - for i in 0..high(params): - if params[i] == p.tok.s: - new(tok) - tok.xkind = pxMacroParam - tok.iNumber = i - break - m.body.add(tok) - of pxDirConc: - # just ignore this token: this implements token merging correctly - discard - else: - m.body.add(p.tok) - # we do not want macro expansion here: - rawGetTok(p) - eatNewLine(p, nil) - closeContext(p) - # newline token might be overwritten, but this is not - # part of the macro body, so it is safe. - -proc parseDef(p: var TParser, m: var TMacro) = - var hasParams = p.tok.xkind == pxDirectiveParLe - getTok(p) - expectIdent(p) - m.name = p.tok.s - getTok(p) - var params: seq[string] = @[] - # parse parameters: - if hasParams: - eat(p, pxParLe) - while p.tok.xkind != pxParRi: - expectIdent(p) - params.add(p.tok.s) - getTok(p) - skipStarCom(p, nil) - if p.tok.xkind != pxComma: break - getTok(p) - eat(p, pxParRi) - m.params = params.len - parseDefBody(p, m, params) - -proc isDir(p: TParser, dir: string): bool = - result = p.tok.xkind in {pxDirectiveParLe, pxDirective} and p.tok.s == dir - -proc parseInclude(p: var TParser): PNode = - result = newNodeP(nkImportStmt, p) - while isDir(p, "include"): - getTok(p) # skip "include" - if p.tok.xkind == pxStrLit and pfSkipInclude notin p.options.flags: - var file = newStrNodeP(nkStrLit, changeFileExt(p.tok.s, ""), p) - addSon(result, file) - getTok(p) - skipStarCom(p, file) - eatNewLine(p, nil) - else: - skipLine(p) - if sonsLen(result) == 0: - # we only parsed includes that we chose to ignore: - result = ast.emptyNode - -proc definedExprAux(p: var TParser): PNode = - result = newNodeP(nkCall, p) - addSon(result, newIdentNodeP("defined", p)) - addSon(result, skipIdent(p)) - -proc parseStmtList(p: var TParser): PNode = - result = newNodeP(nkStmtList, p) - while true: - case p.tok.xkind - of pxEof: break - of pxDirectiveParLe, pxDirective: - case p.tok.s - of "else", "endif", "elif": break - else: discard - addSon(result, statement(p)) - -proc eatEndif(p: var TParser) = - if isDir(p, "endif"): - skipLine(p) - else: - parMessage(p, errXExpected, "#endif") - -proc parseIfDirAux(p: var TParser, result: PNode) = - addSon(result.sons[0], parseStmtList(p)) - while isDir(p, "elif"): - var b = newNodeP(nkElifBranch, p) - getTok(p) - addSon(b, expression(p)) - eatNewLine(p, nil) - addSon(b, parseStmtList(p)) - addSon(result, b) - if isDir(p, "else"): - var s = newNodeP(nkElse, p) - skipLine(p) - addSon(s, parseStmtList(p)) - addSon(result, s) - eatEndif(p) - -proc skipUntilEndif(p: var TParser) = - var nested = 1 - while p.tok.xkind != pxEof: - if isDir(p, "ifdef") or isDir(p, "ifndef") or isDir(p, "if"): - inc(nested) - elif isDir(p, "endif"): - dec(nested) - if nested <= 0: - skipLine(p) - return - getTok(p) - parMessage(p, errXExpected, "#endif") - -type - TEndifMarker = enum - emElif, emElse, emEndif - -proc skipUntilElifElseEndif(p: var TParser): TEndifMarker = - var nested = 1 - while p.tok.xkind != pxEof: - if isDir(p, "ifdef") or isDir(p, "ifndef") or isDir(p, "if"): - inc(nested) - elif isDir(p, "elif") and nested <= 1: - return emElif - elif isDir(p, "else") and nested <= 1: - return emElse - elif isDir(p, "endif"): - dec(nested) - if nested <= 0: - return emEndif - getTok(p) - parMessage(p, errXExpected, "#endif") - -proc parseIfdef(p: var TParser): PNode = - getTok(p) # skip #ifdef - expectIdent(p) - case p.tok.s - of "__cplusplus": - skipUntilEndif(p) - result = ast.emptyNode - of c2nimSymbol: - skipLine(p) - result = parseStmtList(p) - skipUntilEndif(p) - else: - result = newNodeP(nkWhenStmt, p) - addSon(result, newNodeP(nkElifBranch, p)) - addSon(result.sons[0], definedExprAux(p)) - eatNewLine(p, nil) - parseIfDirAux(p, result) - -proc parseIfndef(p: var TParser): PNode = - result = ast.emptyNode - getTok(p) # skip #ifndef - expectIdent(p) - if p.tok.s == c2nimSymbol: - skipLine(p) - case skipUntilElifElseEndif(p) - of emElif: - result = newNodeP(nkWhenStmt, p) - addSon(result, newNodeP(nkElifBranch, p)) - getTok(p) - addSon(result.sons[0], expression(p)) - eatNewLine(p, nil) - parseIfDirAux(p, result) - of emElse: - skipLine(p) - result = parseStmtList(p) - eatEndif(p) - of emEndif: skipLine(p) - else: - result = newNodeP(nkWhenStmt, p) - addSon(result, newNodeP(nkElifBranch, p)) - var e = newNodeP(nkCall, p) - addSon(e, newIdentNodeP("not", p)) - addSon(e, definedExprAux(p)) - eatNewLine(p, nil) - addSon(result.sons[0], e) - parseIfDirAux(p, result) - -proc parseIfDir(p: var TParser): PNode = - result = newNodeP(nkWhenStmt, p) - addSon(result, newNodeP(nkElifBranch, p)) - getTok(p) - addSon(result.sons[0], expression(p)) - eatNewLine(p, nil) - parseIfDirAux(p, result) - -proc parsePegLit(p: var TParser): TPeg = - var col = getColumn(p.lex) + 2 - getTok(p) - if p.tok.xkind != pxStrLit: expectIdent(p) - try: - result = parsePeg( - pattern = if p.tok.xkind == pxStrLit: p.tok.s else: escapePeg(p.tok.s), - filename = p.lex.fileIdx.toFilename, - line = p.lex.linenumber, - col = col) - getTok(p) - except EInvalidPeg: - parMessage(p, errUser, getCurrentExceptionMsg()) - -proc parseMangleDir(p: var TParser) = - var pattern = parsePegLit(p) - if p.tok.xkind != pxStrLit: expectIdent(p) - p.options.mangleRules.add((pattern, p.tok.s)) - getTok(p) - eatNewLine(p, nil) - -proc modulePragmas(p: var TParser): PNode = - if p.options.dynlibSym.len > 0 and not p.hasDeadCodeElimPragma: - p.hasDeadCodeElimPragma = true - result = newNodeP(nkPragma, p) - var e = newNodeP(nkExprColonExpr, p) - addSon(e, newIdentNodeP("deadCodeElim", p), newIdentNodeP("on", p)) - addSon(result, e) - else: - result = ast.emptyNode - -proc parseDir(p: var TParser): PNode = - result = ast.emptyNode - assert(p.tok.xkind in {pxDirective, pxDirectiveParLe}) - case p.tok.s - of "define": result = parseDefine(p) - of "include": result = parseInclude(p) - of "ifdef": result = parseIfdef(p) - of "ifndef": result = parseIfndef(p) - of "if": result = parseIfDir(p) - of "cdecl", "stdcall", "ref", "skipinclude", "typeprefixes", "skipcomments": - discard setOption(p.options, p.tok.s) - getTok(p) - eatNewLine(p, nil) - of "dynlib", "header", "prefix", "suffix", "class": - var key = p.tok.s - getTok(p) - if p.tok.xkind != pxStrLit: expectIdent(p) - discard setOption(p.options, key, p.tok.s) - getTok(p) - eatNewLine(p, nil) - result = modulePragmas(p) - of "mangle": - parseMangleDir(p) - of "def": - var L = p.options.macros.len - setLen(p.options.macros, L+1) - parseDef(p, p.options.macros[L]) - of "private": - var pattern = parsePegLit(p) - p.options.privateRules.add(pattern) - eatNewLine(p, nil) - else: - # ignore unimportant/unknown directive ("undef", "pragma", "error") - skipLine(p) - diff --git a/compiler/c2nim/nimrod.cfg b/compiler/c2nim/nimrod.cfg deleted file mode 100644 index cfeda63ed6..0000000000 --- a/compiler/c2nim/nimrod.cfg +++ /dev/null @@ -1,4 +0,0 @@ -# Use the modules of the compiler - -path: "$nimrod/compiler" - diff --git a/compiler/c2nim/tests/enum.h b/compiler/c2nim/tests/enum.h deleted file mode 100644 index 16bc59058f..0000000000 --- a/compiler/c2nim/tests/enum.h +++ /dev/null @@ -1,40 +0,0 @@ - -enum vehicles -{ - car = 0x10, - truck, - boat = 0x01, - ship = 1, - speedboat = 1, - bicycle = 4, - bobycar -}; - -enum -{ - red = 4, - green = 2, - blue -}; - -typedef enum food -{ - bread = 4, - toast = 4, - bun = 0x04, - cucumber = 2, - chocolate = 6 -}; - -typedef enum numbers -{ - one = 1, - two, - nten = - 10, - nnine, - four = 4, - three = + 3, - positivenine = + 9, - nfour = - 4, - negativeten = -10 -}; \ No newline at end of file diff --git a/compiler/c2nim/tests/matrix.h b/compiler/c2nim/tests/matrix.h deleted file mode 100644 index 715e9e43b2..0000000000 --- a/compiler/c2nim/tests/matrix.h +++ /dev/null @@ -1,240 +0,0 @@ -///////////////////////////////////////////////////////////////////////////// -// Name: wx/matrix.h -// Purpose: wxTransformMatrix class. NOT YET USED -// Author: Chris Breeze, Julian Smart -// Modified by: Klaas Holwerda -// Created: 01/02/97 -// RCS-ID: $Id$ -// Copyright: (c) Julian Smart, Chris Breeze -// Licence: wxWindows licence -///////////////////////////////////////////////////////////////////////////// - -#ifndef _WX_MATRIXH__ -#define _WX_MATRIXH__ - -//! headerfiles="matrix.h wx/object.h" -#include "wx/object.h" -#include "wx/math.h" - -//! codefiles="matrix.cpp" - -// A simple 3x3 matrix. This may be replaced by a more general matrix -// class some day. -// -// Note: this is intended to be used in wxDC at some point to replace -// the current system of scaling/translation. It is not yet used. - -#def WXDLLIMPEXP_CORE -#header "wxmatrix.h" - -//:definition -// A 3x3 matrix to do 2D transformations. -// It can be used to map data to window coordinates, -// and also for manipulating your own data. -// For example drawing a picture (composed of several primitives) -// at a certain coordinate and angle within another parent picture. -// At all times m_isIdentity is set if the matrix itself is an Identity matrix. -// It is used where possible to optimize calculations. -class WXDLLIMPEXP_CORE wxTransformMatrix: public wxObject> -{ -public: - wxTransformMatrix(void); - wxTransformMatrix(const wxTransformMatrix& mat); - - ~wxTransformMatrix(void); - - //get the value in the matrix at col,row - //rows are horizontal (second index of m_matrix member) - //columns are vertical (first index of m_matrix member) - double GetValue(int col, int row) const; - - //set the value in the matrix at col,row - //rows are horizontal (second index of m_matrix member) - //columns are vertical (first index of m_matrix member) - void SetValue(int col, int row, double value); - - void operator = (const wxTransformMatrix& mat); - bool operator == (const wxTransformMatrix& mat) const; - bool operator != (const module::gah::wxTransformMatrix& mat) const; - - //multiply every element by t - wxTransformMatrix& operator*=(const double& t); - //divide every element by t - wxTransformMatrix& operator/=(const double& t); - //add matrix m to this t - wxTransformMatrix& operator+=(const wxTransformMatrix& m); - //subtract matrix m from this - wxTransformMatrix& operator-=(const wxTransformMatrix& m); - //multiply matrix m with this - wxTransformMatrix& operator*=(const wxTransformMatrix& m); - - // constant operators - - //multiply every element by t and return result - wxTransformMatrix operator*(const double& t) const; - //divide this matrix by t and return result - wxTransformMatrix operator/(const double& t) const; - //add matrix m to this and return result - wxTransformMatrix operator+(const wxTransformMatrix& m) const; - //subtract matrix m from this and return result - wxTransformMatrix operator-(const wxTransformMatrix& m) const; - //multiply this by matrix m and return result - wxTransformMatrix operator*(const wxTransformMatrix& m) const; - wxTransformMatrix operator-() const; - - //rows are horizontal (second index of m_matrix member) - //columns are vertical (first index of m_matrix member) - double& operator()(int col, int row); - - //rows are horizontal (second index of m_matrix member) - //columns are vertical (first index of m_matrix member) - double operator()(int col, int row) const; - - // Invert matrix - bool Invert(void); - - // Make into identity matrix - bool Identity(void); - - // Is the matrix the identity matrix? - // Only returns a flag, which is set whenever an operation - // is done. - inline bool IsIdentity(void) const { return m_isIdentity; } - - // This does an actual check. - inline bool IsIdentity1(void) const ; - - //Scale by scale (isotropic scaling i.e. the same in x and y): - //!ex: - //!code: | scale 0 0 | - //!code: matrix' = | 0 scale 0 | x matrix - //!code: | 0 0 scale | - bool Scale(double scale); - - //Scale with center point and x/y scale - // - //!ex: - //!code: | xs 0 xc(1-xs) | - //!code: matrix' = | 0 ys yc(1-ys) | x matrix - //!code: | 0 0 1 | - wxTransformMatrix& Scale(const double &xs, const double &ys,const double &xc, const double &yc); - - // mirror a matrix in x, y - //!ex: - //!code: | -1 0 0 | - //!code: matrix' = | 0 -1 0 | x matrix - //!code: | 0 0 1 | - wxTransformMatrix& Mirror(bool x=true, bool y=false); - // Translate by dx, dy: - //!ex: - //!code: | 1 0 dx | - //!code: matrix' = | 0 1 dy | x matrix - //!code: | 0 0 1 | - bool Translate(double x, double y); - - // Rotate clockwise by the given number of degrees: - //!ex: - //!code: | cos sin 0 | - //!code: matrix' = | -sin cos 0 | x matrix - //!code: | 0 0 1 | - bool Rotate(double angle); - - //Rotate counter clockwise with point of rotation - // - //!ex: - //!code: | cos(r) -sin(r) x(1-cos(r))+y(sin(r)| - //!code: matrix' = | sin(r) cos(r) y(1-cos(r))-x(sin(r)| x matrix - //!code: | 0 0 1 | - wxTransformMatrix& Rotate(const double &r, const double &x, const double &y); - - // Transform X value from logical to device - inline double TransformX(double x) const; - - // Transform Y value from logical to device - inline double TransformY(double y) const; - - // Transform a point from logical to device coordinates - bool TransformPoint(double x, double y, double& tx, double& ty) const; - - // Transform a point from device to logical coordinates. - // Example of use: - // wxTransformMatrix mat = dc.GetTransformation(); - // mat.Invert(); - // mat.InverseTransformPoint(x, y, x1, y1); - // OR (shorthand:) - // dc.LogicalToDevice(x, y, x1, y1); - // The latter is slightly less efficient if we're doing several - // conversions, since the matrix is inverted several times. - // N.B. 'this' matrix is the inverse at this point - bool InverseTransformPoint(double x, double y, double& tx, double& ty) const; - - double Get_scaleX(); - double Get_scaleY(); - double GetRotation(); - void SetRotation(double rotation); - - -public: - double m_matrix[3][3]; - bool m_isIdentity; -}; - - -/* -Chris Breeze reported, that -some functions of wxTransformMatrix cannot work because it is not -known if he matrix has been inverted. Be careful when using it. -*/ - -// Transform X value from logical to device -// warning: this function can only be used for this purpose -// because no rotation is involved when mapping logical to device coordinates -// mirror and scaling for x and y will be part of the matrix -// if you have a matrix that is rotated, eg a shape containing a matrix to place -// it in the logical coordinate system, use TransformPoint -inline double wxTransformMatrix::TransformX(double x) const -{ - //normally like this, but since no rotation is involved (only mirror and scale) - //we can do without Y -> m_matrix[1]{0] is -sin(rotation angle) and therefore zero - //(x * m_matrix[0][0] + y * m_matrix[1][0] + m_matrix[2][0])) - return (m_isIdentity ? x : (x * m_matrix[0][0] + m_matrix[2][0])); -} - -// Transform Y value from logical to device -// warning: this function can only be used for this purpose -// because no rotation is involved when mapping logical to device coordinates -// mirror and scaling for x and y will be part of the matrix -// if you have a matrix that is rotated, eg a shape containing a matrix to place -// it in the logical coordinate system, use TransformPoint -inline double wxTransformMatrix::TransformY(double y) const -{ - //normally like this, but since no rotation is involved (only mirror and scale) - //we can do without X -> m_matrix[0]{1] is sin(rotation angle) and therefore zero - //(x * m_matrix[0][1] + y * m_matrix[1][1] + m_matrix[2][1])) - return (m_isIdentity ? y : (y * m_matrix[1][1] + m_matrix[2][1])); -} - - -// Is the matrix the identity matrix? -// Each operation checks whether the result is still the identity matrix and sets a flag. -inline bool wxTransformMatrix::IsIdentity1(void) const -{ - return - ( wxIsSameDouble(m_matrix[0][0], 1.0) && - wxIsSameDouble(m_matrix[1][1], 1.0) && - wxIsSameDouble(m_matrix[2][2], 1.0) && - wxIsSameDouble(m_matrix[1][0], 0.0) && - wxIsSameDouble(m_matrix[2][0], 0.0) && - wxIsSameDouble(m_matrix[0][1], 0.0) && - wxIsSameDouble(m_matrix[2][1], 0.0) && - wxIsSameDouble(m_matrix[0][2], 0.0) && - wxIsSameDouble(m_matrix[1][2], 0.0) ); -} - -// Calculates the determinant of a 2 x 2 matrix -inline double wxCalculateDet(double a11, double a21, double a12, double a22) -{ - return a11 * a22 - a12 * a21; -} - -#endif // _WX_MATRIXH__ diff --git a/compiler/c2nim/tests/struct_anonym.h b/compiler/c2nim/tests/struct_anonym.h deleted file mode 100644 index 859bfc206f..0000000000 --- a/compiler/c2nim/tests/struct_anonym.h +++ /dev/null @@ -1,27 +0,0 @@ - -struct normal{ - int a; - int b; -}; - -typedef struct outerStruct { - struct normal a_nomal_one; - - int a; - - struct { - union { - int b; - } a_union_in_the_struct; - - int c; - }; - - union { - int d; - - struct { - int e; - } a_struct_in_the_union; - } a_union; -}; \ No newline at end of file diff --git a/compiler/c2nim/tests/systest.c b/compiler/c2nim/tests/systest.c deleted file mode 100644 index 51509e253b..0000000000 --- a/compiler/c2nim/tests/systest.c +++ /dev/null @@ -1,622 +0,0 @@ -/* This file has been written by Blablub. - * - * Another comment line. - */ - -#ifdef __cplusplus -# ifdef __SOME_OTHER_CRAP -extern "C" { -# endif -#endif - -#define interrupts() sei() - -enum -{ -/* 8bit, color or not */ - CV_LOAD_IMAGE_UNCHANGED =-1, -/* 8bit, gray */ - CV_LOAD_IMAGE_GRAYSCALE =0, -/* ?, color */ - CV_LOAD_IMAGE_COLOR =1, -/* any depth, ? */ - CV_LOAD_IMAGE_ANYDEPTH =2, -/* ?, any color */ - CV_LOAD_IMAGE_ANYCOLOR =4 -}; - -typedef void (*callback_t) (int rc); -typedef const char* (*callback2)(int rc, long L, const char* buffer); - -int aw_callback_set (AW_CALLBACK c, callback_t callback ); -int aw_instance_callback_set (AW_CALLBACK c, callback_t callback); - -unsigned long int wawa; - -#define MAX(x, y) ((x) < (y)? (y) : (x)) - -#define AW_BUILD 85 // AW 5.0 -// Limits -#define AW_MAX_AVCHANGE_PER_SECOND 10 - -#private expatDll - -#if !defined(expatDll) -# if defined(windows) -# define expatDll "expat.dll" -# elif defined(macosx) -# define expatDll "libexpat.dynlib" -# else -# define expatDll "libexpat.so(.1|)" -# endif -#endif - -#mangle "'XML_'{.*}" "$1" -#private "'XML_ParserStruct'" - -#mangle cuint cint - -unsigned int uiVar; - -#private "@('_'!.)" -unsigned int myPrivateVar__; - - -struct XML_ParserStruct; - -#def XMLCALL __cdecl - -typedef void (XMLCALL *XML_ElementDeclHandler) (void *userData, - const XML_Char *name, - XML_Content *model); - - -void* x; -void* fn(void); -void (*fn)(void); -void* (*fn)(void); -void* (*fn)(void*); - -/* - * Very ugly real world code ahead: - */ - -#def JMETHOD(rettype, name, params) rettype (*name) params - -typedef struct cjpeg_source_struct * cjpeg_source_ptr; - -struct cjpeg_source_struct { - JMETHOD(void, start_input, (j_compress_ptr cinfo, - cjpeg_source_ptr sinfo)); - JMETHOD(JDIMENSION, get_pixel_rows, (j_compress_ptr cinfo, - cjpeg_source_ptr sinfo)); - JMETHOD(void, finish_input, (j_compress_ptr cinfo, - cjpeg_source_ptr sinfo)); - - FILE *input_file; - - JSAMPARRAY buffer; - JDIMENSION buffer_height; -}; - -// Test standalone structs: - -union myunion { - char x, y, *z; - myint a, b; -} u; - -struct mystruct { - char x, y, *z; - myint a, b; -}; - -struct mystruct fn(i32 x, i64 y); - -struct mystruct { - char x, y, *z; - myint a, b; -} *myvar = NULL, **myvar2 = NULL; - -// anonymous struct: - -struct { - char x, y, *z; - myint a, b; -} varX, **varY; - -// empty anonymous struct: - -struct { - -} varX, **varY; - -// Test C2NIM skipping: - -#define MASK(x) ((x) & 0xff) -#define CAST1(x) ((int) &x) -#define CAST2(x) (typ*) &x -#define CAST3(x) ((const unsigned char**) &x) - -#ifndef C2NIM - #if someNestedCond - This is an invalid text that should generate a parser error, if not - #endif - skipped correctly. -#endif - -#ifndef C2NIM - #if someNestedCond - This is an invalid text that should generate a parser error, if not - #endif - skipped correctly. -#else -typedef char gchar; -typedef unsigned int gunsignedint; -typedef unsigned char guchar; -#endif - -#ifdef C2NIM -# mangle "'those'" "these" -int those; -#elif abc - #if someNestedCond - This is an invalid text that should generate a parser error, if not - #else - skipped correctly. - #endif -#else - Another crappy input line. -#endif - -point* newPoint(void) { - for (int i = 0; i < 89; ++i) echo("test" " string " "concatenation"); - for (; j < 54; j++) {} - for (;; j--) ; - for (;;) {} - mytype * x = y * z; - - if (**p == ' ') { - --p; - } else if (**p == '\t') { - p += 3; - } else { - p = 45 + (mytype*)45; - p = 45 + ((mytype*)45); - p = 45 + ((mytype)45); - // BUG: This does not parse: - // p = 45 + (mytype)45; - } - - while (x >= 6 && x <= 20) - --x; - - switch (*p) { - case 'A'...'Z': - case 'a'...'z': - ++p; - break; - case '0': - ++p; - break; - default: - return NULL; - } -} - -enum { - a1, a2 = 4, a3 -}; - -typedef enum crazyTAG { - x1, x2, x3 = 8, x4, x5 -} myEnum, *pMyEnum; - -typedef enum { - x1, x2, x3 = 8, x4, x5 -} myEnum, *pMyEnum; - -// Test multi-line macro: - -#define MUILTILINE "abc" \ - "xyz" \ - "def" - -#define MULTILINE(x, y) do { \ - ++y; ++x; \ -} while (0) - -#ifdef C2NIM -# dynlib iupdll -# cdecl -# mangle "'GTK_'{.*}" "TGtk$1" -# mangle "'PGTK_'{.*}" "PGtk$1" -# if defined(windows) -# define iupdll "iup.dll" -# elif defined(macosx) -# define iupdll "libiup.dynlib" -# else -# define iupdll "libiup.so" -# endif -#endif - -typedef struct stupidTAG { - mytype a, b; -} GTK_MyStruct, *PGTK_MyStruct; - -typedef struct { - mytype a, b; -} GTK_MyStruct, *PGTK_MyStruct; - -int IupConvertXYToPos(PIhandle ih, int x, int y); - -#ifdef DEBUG -# define OUT(x) printf("%s\n", x) -#else -# define OUT(x) -#endif - - - #ifdef C2NIM - # def EXTERN(x) static x - # def TWO_ARGS(x, y) x* y - #endif - // parses now! - EXTERN(int) f(void); - EXTERN(int) g(void); - - - #def EXPORT - // does parse now! - EXPORT int f(void); - EXPORT int g(void); - - static TWO_ARGS(int, x) = TWO_ARGS(56, 45); - - -# define abc 34 -# define xyz 42 - -# define wuseldusel "my string\nconstant" - -#undef ignoreThis - -char* x; - -typedef struct { - char x, y, *z; -} point; - -char* __stdcall printf(char* frmt, const char* const** ptrToStrArray, - const int* const dummy, ...); - -inline char* myinlineProc(char* frmt, const char* const* strArray, - const int* const dummy, ...); - -// Test void parameter list: -void myVoidProc(void); - -void emptyReturn(void) { return; } - -// POSIX stuff: - -#ifdef C2NIM -#prefix posix_ -int c2nimBranch; -#elif defined(MACOSX) -int* x, y, z; -#else -int dummy; -#endif - -#ifndef C2NIM -int dontTranslateThis; -#elif defined(Windows) -int WindowsTrue = true; -#endif - -int posix_spawn(pid_t *restrict, const char *restrict, - const posix_spawn_file_actions_t *, - const posix_spawnattr_t *restrict, char *const [restrict], - char *const [restrict]); -int posix_spawn_file_actions_addclose(posix_spawn_file_actions_t *, - int); -int posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t *, - int, int); -int posix_spawn_file_actions_addopen(posix_spawn_file_actions_t *restrict, - int, const char *restrict, int, mode_t); -int posix_spawn_file_actions_destroy(posix_spawn_file_actions_t *); -int posix_spawn_file_actions_init(posix_spawn_file_actions_t *); -int posix_spawnattr_destroy(posix_spawnattr_t *); -int posix_spawnattr_getsigdefault(const posix_spawnattr_t *restrict, - sigset_t *restrict); -int posix_spawnattr_getflags(const posix_spawnattr_t *restrict, - short *restrict); -int posix_spawnattr_getpgroup(const posix_spawnattr_t *restrict, - pid_t *restrict); -int posix_spawnattr_getschedparam(const posix_spawnattr_t *restrict, - struct sched_param *restrict); -int posix_spawnattr_getschedpolicy(const posix_spawnattr_t *restrict, - int *restrict); -int posix_spawnattr_getsigmask(const posix_spawnattr_t *restrict, - sigset_t *restrict); -int posix_spawnattr_init(posix_spawnattr_t *); -int posix_spawnattr_setsigdefault(posix_spawnattr_t *restrict, - const sigset_t *restrict); -int posix_spawnattr_setflags(posix_spawnattr_t *, short); -int posix_spawnattr_setpgroup(posix_spawnattr_t *, pid_t); - - -int posix_spawnattr_setschedparam(posix_spawnattr_t *restrict, - const struct sched_param *restrict); -int posix_spawnattr_setschedpolicy(posix_spawnattr_t *, int); -int posix_spawnattr_setsigmask(posix_spawnattr_t *restrict, - const sigset_t *restrict); -int posix_spawnp(pid_t *restrict, const char *restrict, - const posix_spawn_file_actions_t *, - const posix_spawnattr_t *restrict, - char *const [restrict], char *const [restrict]); - -typedef struct -{ - float R, G, B; -} -RGBType; -typedef struct -{ - float H, W, B; -} -HWBType; - -static HWBType * -RGB_to_HWB (RGBType RGB, HWBType * HWB) -{ - HWBType* myArray[20]; - /* - * RGB are each on [0, 1]. W and B are returned on [0, 1] and H is - * returned on [0, 6]. Exception: H is returned UNDEFINED if W == 1 - B. - */ - - float R = RGB.R, G = RGB.G, B = RGB.B, w, v, b, f; - int i; - - w = MIN3 (R, G, B); - v = MAX3 (R, G, B); - b &= 1 - v; - if (v == w) - RETURN_HWB (HWB_UNDEFINED, w, b); - f = (R == w) ? G - B : ((G == w) ? B - R : R - G); - i = (R == w) ? 3 : ((G == w) ? 5 : 1); - RETURN_HWB (i - f / (v - w), w, b); - -} - -static int -clip_1d (int *x0, int *y0, int *x1, int *y1, int mindim, int maxdim) -{ - double m; // gradient of line - if (*x0 < mindim) - { // start of line is left of window - if (*x1 < mindim) // as is the end, so the line never cuts the window - return 0; - m = (*y1 - *y0) / (double) (*x1 - *x0); // calculate the slope of the line - // adjust x0 to be on the left boundary (ie to be zero), and y0 to match - *y0 -= m * (*x0 - mindim); - *x0 = mindim; - // now, perhaps, adjust the far end of the line as well - if (*x1 > maxdim) - { - *y1 += m * (maxdim - *x1); - *x1 = maxdim; - } - return 1; - } - if (*x0 > maxdim) - { // start of line is right of window - complement of above - if (*x1 > maxdim) // as is the end, so the line misses the window - return 0; - m = (*y1 - *y0) / (double) (*x1 - *x0); // calculate the slope of the line - *y0 += m * (maxdim - *x0); // adjust so point is on the right - // boundary - *x0 = maxdim; - // now, perhaps, adjust the end of the line - if (*x1 < mindim) - { - *y1 -= m * (*x1 - mindim); - *x1 = mindim; - } - return 1; - } - // the final case - the start of the line is inside the window - if (*x1 > maxdim) - { // other end is outside to the right - m = (*y1 - *y0) / (double) (*x1 - *x0); // calculate the slope of the line - *y1 += m * (maxdim - *x1); - *x1 = maxdim; - return 1; - } - if (*x1 < mindim) - { // other end is outside to the left - m = (*y1 - *y0) / (double) (*x1 - *x0); // calculate the slope of line - *y1 -= m * (*x1 - mindim); - *x1 = mindim; - return 1; - } - // only get here if both points are inside the window - return 1; -} - -// end of line clipping code - -static void -gdImageBrushApply (gdImagePtr im, int x, int y) -{ - int lx, ly; - int hy; - int hx; - int x1, y1, x2, y2; - int srcx, srcy; - if (!im->brush) - { - return; - } - hy = gdImageSY (im->brush) / 2; - y1 = y - hy; - y2 = y1 + gdImageSY (im->brush); - hx = gdImageSX (im->brush) / 2; - x1 = x - hx; - x2 = x1 + gdImageSX (im->brush); - srcy = 0; - if (im->trueColor) - { - if (im->brush->trueColor) - { - for (ly = y1; (ly < y2); ly++) - { - srcx = 0; - for (lx = x1; (lx < x2); lx++) - { - int p; - p = gdImageGetTrueColorPixel (im->brush, srcx, srcy); - // 2.0.9, Thomas Winzig: apply simple full transparency - if (p != gdImageGetTransparent (im->brush)) - { - gdImageSetPixel (im, lx, ly, p); - } - srcx++; - } - srcy++; - } - } - else - { - // 2.0.12: Brush palette, image truecolor (thanks to Thorben Kundinger - // for pointing out the issue) - for (ly = y1; (ly < y2); ly++) - { - srcx = 0; - for (lx = x1; (lx < x2); lx++) - { - int p, tc; - p = gdImageGetPixel (im->brush, srcx, srcy); - tc = gdImageGetTrueColorPixel (im->brush, srcx, srcy); - // 2.0.9, Thomas Winzig: apply simple full transparency - if (p != gdImageGetTransparent (im->brush)) - { - gdImageSetPixel (im, lx, ly, tc); - } - srcx++; - } - srcy++; - } - } - } - else - { - for (ly = y1; (ly < y2); ly++) - { - srcx = 0; - for (lx = x1; (lx < x2); lx++) - { - int p; - p = gdImageGetPixel (im->brush, srcx, srcy); - // Allow for non-square brushes! - if (p != gdImageGetTransparent (im->brush)) - { - // Truecolor brush. Very slow - // on a palette destination. - if (im->brush->trueColor) - { - gdImageSetPixel (im, lx, ly, - gdImageColorResolveAlpha(im, - gdTrueColorGetRed(p), - gdTrueColorGetGreen(p), - gdTrueColorGetBlue(p), - gdTrueColorGetAlpha(p))); - } - else - { - gdImageSetPixel (im, lx, ly, im->brushColorMap[p]); - } - } - srcx++; - } - srcy++; - } - } -} - - -void gdImageSetPixel (gdImagePtr im, int x, int y, int color) -{ - int p; - switch (color) - { - case gdStyled: - if (!im->style) - { - // Refuse to draw if no style is set. - return; - } - else - { - p = im->style[im->stylePos++]; - } - if (p != (gdTransparent)) - { - gdImageSetPixel (im, x, y, p); - } - im->stylePos = im->stylePos % im->styleLength; - break; - case gdStyledBrushed: - if (!im->style) - { - // Refuse to draw if no style is set. - return; - } - p = im->style[im->stylePos++]; - if ((p != gdTransparent) && (p != 0)) - { - gdImageSetPixel (im, x, y, gdBrushed); - } - im->stylePos = im->stylePos % im->styleLength; - break; - case gdBrushed: - gdImageBrushApply (im, x, y); - break; - case gdTiled: - gdImageTileApply (im, x, y); - break; - case gdAntiAliased: - // This shouldn't happen (2.0.26) because we just call - // gdImageAALine now, but do something sane. - gdImageSetPixel(im, x, y, im->AA_color); - break; - default: - if (gdImageBoundsSafeMacro (im, x, y)) - { - if (im->trueColor) - { - if (im->alphaBlendingFlag) - { - im->tpixels[y][x] = gdAlphaBlend (im->tpixels[y][x], color); - } - else - { - im->tpixels[y][x] = color; - } - } - else - { - im->pixels[y][x] = color; - } - } - break; - } -} - -#ifdef __cplusplus -} -#endif - - diff --git a/compiler/c2nim/tests/systest2.c b/compiler/c2nim/tests/systest2.c deleted file mode 100644 index bf3027cfcf..0000000000 --- a/compiler/c2nim/tests/systest2.c +++ /dev/null @@ -1,17 +0,0 @@ -#ifdef C2NIM -# header "iup.h" -# cdecl -# mangle "'GTK_'{.*}" "TGtk$1" -# mangle "'PGTK_'{.*}" "PGtk$1" -#endif - -typedef struct stupidTAG { - mytype a, b; -} GTK_MyStruct, *PGTK_MyStruct; - -typedef struct { - mytype a, b; -} GTK_MyStruct, *PGTK_MyStruct; - -int IupConvertXYToPos(PIhandle ih, int x, int y); - diff --git a/compiler/c2nim/tests/vincent.c b/compiler/c2nim/tests/vincent.c deleted file mode 100644 index 24c6d6425f..0000000000 --- a/compiler/c2nim/tests/vincent.c +++ /dev/null @@ -1,33 +0,0 @@ -#include -#include - -int rand(void); - -int id2(void) { - return (int *)1; -} - -int id(void (*f)(void)) { - f(); - ((void (*)(int))f)(10); - return 10; - return (20+1); - return (int *)id; -} - -int main() { - float f = .2, - g = 2., - h = 1.0+rand(), - i = 1.0e+3; - int j, a; - for(j = 0, a = 10; j < 0; j++, a++) ; - do { - printf("howdy"); - } while(--i, 0); - if(1) - printf("1"); // error from this comment - else - printf("2"); - return '\x00'; -} diff --git a/compiler/c2nim/tests/vincent.h b/compiler/c2nim/tests/vincent.h deleted file mode 100644 index b4e761ee14..0000000000 --- a/compiler/c2nim/tests/vincent.h +++ /dev/null @@ -1,3 +0,0 @@ -struct foo { - int x,y,z; -}; diff --git a/compiler/pas2nim/nimrod.cfg b/compiler/pas2nim/nimrod.cfg deleted file mode 100644 index cfeda63ed6..0000000000 --- a/compiler/pas2nim/nimrod.cfg +++ /dev/null @@ -1,4 +0,0 @@ -# Use the modules of the compiler - -path: "$nimrod/compiler" - diff --git a/compiler/pas2nim/pas2nim.nim b/compiler/pas2nim/pas2nim.nim deleted file mode 100644 index d100281670..0000000000 --- a/compiler/pas2nim/pas2nim.nim +++ /dev/null @@ -1,64 +0,0 @@ -# -# -# Pas2nim - Pascal to Nimrod source converter -# (c) Copyright 2012 Andreas Rumpf -# -# See the file "copying.txt", included in this -# distribution, for details about the copyright. -# - -import - strutils, os, parseopt, llstream, ast, renderer, options, msgs, - paslex, pasparse - -const - Version = "0.8" - Usage = """ -pas2nim - Pascal to Nimrod source converter - (c) 2012 Andreas Rumpf -Usage: pas2nim [options] inputfile [options] -Options: - -o, --out:FILE set output filename - --ref convert ^typ to ref typ (default: ptr typ) - --boot use special translation rules for the Nimrod compiler - -v, --version write pas2nim's version - -h, --help show this help -""" - -proc main(infile, outfile: string, flags: set[TParserFlag]) = - var stream = llStreamOpen(infile, fmRead) - if stream == nil: rawMessage(errCannotOpenFile, infile) - var p: TParser - openParser(p, infile, stream, flags) - var module = parseUnit(p) - closeParser(p) - renderModule(module, outfile) - -var - infile = "" - outfile = "" - flags: set[TParserFlag] = {} -for kind, key, val in getopt(): - case kind - of cmdArgument: infile = key - of cmdLongOption, cmdShortOption: - case key - of "help", "h": - stdout.write(Usage) - quit(0) - of "version", "v": - stdout.write(Version & "\n") - quit(0) - of "o", "out": outfile = val - of "ref": incl(flags, pfRefs) - of "boot": flags = flags + {pfRefs, pfMoreReplacements, pfImportBlackList} - else: stdout.writeln("[Error] unknown option: " & key) - of cmdEnd: assert(false) -if infile.len == 0: - # no filename has been given, so we show the help: - stdout.write(Usage) -else: - if outfile.len == 0: - outfile = changeFileExt(infile, "nim") - infile = addFileExt(infile, "pas") - main(infile, outfile, flags) diff --git a/compiler/pas2nim/paslex.nim b/compiler/pas2nim/paslex.nim deleted file mode 100644 index f24b0c420a..0000000000 --- a/compiler/pas2nim/paslex.nim +++ /dev/null @@ -1,570 +0,0 @@ -# -# -# Pas2nim - Pascal to Nimrod source converter -# (c) Copyright 2012 Andreas Rumpf -# -# See the file "copying.txt", included in this -# distribution, for details about the copyright. -# - -# This module implements a FreePascal scanner. This is an adaption from -# the scanner module. - -import - hashes, options, msgs, strutils, platform, idents, nimlexbase, llstream - -const - MaxLineLength* = 80 # lines longer than this lead to a warning - numChars*: TCharSet = {'0'..'9', 'a'..'z', 'A'..'Z'} - SymChars*: TCharSet = {'a'..'z', 'A'..'Z', '0'..'9', '\x80'..'\xFF'} - SymStartChars*: TCharSet = {'a'..'z', 'A'..'Z', '\x80'..'\xFF'} - OpChars*: TCharSet = {'+', '-', '*', '/', '<', '>', '!', '?', '^', '.', '|', - '=', ':', '%', '&', '$', '@', '~', '\x80'..'\xFF'} - -# keywords are sorted! - -type - TTokKind* = enum - pxInvalid, pxEof, - pxAnd, pxArray, pxAs, pxAsm, pxBegin, pxCase, pxClass, pxConst, - pxConstructor, pxDestructor, pxDiv, pxDo, pxDownto, pxElse, pxEnd, pxExcept, - pxExports, pxFinalization, pxFinally, pxFor, pxFunction, pxGoto, pxIf, - pxImplementation, pxIn, pxInherited, pxInitialization, pxInline, - pxInterface, pxIs, pxLabel, pxLibrary, pxMod, pxNil, pxNot, pxObject, pxOf, - pxOr, pxOut, pxPacked, pxProcedure, pxProgram, pxProperty, pxRaise, - pxRecord, pxRepeat, pxResourcestring, pxSet, pxShl, pxShr, pxThen, - pxThreadvar, pxTo, pxTry, pxType, pxUnit, pxUntil, pxUses, pxVar, pxWhile, - pxWith, pxXor, - pxComment, # ordinary comment - pxCommand, # {@} - pxAmp, # {&} - pxPer, # {%} - pxStrLit, pxSymbol, # a symbol - pxIntLit, pxInt64Lit, # long constant like 0x70fffffff or out of int range - pxFloatLit, pxParLe, pxParRi, pxBracketLe, pxBracketRi, pxComma, - pxSemiColon, pxColon, # operators - pxAsgn, pxEquals, pxDot, pxDotDot, pxHat, pxPlus, pxMinus, pxStar, pxSlash, - pxLe, pxLt, pxGe, pxGt, pxNeq, pxAt, pxStarDirLe, pxStarDirRi, pxCurlyDirLe, - pxCurlyDirRi - TTokKinds* = set[TTokKind] - -const - Keywords = ["and", "array", "as", "asm", "begin", "case", "class", "const", - "constructor", "destructor", "div", "do", "downto", "else", "end", "except", - "exports", "finalization", "finally", "for", "function", "goto", "if", - "implementation", "in", "inherited", "initialization", "inline", - "interface", "is", "label", "library", "mod", "nil", "not", "object", "of", - "or", "out", "packed", "procedure", "program", "property", "raise", - "record", "repeat", "resourcestring", "set", "shl", "shr", "then", - "threadvar", "to", "try", "type", "unit", "until", "uses", "var", "while", - "with", "xor"] - - firstKeyword = pxAnd - lastKeyword = pxXor - -type - TNumericalBase* = enum base10, base2, base8, base16 - TToken* = object - xkind*: TTokKind # the type of the token - ident*: PIdent # the parsed identifier - iNumber*: BiggestInt # the parsed integer literal - fNumber*: BiggestFloat # the parsed floating point literal - base*: TNumericalBase # the numerical base; only valid for int - # or float literals - literal*: string # the parsed (string) literal - - TLexer* = object of TBaseLexer - filename*: string - - -proc getTok*(L: var TLexer, tok: var TToken) -proc printTok*(tok: TToken) -proc `$`*(tok: TToken): string -# implementation - -var - dummyIdent: PIdent - gLinesCompiled: int - -proc fillToken(L: var TToken) = - L.xkind = pxInvalid - L.iNumber = 0 - L.literal = "" - L.fNumber = 0.0 - L.base = base10 - L.ident = dummyIdent # this prevents many bugs! - -proc openLexer*(lex: var TLexer, filename: string, inputstream: PLLStream) = - openBaseLexer(lex, inputstream) - lex.filename = filename - -proc closeLexer*(lex: var TLexer) = - inc(gLinesCompiled, lex.LineNumber) - closeBaseLexer(lex) - -proc getColumn(L: TLexer): int = - result = getColNumber(L, L.bufPos) - -proc getLineInfo*(L: TLexer): TLineInfo = - result = newLineInfo(L.filename, L.linenumber, getColNumber(L, L.bufpos)) - -proc lexMessage*(L: TLexer, msg: TMsgKind, arg = "") = - msgs.globalError(getLineInfo(L), msg, arg) - -proc lexMessagePos(L: var TLexer, msg: TMsgKind, pos: int, arg = "") = - var info = newLineInfo(L.filename, L.linenumber, pos - L.lineStart) - msgs.globalError(info, msg, arg) - -proc tokKindToStr*(k: TTokKind): string = - case k - of pxEof: result = "[EOF]" - of firstKeyword..lastKeyword: - result = Keywords[ord(k)-ord(firstKeyword)] - of pxInvalid, pxComment, pxStrLit: result = "string literal" - of pxCommand: result = "{@" - of pxAmp: result = "{&" - of pxPer: result = "{%" - of pxSymbol: result = "identifier" - of pxIntLit, pxInt64Lit: result = "integer literal" - of pxFloatLit: result = "floating point literal" - of pxParLe: result = "(" - of pxParRi: result = ")" - of pxBracketLe: result = "[" - of pxBracketRi: result = "]" - of pxComma: result = "," - of pxSemiColon: result = ";" - of pxColon: result = ":" - of pxAsgn: result = ":=" - of pxEquals: result = "=" - of pxDot: result = "." - of pxDotDot: result = ".." - of pxHat: result = "^" - of pxPlus: result = "+" - of pxMinus: result = "-" - of pxStar: result = "*" - of pxSlash: result = "/" - of pxLe: result = "<=" - of pxLt: result = "<" - of pxGe: result = ">=" - of pxGt: result = ">" - of pxNeq: result = "<>" - of pxAt: result = "@" - of pxStarDirLe: result = "(*$" - of pxStarDirRi: result = "*)" - of pxCurlyDirLe: result = "{$" - of pxCurlyDirRi: result = "}" - -proc `$`(tok: TToken): string = - case tok.xkind - of pxInvalid, pxComment, pxStrLit: result = tok.literal - of pxSymbol: result = tok.ident.s - of pxIntLit, pxInt64Lit: result = $tok.iNumber - of pxFloatLit: result = $tok.fNumber - else: result = tokKindToStr(tok.xkind) - -proc printTok(tok: TToken) = - writeln(stdout, $tok) - -proc setKeyword(L: var TLexer, tok: var TToken) = - var x = binaryStrSearch(keywords, toLower(tok.ident.s)) - if x < 0: tok.xkind = pxSymbol - else: tok.xKind = TTokKind(x + ord(firstKeyword)) - -proc matchUnderscoreChars(L: var TLexer, tok: var TToken, chars: TCharSet) = - # matches ([chars]_)* - var pos = L.bufpos # use registers for pos, buf - var buf = L.buf - while true: - if buf[pos] in chars: - add(tok.literal, buf[pos]) - inc(pos) - else: - break - if buf[pos] == '_': - add(tok.literal, '_') - inc(pos) - L.bufPos = pos - -proc isFloatLiteral(s: string): bool = - for i in countup(0, len(s)-1): - if s[i] in {'.', 'e', 'E'}: - return true - -proc getNumber2(L: var TLexer, tok: var TToken) = - var pos = L.bufpos + 1 # skip % - if not (L.buf[pos] in {'0'..'1'}): - # BUGFIX for %date% - tok.xkind = pxInvalid - add(tok.literal, '%') - inc(L.bufpos) - return - tok.base = base2 - var xi: BiggestInt = 0 - var bits = 0 - while true: - case L.buf[pos] - of 'A'..'Z', 'a'..'z', '2'..'9', '.': - lexMessage(L, errInvalidNumber) - inc(pos) - of '_': - inc(pos) - of '0', '1': - xi = `shl`(xi, 1) or (ord(L.buf[pos]) - ord('0')) - inc(pos) - inc(bits) - else: break - tok.iNumber = xi - if (bits > 32): tok.xkind = pxInt64Lit - else: tok.xkind = pxIntLit - L.bufpos = pos - -proc getNumber16(L: var TLexer, tok: var TToken) = - var pos = L.bufpos + 1 # skip $ - tok.base = base16 - var xi: BiggestInt = 0 - var bits = 0 - while true: - case L.buf[pos] - of 'G'..'Z', 'g'..'z', '.': - lexMessage(L, errInvalidNumber) - inc(pos) - of '_': inc(pos) - of '0'..'9': - xi = `shl`(xi, 4) or (ord(L.buf[pos]) - ord('0')) - inc(pos) - inc(bits, 4) - of 'a'..'f': - xi = `shl`(xi, 4) or (ord(L.buf[pos]) - ord('a') + 10) - inc(pos) - inc(bits, 4) - of 'A'..'F': - xi = `shl`(xi, 4) or (ord(L.buf[pos]) - ord('A') + 10) - inc(pos) - inc(bits, 4) - else: break - tok.iNumber = xi - if (bits > 32): - tok.xkind = pxInt64Lit - else: - tok.xkind = pxIntLit - L.bufpos = pos - -proc getNumber10(L: var TLexer, tok: var TToken) = - tok.base = base10 - matchUnderscoreChars(L, tok, {'0'..'9'}) - if (L.buf[L.bufpos] == '.') and (L.buf[L.bufpos + 1] in {'0'..'9'}): - add(tok.literal, '.') - inc(L.bufpos) - matchUnderscoreChars(L, tok, {'e', 'E', '+', '-', '0'..'9'}) - try: - if isFloatLiteral(tok.literal): - tok.fnumber = parseFloat(tok.literal) - tok.xkind = pxFloatLit - else: - tok.iNumber = parseInt(tok.literal) - if (tok.iNumber < low(int32)) or (tok.iNumber > high(int32)): - tok.xkind = pxInt64Lit - else: - tok.xkind = pxIntLit - except EInvalidValue: - lexMessage(L, errInvalidNumber, tok.literal) - except EOverflow: - lexMessage(L, errNumberOutOfRange, tok.literal) - -proc handleCRLF(L: var TLexer, pos: int): int = - case L.buf[pos] - of CR: result = nimlexbase.handleCR(L, pos) - of LF: result = nimlexbase.handleLF(L, pos) - else: result = pos - -proc getString(L: var TLexer, tok: var TToken) = - var xi: int - var pos = L.bufPos - var buf = L.buf - while true: - if buf[pos] == '\'': - inc(pos) - while true: - case buf[pos] - of CR, LF, nimlexbase.EndOfFile: - lexMessage(L, errClosingQuoteExpected) - break - of '\'': - inc(pos) - if buf[pos] == '\'': - inc(pos) - add(tok.literal, '\'') - else: - break - else: - add(tok.literal, buf[pos]) - inc(pos) - elif buf[pos] == '#': - inc(pos) - xi = 0 - case buf[pos] - of '$': - inc(pos) - xi = 0 - while true: - case buf[pos] - of '0'..'9': xi = (xi shl 4) or (ord(buf[pos]) - ord('0')) - of 'a'..'f': xi = (xi shl 4) or (ord(buf[pos]) - ord('a') + 10) - of 'A'..'F': xi = (xi shl 4) or (ord(buf[pos]) - ord('A') + 10) - else: break - inc(pos) - of '0'..'9': - xi = 0 - while buf[pos] in {'0'..'9'}: - xi = (xi * 10) + (ord(buf[pos]) - ord('0')) - inc(pos) - else: lexMessage(L, errInvalidCharacterConstant) - if (xi <= 255): add(tok.literal, chr(xi)) - else: lexMessage(L, errInvalidCharacterConstant) - else: - break - tok.xkind = pxStrLit - L.bufpos = pos - -proc getSymbol(L: var TLexer, tok: var TToken) = - var h: THash = 0 - var pos = L.bufpos - var buf = L.buf - while true: - var c = buf[pos] - case c - of 'a'..'z', '0'..'9', '\x80'..'\xFF': - h = h +% ord(c) - h = h +% h shl 10 - h = h xor (h shr 6) - of 'A'..'Z': - c = chr(ord(c) + (ord('a') - ord('A'))) # toLower() - h = h +% ord(c) - h = h +% h shl 10 - h = h xor (h shr 6) - of '_': discard - else: break - inc(pos) - h = h +% h shl 3 - h = h xor (h shr 11) - h = h +% h shl 15 - tok.ident = getIdent(addr(L.buf[L.bufpos]), pos - L.bufpos, h) - L.bufpos = pos - setKeyword(L, tok) - -proc scanLineComment(L: var TLexer, tok: var TToken) = - var pos = L.bufpos - var buf = L.buf - # a comment ends if the next line does not start with the // on the same - # column after only whitespace - tok.xkind = pxComment - var col = getColNumber(L, pos) - while true: - inc(pos, 2) # skip // - add(tok.literal, '#') - while not (buf[pos] in {CR, LF, nimlexbase.EndOfFile}): - add(tok.literal, buf[pos]) - inc(pos) - pos = handleCRLF(L, pos) - buf = L.buf - var indent = 0 - while buf[pos] == ' ': - inc(pos) - inc(indent) - if (col == indent) and (buf[pos] == '/') and (buf[pos + 1] == '/'): - tok.literal = tok.literal & "\n" - else: - break - L.bufpos = pos - -proc scanCurlyComment(L: var TLexer, tok: var TToken) = - var pos = L.bufpos - var buf = L.buf - tok.literal = "#" - tok.xkind = pxComment - while true: - case buf[pos] - of CR, LF: - pos = handleCRLF(L, pos) - buf = L.buf - add(tok.literal, "\n#") - of '}': - inc(pos) - break - of nimlexbase.EndOfFile: lexMessage(L, errTokenExpected, "}") - else: - add(tok.literal, buf[pos]) - inc(pos) - L.bufpos = pos - -proc scanStarComment(L: var TLexer, tok: var TToken) = - var pos = L.bufpos - var buf = L.buf - tok.literal = "#" - tok.xkind = pxComment - while true: - case buf[pos] - of CR, LF: - pos = handleCRLF(L, pos) - buf = L.buf - add(tok.literal, "\n#") - of '*': - inc(pos) - if buf[pos] == ')': - inc(pos) - break - else: - add(tok.literal, '*') - of nimlexbase.EndOfFile: - lexMessage(L, errTokenExpected, "*)") - else: - add(tok.literal, buf[pos]) - inc(pos) - L.bufpos = pos - -proc skip(L: var TLexer, tok: var TToken) = - var pos = L.bufpos - var buf = L.buf - while true: - case buf[pos] - of ' ', Tabulator: - inc(pos) # newline is special: - of CR, LF: - pos = handleCRLF(L, pos) - buf = L.buf - else: - break # EndOfFile also leaves the loop - L.bufpos = pos - -proc getTok(L: var TLexer, tok: var TToken) = - tok.xkind = pxInvalid - fillToken(tok) - skip(L, tok) - var c = L.buf[L.bufpos] - if c in SymStartChars: - getSymbol(L, tok) - elif c in {'0'..'9'}: - getNumber10(L, tok) - else: - case c - of ';': - tok.xkind = pxSemicolon - inc(L.bufpos) - of '/': - if L.buf[L.bufpos + 1] == '/': - scanLineComment(L, tok) - else: - tok.xkind = pxSlash - inc(L.bufpos) - of ',': - tok.xkind = pxComma - inc(L.bufpos) - of '(': - inc(L.bufpos) - if (L.buf[L.bufPos] == '*'): - if (L.buf[L.bufPos + 1] == '$'): - inc(L.bufpos, 2) - skip(L, tok) - getSymbol(L, tok) - tok.xkind = pxStarDirLe - else: - inc(L.bufpos) - scanStarComment(L, tok) - else: - tok.xkind = pxParLe - of '*': - inc(L.bufpos) - if L.buf[L.bufpos] == ')': - inc(L.bufpos) - tok.xkind = pxStarDirRi - else: - tok.xkind = pxStar - of ')': - tok.xkind = pxParRi - inc(L.bufpos) - of '[': - inc(L.bufpos) - tok.xkind = pxBracketLe - of ']': - inc(L.bufpos) - tok.xkind = pxBracketRi - of '.': - inc(L.bufpos) - if L.buf[L.bufpos] == '.': - tok.xkind = pxDotDot - inc(L.bufpos) - else: - tok.xkind = pxDot - of '{': - inc(L.bufpos) - case L.buf[L.bufpos] - of '$': - inc(L.bufpos) - skip(L, tok) - getSymbol(L, tok) - tok.xkind = pxCurlyDirLe - of '&': - inc(L.bufpos) - tok.xkind = pxAmp - of '%': - inc(L.bufpos) - tok.xkind = pxPer - of '@': - inc(L.bufpos) - tok.xkind = pxCommand - else: scanCurlyComment(L, tok) - of '+': - tok.xkind = pxPlus - inc(L.bufpos) - of '-': - tok.xkind = pxMinus - inc(L.bufpos) - of ':': - inc(L.bufpos) - if L.buf[L.bufpos] == '=': - inc(L.bufpos) - tok.xkind = pxAsgn - else: - tok.xkind = pxColon - of '<': - inc(L.bufpos) - if L.buf[L.bufpos] == '>': - inc(L.bufpos) - tok.xkind = pxNeq - elif L.buf[L.bufpos] == '=': - inc(L.bufpos) - tok.xkind = pxLe - else: - tok.xkind = pxLt - of '>': - inc(L.bufpos) - if L.buf[L.bufpos] == '=': - inc(L.bufpos) - tok.xkind = pxGe - else: - tok.xkind = pxGt - of '=': - tok.xkind = pxEquals - inc(L.bufpos) - of '@': - tok.xkind = pxAt - inc(L.bufpos) - of '^': - tok.xkind = pxHat - inc(L.bufpos) - of '}': - tok.xkind = pxCurlyDirRi - inc(L.bufpos) - of '\'', '#': - getString(L, tok) - of '$': - getNumber16(L, tok) - of '%': - getNumber2(L, tok) - of nimlexbase.EndOfFile: - tok.xkind = pxEof - else: - tok.literal = c & "" - tok.xkind = pxInvalid - lexMessage(L, errInvalidToken, c & " (\\" & $(ord(c)) & ')') - inc(L.bufpos) diff --git a/compiler/pas2nim/pasparse.nim b/compiler/pas2nim/pasparse.nim deleted file mode 100644 index a6f8363f61..0000000000 --- a/compiler/pas2nim/pasparse.nim +++ /dev/null @@ -1,1513 +0,0 @@ -# -# -# Pas2nim - Pascal to Nimrod source converter -# (c) Copyright 2012 Andreas Rumpf -# -# See the file "copying.txt", included in this -# distribution, for details about the copyright. -# - -# This module implements the parser of the Pascal variant Nimrod is written in. -# It transfers a Pascal module into a Nimrod AST. Then the renderer can be -# used to convert the AST to its text representation. - -import - os, llstream, paslex, idents, strutils, ast, astalgo, msgs, options - -type - TSection = enum - seImplementation, seInterface - TContext = enum - conExpr, conStmt, conTypeDesc - TParserFlag* = enum - pfRefs, ## use "ref" instead of "ptr" for Pascal's ^typ - pfMoreReplacements, ## use more than the default replacements - pfImportBlackList ## use import blacklist - TParser*{.final.} = object - section: TSection - inParamList: bool - context: TContext # needed for the @emit command - lastVarSection: PNode - lex: TLexer - tok: TToken - repl: TIdTable # replacements - flags: set[TParserFlag] - - TReplaceTuple* = array[0..1, string] - -const - ImportBlackList*: array[1..3, string] = ["nsystem", "sysutils", "charsets"] - stdReplacements*: array[1..19, TReplaceTuple] = [["include", "incl"], - ["exclude", "excl"], ["pchar", "cstring"], ["assignfile", "open"], - ["integer", "int"], ["longword", "int32"], ["cardinal", "int"], - ["boolean", "bool"], ["shortint", "int8"], ["smallint", "int16"], - ["longint", "int32"], ["byte", "int8"], ["word", "int16"], - ["single", "float32"], ["double", "float64"], ["real", "float"], - ["length", "len"], ["len", "length"], ["setlength", "setlen"]] - nimReplacements*: array[1..35, TReplaceTuple] = [["nimread", "read"], - ["nimwrite", "write"], ["nimclosefile", "close"], ["closefile", "close"], - ["openfile", "open"], ["nsystem", "system"], ["ntime", "times"], - ["nos", "os"], ["nmath", "math"], ["ncopy", "copy"], ["addChar", "add"], - ["halt", "quit"], ["nobject", "TObject"], ["eof", "EndOfFile"], - ["input", "stdin"], ["output", "stdout"], ["addu", "`+%`"], - ["subu", "`-%`"], ["mulu", "`*%`"], ["divu", "`/%`"], ["modu", "`%%`"], - ["ltu", "`<%`"], ["leu", "`<=%`"], ["shlu", "`shl`"], ["shru", "`shr`"], - ["assigned", "not isNil"], ["eintoverflow", "EOverflow"], ["format", "`%`"], - ["snil", "nil"], ["tostringf", "$"], ["ttextfile", "tfile"], - ["tbinaryfile", "tfile"], ["strstart", "0"], ["nl", "\"\\n\""], - ["tostring", "$"]] - -proc parseUnit*(p: var TParser): PNode -proc openParser*(p: var TParser, filename: string, inputStream: PLLStream, - flags: set[TParserFlag] = {}) -proc closeParser*(p: var TParser) -proc exSymbol*(n: var PNode) -proc fixRecordDef*(n: var PNode) - # XXX: move these two to an auxiliary module - -# implementation - -proc openParser(p: var TParser, filename: string, - inputStream: PLLStream, flags: set[TParserFlag] = {}) = - openLexer(p.lex, filename, inputStream) - initIdTable(p.repl) - for i in countup(low(stdReplacements), high(stdReplacements)): - idTablePut(p.repl, getIdent(stdReplacements[i][0]), - getIdent(stdReplacements[i][1])) - if pfMoreReplacements in flags: - for i in countup(low(nimReplacements), high(nimReplacements)): - idTablePut(p.repl, getIdent(nimReplacements[i][0]), - getIdent(nimReplacements[i][1])) - p.flags = flags - -proc closeParser(p: var TParser) = closeLexer(p.lex) -proc getTok(p: var TParser) = getTok(p.lex, p.tok) - -proc parMessage(p: TParser, msg: TMsgKind, arg = "") = - lexMessage(p.lex, msg, arg) - -proc parLineInfo(p: TParser): TLineInfo = - result = getLineInfo(p.lex) - -proc skipCom(p: var TParser, n: PNode) = - while p.tok.xkind == pxComment: - if (n != nil): - if n.comment == nil: n.comment = p.tok.literal - else: add(n.comment, "\n" & p.tok.literal) - else: - parMessage(p, warnCommentXIgnored, p.tok.literal) - getTok(p) - -proc expectIdent(p: TParser) = - if p.tok.xkind != pxSymbol: - lexMessage(p.lex, errIdentifierExpected, $(p.tok)) - -proc eat(p: var TParser, xkind: TTokKind) = - if p.tok.xkind == xkind: getTok(p) - else: lexMessage(p.lex, errTokenExpected, tokKindToStr(xkind)) - -proc opt(p: var TParser, xkind: TTokKind) = - if p.tok.xkind == xkind: getTok(p) - -proc newNodeP(kind: TNodeKind, p: TParser): PNode = - result = newNodeI(kind, getLineInfo(p.lex)) - -proc newIntNodeP(kind: TNodeKind, intVal: BiggestInt, p: TParser): PNode = - result = newNodeP(kind, p) - result.intVal = intVal - -proc newFloatNodeP(kind: TNodeKind, floatVal: BiggestFloat, - p: TParser): PNode = - result = newNodeP(kind, p) - result.floatVal = floatVal - -proc newStrNodeP(kind: TNodeKind, strVal: string, p: TParser): PNode = - result = newNodeP(kind, p) - result.strVal = strVal - -proc newIdentNodeP(ident: PIdent, p: TParser): PNode = - result = newNodeP(nkIdent, p) - result.ident = ident - -proc createIdentNodeP(ident: PIdent, p: TParser): PNode = - result = newNodeP(nkIdent, p) - var x = PIdent(idTableGet(p.repl, ident)) - if x != nil: result.ident = x - else: result.ident = ident - -proc parseExpr(p: var TParser): PNode -proc parseStmt(p: var TParser): PNode -proc parseTypeDesc(p: var TParser, definition: PNode = nil): PNode - -proc parseEmit(p: var TParser, definition: PNode): PNode = - getTok(p) # skip 'emit' - result = ast.emptyNode - if p.tok.xkind != pxCurlyDirRi: - case p.context - of conExpr: - result = parseExpr(p) - of conStmt: - result = parseStmt(p) - if p.tok.xkind != pxCurlyDirRi: - var a = result - result = newNodeP(nkStmtList, p) - addSon(result, a) - while p.tok.xkind != pxCurlyDirRi: - addSon(result, parseStmt(p)) - of conTypeDesc: - result = parseTypeDesc(p, definition) - eat(p, pxCurlyDirRi) - -proc parseCommand(p: var TParser, definition: PNode = nil): PNode = - result = ast.emptyNode - getTok(p) - if p.tok.ident.id == getIdent("discard").id: - result = newNodeP(nkDiscardStmt, p) - getTok(p) - eat(p, pxCurlyDirRi) - addSon(result, parseExpr(p)) - elif p.tok.ident.id == getIdent("set").id: - getTok(p) - eat(p, pxCurlyDirRi) - result = parseExpr(p) - if result.kind == nkEmpty: internalError("emptyNode modified") - result.kind = nkCurly - elif p.tok.ident.id == getIdent("cast").id: - getTok(p) - eat(p, pxCurlyDirRi) - var a = parseExpr(p) - if (a.kind == nkCall) and (sonsLen(a) == 2): - result = newNodeP(nkCast, p) - addSon(result, a.sons[0]) - addSon(result, a.sons[1]) - else: - parMessage(p, errInvalidDirectiveX, $p.tok) - result = a - elif p.tok.ident.id == getIdent("emit").id: - result = parseEmit(p, definition) - elif p.tok.ident.id == getIdent("ignore").id: - getTok(p) - eat(p, pxCurlyDirRi) - while true: - case p.tok.xkind - of pxEof: - parMessage(p, errTokenExpected, "{@emit}") - of pxCommand: - getTok(p) - if p.tok.ident.id == getIdent("emit").id: - result = parseEmit(p, definition) - break - else: - while (p.tok.xkind != pxCurlyDirRi) and (p.tok.xkind != pxEof): - getTok(p) - eat(p, pxCurlyDirRi) - else: - getTok(p) # skip token - elif p.tok.ident.id == getIdent("ptr").id: - result = newNodeP(nkPtrTy, p) - getTok(p) - eat(p, pxCurlyDirRi) - elif p.tok.ident.id == getIdent("tuple").id: - result = newNodeP(nkTupleTy, p) - getTok(p) - eat(p, pxCurlyDirRi) - elif p.tok.ident.id == getIdent("acyclic").id: - result = newIdentNodeP(p.tok.ident, p) - getTok(p) - eat(p, pxCurlyDirRi) - else: - parMessage(p, errInvalidDirectiveX, $p.tok) - while true: - getTok(p) - if p.tok.xkind == pxCurlyDirRi or p.tok.xkind == pxEof: break - eat(p, pxCurlyDirRi) - result = ast.emptyNode - -proc getPrecedence(kind: TTokKind): int = - case kind - of pxDiv, pxMod, pxStar, pxSlash, pxShl, pxShr, pxAnd: result = 5 - of pxPlus, pxMinus, pxOr, pxXor: result = 4 - of pxIn, pxEquals, pxLe, pxLt, pxGe, pxGt, pxNeq, pxIs: result = 3 - else: result = -1 - -proc rangeExpr(p: var TParser): PNode = - var a = parseExpr(p) - if p.tok.xkind == pxDotDot: - result = newNodeP(nkRange, p) - addSon(result, a) - getTok(p) - skipCom(p, result) - addSon(result, parseExpr(p)) - else: - result = a - -proc bracketExprList(p: var TParser, first: PNode): PNode = - result = newNodeP(nkBracketExpr, p) - addSon(result, first) - getTok(p) - skipCom(p, result) - while true: - if p.tok.xkind == pxBracketRi: - getTok(p) - break - if p.tok.xkind == pxEof: - parMessage(p, errTokenExpected, tokKindToStr(pxBracketRi)) - break - var a = rangeExpr(p) - skipCom(p, a) - if p.tok.xkind == pxComma: - getTok(p) - skipCom(p, a) - addSon(result, a) - -proc exprColonEqExpr(p: var TParser, kind: TNodeKind, - tok: TTokKind): PNode = - var a = parseExpr(p) - if p.tok.xkind == tok: - result = newNodeP(kind, p) - getTok(p) - skipCom(p, result) - addSon(result, a) - addSon(result, parseExpr(p)) - else: - result = a - -proc exprListAux(p: var TParser, elemKind: TNodeKind, - endTok, sepTok: TTokKind, result: PNode) = - getTok(p) - skipCom(p, result) - while true: - if p.tok.xkind == endTok: - getTok(p) - break - if p.tok.xkind == pxEof: - parMessage(p, errTokenExpected, tokKindToStr(endTok)) - break - var a = exprColonEqExpr(p, elemKind, sepTok) - skipCom(p, a) - if (p.tok.xkind == pxComma) or (p.tok.xkind == pxSemicolon): - getTok(p) - skipCom(p, a) - addSon(result, a) - -proc qualifiedIdent(p: var TParser): PNode = - if p.tok.xkind == pxSymbol: - result = createIdentNodeP(p.tok.ident, p) - else: - parMessage(p, errIdentifierExpected, $p.tok) - return ast.emptyNode - getTok(p) - skipCom(p, result) - if p.tok.xkind == pxDot: - getTok(p) - skipCom(p, result) - if p.tok.xkind == pxSymbol: - var a = result - result = newNodeI(nkDotExpr, a.info) - addSon(result, a) - addSon(result, createIdentNodeP(p.tok.ident, p)) - getTok(p) - else: - parMessage(p, errIdentifierExpected, $p.tok) - -proc qualifiedIdentListAux(p: var TParser, endTok: TTokKind, - result: PNode) = - getTok(p) - skipCom(p, result) - while true: - if p.tok.xkind == endTok: - getTok(p) - break - if p.tok.xkind == pxEof: - parMessage(p, errTokenExpected, tokKindToStr(endTok)) - break - var a = qualifiedIdent(p) - skipCom(p, a) - if p.tok.xkind == pxComma: - getTok(p) - skipCom(p, a) - addSon(result, a) - -proc exprColonEqExprList(p: var TParser, kind, elemKind: TNodeKind, - endTok, sepTok: TTokKind): PNode = - result = newNodeP(kind, p) - exprListAux(p, elemKind, endTok, sepTok, result) - -proc setBaseFlags(n: PNode, base: TNumericalBase) = - case base - of base10: discard - of base2: incl(n.flags, nfBase2) - of base8: incl(n.flags, nfBase8) - of base16: incl(n.flags, nfBase16) - -proc identOrLiteral(p: var TParser): PNode = - case p.tok.xkind - of pxSymbol: - result = createIdentNodeP(p.tok.ident, p) - getTok(p) - of pxIntLit: - result = newIntNodeP(nkIntLit, p.tok.iNumber, p) - setBaseFlags(result, p.tok.base) - getTok(p) - of pxInt64Lit: - result = newIntNodeP(nkInt64Lit, p.tok.iNumber, p) - setBaseFlags(result, p.tok.base) - getTok(p) - of pxFloatLit: - result = newFloatNodeP(nkFloatLit, p.tok.fNumber, p) - setBaseFlags(result, p.tok.base) - getTok(p) - of pxStrLit: - if len(p.tok.literal) != 1: result = newStrNodeP(nkStrLit, p.tok.literal, p) - else: result = newIntNodeP(nkCharLit, ord(p.tok.literal[0]), p) - getTok(p) - of pxNil: - result = newNodeP(nkNilLit, p) - getTok(p) - of pxParLe: - # () constructor - result = exprColonEqExprList(p, nkPar, nkExprColonExpr, pxParRi, pxColon) - #if hasSonWith(result, nkExprColonExpr) then - # replaceSons(result, nkExprColonExpr, nkExprEqExpr) - if (sonsLen(result) > 1) and not hasSonWith(result, nkExprColonExpr): - result.kind = nkBracket # is an array constructor - of pxBracketLe: - # [] constructor - result = newNodeP(nkBracket, p) - getTok(p) - skipCom(p, result) - while (p.tok.xkind != pxBracketRi) and (p.tok.xkind != pxEof): - var a = rangeExpr(p) - if a.kind == nkRange: - result.kind = nkCurly # it is definitely a set literal - opt(p, pxComma) - skipCom(p, a) - assert(a != nil) - addSon(result, a) - eat(p, pxBracketRi) - of pxCommand: - result = parseCommand(p) - else: - parMessage(p, errExprExpected, $(p.tok)) - getTok(p) # we must consume a token here to prevend endless loops! - result = ast.emptyNode - if result.kind != nkEmpty: skipCom(p, result) - -proc primary(p: var TParser): PNode = - # prefix operator? - if (p.tok.xkind == pxNot) or (p.tok.xkind == pxMinus) or - (p.tok.xkind == pxPlus): - result = newNodeP(nkPrefix, p) - var a = newIdentNodeP(getIdent($p.tok), p) - addSon(result, a) - getTok(p) - skipCom(p, a) - addSon(result, primary(p)) - return - elif p.tok.xkind == pxAt: - result = newNodeP(nkAddr, p) - var a = newIdentNodeP(getIdent($p.tok), p) - getTok(p) - if p.tok.xkind == pxBracketLe: - result = newNodeP(nkPrefix, p) - addSon(result, a) - addSon(result, identOrLiteral(p)) - else: - addSon(result, primary(p)) - return - result = identOrLiteral(p) - while true: - case p.tok.xkind - of pxParLe: - var a = result - result = newNodeP(nkCall, p) - addSon(result, a) - exprListAux(p, nkExprEqExpr, pxParRi, pxEquals, result) - of pxDot: - var a = result - result = newNodeP(nkDotExpr, p) - addSon(result, a) - getTok(p) # skip '.' - skipCom(p, result) - if p.tok.xkind == pxSymbol: - addSon(result, createIdentNodeP(p.tok.ident, p)) - getTok(p) - else: - parMessage(p, errIdentifierExpected, $p.tok) - of pxHat: - var a = result - result = newNodeP(nkBracketExpr, p) - addSon(result, a) - getTok(p) - of pxBracketLe: - result = bracketExprList(p, result) - else: break - -proc lowestExprAux(p: var TParser, v: var PNode, limit: int): TTokKind = - var - nextop: TTokKind - v2, node, opNode: PNode - v = primary(p) # expand while operators have priorities higher than 'limit' - var op = p.tok.xkind - var opPred = getPrecedence(op) - while (opPred > limit): - node = newNodeP(nkInfix, p) - opNode = newIdentNodeP(getIdent($(p.tok)), p) # skip operator: - getTok(p) - case op - of pxPlus: - case p.tok.xkind - of pxPer: - getTok(p) - eat(p, pxCurlyDirRi) - opNode.ident = getIdent("+%") - of pxAmp: - getTok(p) - eat(p, pxCurlyDirRi) - opNode.ident = getIdent("&") - else: - discard - of pxMinus: - if p.tok.xkind == pxPer: - getTok(p) - eat(p, pxCurlyDirRi) - opNode.ident = getIdent("-%") - of pxEquals: - opNode.ident = getIdent("==") - of pxNeq: - opNode.ident = getIdent("!=") - else: - discard - skipCom(p, opNode) # read sub-expression with higher priority - nextop = lowestExprAux(p, v2, opPred) - addSon(node, opNode) - addSon(node, v) - addSon(node, v2) - v = node - op = nextop - opPred = getPrecedence(nextop) - result = op # return first untreated operator - -proc fixExpr(n: PNode): PNode = - result = n - case n.kind - of nkInfix: - if n.sons[1].kind == nkBracket: n.sons[1].kind = nkCurly - if n.sons[2].kind == nkBracket: n.sons[2].kind = nkCurly - if (n.sons[0].kind == nkIdent): - if (n.sons[0].ident.id == getIdent("+").id): - if (n.sons[1].kind == nkCharLit) and (n.sons[2].kind == nkStrLit) and - (n.sons[2].strVal == ""): - result = newStrNode(nkStrLit, chr(int(n.sons[1].intVal)) & "") - result.info = n.info - return # do not process sons as they don't exist anymore - elif (n.sons[1].kind in {nkCharLit, nkStrLit}) or - (n.sons[2].kind in {nkCharLit, nkStrLit}): - n.sons[0].ident = getIdent("&") # fix operator - else: - discard - if not (n.kind in {nkEmpty..nkNilLit}): - for i in countup(0, sonsLen(n) - 1): result.sons[i] = fixExpr(n.sons[i]) - -proc parseExpr(p: var TParser): PNode = - var oldcontext = p.context - p.context = conExpr - if p.tok.xkind == pxCommand: - result = parseCommand(p) - else: - discard lowestExprAux(p, result, - 1) - result = fixExpr(result) - p.context = oldcontext - -proc parseExprStmt(p: var TParser): PNode = - var info = parLineInfo(p) - var a = parseExpr(p) - if p.tok.xkind == pxAsgn: - getTok(p) - skipCom(p, a) - var b = parseExpr(p) - result = newNodeI(nkAsgn, info) - addSon(result, a) - addSon(result, b) - else: - result = a - -proc inImportBlackList(ident: PIdent): bool = - for i in countup(low(ImportBlackList), high(ImportBlackList)): - if ident.id == getIdent(ImportBlackList[i]).id: - return true - -proc parseUsesStmt(p: var TParser): PNode = - var a: PNode - result = newNodeP(nkImportStmt, p) - getTok(p) # skip `import` - skipCom(p, result) - while true: - case p.tok.xkind - of pxEof: break - of pxSymbol: a = newIdentNodeP(p.tok.ident, p) - else: - parMessage(p, errIdentifierExpected, $(p.tok)) - break - getTok(p) # skip identifier, string - skipCom(p, a) - if pfImportBlackList notin p.flags or not inImportBlackList(a.ident): - addSon(result, createIdentNodeP(a.ident, p)) - if p.tok.xkind == pxComma: - getTok(p) - skipCom(p, a) - else: - break - if sonsLen(result) == 0: result = ast.emptyNode - -proc parseIncludeDir(p: var TParser): PNode = - result = newNodeP(nkIncludeStmt, p) - getTok(p) # skip `include` - var filename = "" - while true: - case p.tok.xkind - of pxSymbol, pxDot, pxDotDot, pxSlash: - add(filename, $p.tok) - getTok(p) - of pxStrLit: - filename = p.tok.literal - getTok(p) - break - of pxCurlyDirRi: - break - else: - parMessage(p, errIdentifierExpected, $p.tok) - break - addSon(result, newStrNodeP(nkStrLit, changeFileExt(filename, "nim"), p)) - if filename == "config.inc": result = ast.emptyNode - -proc definedExprAux(p: var TParser): PNode = - result = newNodeP(nkCall, p) - addSon(result, newIdentNodeP(getIdent("defined"), p)) - expectIdent(p) - addSon(result, createIdentNodeP(p.tok.ident, p)) - getTok(p) - -proc isHandledDirective(p: TParser): bool = - if p.tok.xkind in {pxCurlyDirLe, pxStarDirLe}: - case toLower(p.tok.ident.s) - of "else", "endif": result = false - else: result = true - -proc parseStmtList(p: var TParser): PNode = - result = newNodeP(nkStmtList, p) - while true: - case p.tok.xkind - of pxEof: - break - of pxCurlyDirLe, pxStarDirLe: - if not isHandledDirective(p): break - else: - discard - addSon(result, parseStmt(p)) - if sonsLen(result) == 1: result = result.sons[0] - -proc parseIfDirAux(p: var TParser, result: PNode) = - addSon(result.sons[0], parseStmtList(p)) - if p.tok.xkind in {pxCurlyDirLe, pxStarDirLe}: - var endMarker = succ(p.tok.xkind) - if toLower(p.tok.ident.s) == "else": - var s = newNodeP(nkElse, p) - while p.tok.xkind != pxEof and p.tok.xkind != endMarker: getTok(p) - eat(p, endMarker) - addSon(s, parseStmtList(p)) - addSon(result, s) - if p.tok.xkind in {pxCurlyDirLe, pxStarDirLe}: - endMarker = succ(p.tok.xkind) - if toLower(p.tok.ident.s) == "endif": - while p.tok.xkind != pxEof and p.tok.xkind != endMarker: getTok(p) - eat(p, endMarker) - else: - parMessage(p, errXExpected, "{$endif}") - else: - parMessage(p, errXExpected, "{$endif}") - -proc parseIfdefDir(p: var TParser, endMarker: TTokKind): PNode = - result = newNodeP(nkWhenStmt, p) - addSon(result, newNodeP(nkElifBranch, p)) - getTok(p) - addSon(result.sons[0], definedExprAux(p)) - eat(p, endMarker) - parseIfDirAux(p, result) - -proc parseIfndefDir(p: var TParser, endMarker: TTokKind): PNode = - result = newNodeP(nkWhenStmt, p) - addSon(result, newNodeP(nkElifBranch, p)) - getTok(p) - var e = newNodeP(nkCall, p) - addSon(e, newIdentNodeP(getIdent("not"), p)) - addSon(e, definedExprAux(p)) - eat(p, endMarker) - addSon(result.sons[0], e) - parseIfDirAux(p, result) - -proc parseIfDir(p: var TParser, endMarker: TTokKind): PNode = - result = newNodeP(nkWhenStmt, p) - addSon(result, newNodeP(nkElifBranch, p)) - getTok(p) - addSon(result.sons[0], parseExpr(p)) - eat(p, endMarker) - parseIfDirAux(p, result) - -proc parseDirective(p: var TParser): PNode = - result = ast.emptyNode - if not (p.tok.xkind in {pxCurlyDirLe, pxStarDirLe}): return - var endMarker = succ(p.tok.xkind) - if p.tok.ident != nil: - case toLower(p.tok.ident.s) - of "include": - result = parseIncludeDir(p) - eat(p, endMarker) - of "if": result = parseIfDir(p, endMarker) - of "ifdef": result = parseIfdefDir(p, endMarker) - of "ifndef": result = parseIfndefDir(p, endMarker) - else: - # skip unknown compiler directive - while p.tok.xkind != pxEof and p.tok.xkind != endMarker: getTok(p) - eat(p, endMarker) - else: - eat(p, endMarker) - -proc parseRaise(p: var TParser): PNode = - result = newNodeP(nkRaiseStmt, p) - getTok(p) - skipCom(p, result) - if p.tok.xkind != pxSemicolon: addSon(result, parseExpr(p)) - else: addSon(result, ast.emptyNode) - -proc parseIf(p: var TParser): PNode = - result = newNodeP(nkIfStmt, p) - while true: - getTok(p) # skip ``if`` - var branch = newNodeP(nkElifBranch, p) - skipCom(p, branch) - addSon(branch, parseExpr(p)) - eat(p, pxThen) - skipCom(p, branch) - addSon(branch, parseStmt(p)) - skipCom(p, branch) - addSon(result, branch) - if p.tok.xkind == pxElse: - getTok(p) - if p.tok.xkind != pxIf: - # ordinary else part: - branch = newNodeP(nkElse, p) - skipCom(p, result) # BUGFIX - addSon(branch, parseStmt(p)) - addSon(result, branch) - break - else: - break - -proc parseWhile(p: var TParser): PNode = - result = newNodeP(nkWhileStmt, p) - getTok(p) - skipCom(p, result) - addSon(result, parseExpr(p)) - eat(p, pxDo) - skipCom(p, result) - addSon(result, parseStmt(p)) - -proc parseRepeat(p: var TParser): PNode = - result = newNodeP(nkWhileStmt, p) - getTok(p) - skipCom(p, result) - addSon(result, newIdentNodeP(getIdent("true"), p)) - var s = newNodeP(nkStmtList, p) - while p.tok.xkind != pxEof and p.tok.xkind != pxUntil: - addSon(s, parseStmt(p)) - eat(p, pxUntil) - var a = newNodeP(nkIfStmt, p) - skipCom(p, a) - var b = newNodeP(nkElifBranch, p) - var c = newNodeP(nkBreakStmt, p) - addSon(c, ast.emptyNode) - addSon(b, parseExpr(p)) - skipCom(p, a) - addSon(b, c) - addSon(a, b) - if b.sons[0].kind == nkIdent and b.sons[0].ident.id == getIdent("false").id: - discard - else: - addSon(s, a) - addSon(result, s) - -proc parseCase(p: var TParser): PNode = - var b: PNode - result = newNodeP(nkCaseStmt, p) - getTok(p) - addSon(result, parseExpr(p)) - eat(p, pxOf) - skipCom(p, result) - while (p.tok.xkind != pxEnd) and (p.tok.xkind != pxEof): - if p.tok.xkind == pxElse: - b = newNodeP(nkElse, p) - getTok(p) - else: - b = newNodeP(nkOfBranch, p) - while (p.tok.xkind != pxEof) and (p.tok.xkind != pxColon): - addSon(b, rangeExpr(p)) - opt(p, pxComma) - skipCom(p, b) - eat(p, pxColon) - skipCom(p, b) - addSon(b, parseStmt(p)) - addSon(result, b) - if b.kind == nkElse: break - eat(p, pxEnd) - -proc parseTry(p: var TParser): PNode = - result = newNodeP(nkTryStmt, p) - getTok(p) - skipCom(p, result) - var b = newNodeP(nkStmtList, p) - while not (p.tok.xkind in {pxFinally, pxExcept, pxEof, pxEnd}): - addSon(b, parseStmt(p)) - addSon(result, b) - if p.tok.xkind == pxExcept: - getTok(p) - while p.tok.ident.id == getIdent("on").id: - b = newNodeP(nkExceptBranch, p) - getTok(p) - var e = qualifiedIdent(p) - if p.tok.xkind == pxColon: - getTok(p) - e = qualifiedIdent(p) - addSon(b, e) - eat(p, pxDo) - addSon(b, parseStmt(p)) - addSon(result, b) - if p.tok.xkind == pxCommand: discard parseCommand(p) - if p.tok.xkind == pxElse: - b = newNodeP(nkExceptBranch, p) - getTok(p) - addSon(b, parseStmt(p)) - addSon(result, b) - if p.tok.xkind == pxFinally: - b = newNodeP(nkFinally, p) - getTok(p) - var e = newNodeP(nkStmtList, p) - while (p.tok.xkind != pxEof) and (p.tok.xkind != pxEnd): - addSon(e, parseStmt(p)) - if sonsLen(e) == 0: addSon(e, newNodeP(nkNilLit, p)) - addSon(result, e) - eat(p, pxEnd) - -proc parseFor(p: var TParser): PNode = - result = newNodeP(nkForStmt, p) - getTok(p) - skipCom(p, result) - expectIdent(p) - addSon(result, createIdentNodeP(p.tok.ident, p)) - getTok(p) - eat(p, pxAsgn) - var a = parseExpr(p) - var b = ast.emptyNode - var c = newNodeP(nkCall, p) - if p.tok.xkind == pxTo: - addSon(c, newIdentNodeP(getIdent("countup"), p)) - getTok(p) - b = parseExpr(p) - elif p.tok.xkind == pxDownto: - addSon(c, newIdentNodeP(getIdent("countdown"), p)) - getTok(p) - b = parseExpr(p) - else: - parMessage(p, errTokenExpected, tokKindToStr(pxTo)) - addSon(c, a) - addSon(c, b) - eat(p, pxDo) - skipCom(p, result) - addSon(result, c) - addSon(result, parseStmt(p)) - -proc parseParam(p: var TParser): PNode = - var a: PNode - result = newNodeP(nkIdentDefs, p) - var v = ast.emptyNode - case p.tok.xkind - of pxConst: - getTok(p) - of pxVar: - getTok(p) - v = newNodeP(nkVarTy, p) - of pxOut: - getTok(p) - v = newNodeP(nkVarTy, p) - else: - discard - while true: - case p.tok.xkind - of pxSymbol: a = createIdentNodeP(p.tok.ident, p) - of pxColon, pxEof, pxParRi, pxEquals: break - else: - parMessage(p, errIdentifierExpected, $p.tok) - return - getTok(p) # skip identifier - skipCom(p, a) - if p.tok.xkind == pxComma: - getTok(p) - skipCom(p, a) - addSon(result, a) - if p.tok.xkind == pxColon: - getTok(p) - skipCom(p, result) - if v.kind != nkEmpty: addSon(v, parseTypeDesc(p)) - else: v = parseTypeDesc(p) - addSon(result, v) - else: - addSon(result, ast.emptyNode) - if p.tok.xkind != pxEquals: - parMessage(p, errColonOrEqualsExpected, $p.tok) - if p.tok.xkind == pxEquals: - getTok(p) - skipCom(p, result) - addSon(result, parseExpr(p)) - else: - addSon(result, ast.emptyNode) - -proc parseParamList(p: var TParser): PNode = - var a: PNode - result = newNodeP(nkFormalParams, p) - addSon(result, ast.emptyNode) # return type - if p.tok.xkind == pxParLe: - p.inParamList = true - getTok(p) - skipCom(p, result) - while true: - case p.tok.xkind - of pxSymbol, pxConst, pxVar, pxOut: - a = parseParam(p) - of pxParRi: - getTok(p) - break - else: - parMessage(p, errTokenExpected, ")") - break - skipCom(p, a) - if p.tok.xkind == pxSemicolon: - getTok(p) - skipCom(p, a) - addSon(result, a) - p.inParamList = false - if p.tok.xkind == pxColon: - getTok(p) - skipCom(p, result) - result.sons[0] = parseTypeDesc(p) - -proc parseCallingConvention(p: var TParser): PNode = - result = ast.emptyNode - if p.tok.xkind == pxSymbol: - case toLower(p.tok.ident.s) - of "stdcall", "cdecl", "safecall", "syscall", "inline", "fastcall": - result = newNodeP(nkPragma, p) - addSon(result, newIdentNodeP(p.tok.ident, p)) - getTok(p) - opt(p, pxSemicolon) - of "register": - result = newNodeP(nkPragma, p) - addSon(result, newIdentNodeP(getIdent("fastcall"), p)) - getTok(p) - opt(p, pxSemicolon) - else: - discard - -proc parseRoutineSpecifiers(p: var TParser, noBody: var bool): PNode = - var e: PNode - result = parseCallingConvention(p) - noBody = false - while p.tok.xkind == pxSymbol: - case toLower(p.tok.ident.s) - of "assembler", "overload", "far": - getTok(p) - opt(p, pxSemicolon) - of "forward": - noBody = true - getTok(p) - opt(p, pxSemicolon) - of "importc": - # This is a fake for platform module. There is no ``importc`` - # directive in Pascal. - if result.kind == nkEmpty: result = newNodeP(nkPragma, p) - addSon(result, newIdentNodeP(getIdent("importc"), p)) - noBody = true - getTok(p) - opt(p, pxSemicolon) - of "noconv": - # This is a fake for platform module. There is no ``noconv`` - # directive in Pascal. - if result.kind == nkEmpty: result = newNodeP(nkPragma, p) - addSon(result, newIdentNodeP(getIdent("noconv"), p)) - noBody = true - getTok(p) - opt(p, pxSemicolon) - of "procvar": - # This is a fake for the Nimrod compiler. There is no ``procvar`` - # directive in Pascal. - if result.kind == nkEmpty: result = newNodeP(nkPragma, p) - addSon(result, newIdentNodeP(getIdent("procvar"), p)) - getTok(p) - opt(p, pxSemicolon) - of "varargs": - if result.kind == nkEmpty: result = newNodeP(nkPragma, p) - addSon(result, newIdentNodeP(getIdent("varargs"), p)) - getTok(p) - opt(p, pxSemicolon) - of "external": - if result.kind == nkEmpty: result = newNodeP(nkPragma, p) - getTok(p) - noBody = true - e = newNodeP(nkExprColonExpr, p) - addSon(e, newIdentNodeP(getIdent("dynlib"), p)) - addSon(e, parseExpr(p)) - addSon(result, e) - opt(p, pxSemicolon) - if (p.tok.xkind == pxSymbol) and - (p.tok.ident.id == getIdent("name").id): - e = newNodeP(nkExprColonExpr, p) - getTok(p) - addSon(e, newIdentNodeP(getIdent("importc"), p)) - addSon(e, parseExpr(p)) - addSon(result, e) - else: - addSon(result, newIdentNodeP(getIdent("importc"), p)) - opt(p, pxSemicolon) - else: - e = parseCallingConvention(p) - if e.kind == nkEmpty: break - if result.kind == nkEmpty: result = newNodeP(nkPragma, p) - addSon(result, e.sons[0]) - -proc parseRoutineType(p: var TParser): PNode = - result = newNodeP(nkProcTy, p) - getTok(p) - skipCom(p, result) - addSon(result, parseParamList(p)) - opt(p, pxSemicolon) - addSon(result, parseCallingConvention(p)) - skipCom(p, result) - -proc parseEnum(p: var TParser): PNode = - var a: PNode - result = newNodeP(nkEnumTy, p) - getTok(p) - skipCom(p, result) - addSon(result, ast.emptyNode) # it does not inherit from any enumeration - while true: - case p.tok.xkind - of pxEof, pxParRi: break - of pxSymbol: a = newIdentNodeP(p.tok.ident, p) - else: - parMessage(p, errIdentifierExpected, $(p.tok)) - break - getTok(p) # skip identifier - skipCom(p, a) - if (p.tok.xkind == pxEquals) or (p.tok.xkind == pxAsgn): - getTok(p) - skipCom(p, a) - var b = a - a = newNodeP(nkEnumFieldDef, p) - addSon(a, b) - addSon(a, parseExpr(p)) - if p.tok.xkind == pxComma: - getTok(p) - skipCom(p, a) - addSon(result, a) - eat(p, pxParRi) - -proc identVis(p: var TParser): PNode = - # identifier with visability - var a = createIdentNodeP(p.tok.ident, p) - if p.section == seInterface: - result = newNodeP(nkPostfix, p) - addSon(result, newIdentNodeP(getIdent("*"), p)) - addSon(result, a) - else: - result = a - getTok(p) - -type - TSymbolParser = proc (p: var TParser): PNode {.nimcall.} - -proc rawIdent(p: var TParser): PNode = - result = createIdentNodeP(p.tok.ident, p) - getTok(p) - -proc parseIdentColonEquals(p: var TParser, - identParser: TSymbolParser): PNode = - var a: PNode - result = newNodeP(nkIdentDefs, p) - while true: - case p.tok.xkind - of pxSymbol: a = identParser(p) - of pxColon, pxEof, pxParRi, pxEquals: break - else: - parMessage(p, errIdentifierExpected, $(p.tok)) - return - skipCom(p, a) - if p.tok.xkind == pxComma: - getTok(p) - skipCom(p, a) - addSon(result, a) - if p.tok.xkind == pxColon: - getTok(p) - skipCom(p, result) - addSon(result, parseTypeDesc(p)) - else: - addSon(result, ast.emptyNode) - if p.tok.xkind != pxEquals: - parMessage(p, errColonOrEqualsExpected, $(p.tok)) - if p.tok.xkind == pxEquals: - getTok(p) - skipCom(p, result) - addSon(result, parseExpr(p)) - else: - addSon(result, ast.emptyNode) - if p.tok.xkind == pxSemicolon: - getTok(p) - skipCom(p, result) - -proc parseRecordCase(p: var TParser): PNode = - var b, c: PNode - result = newNodeP(nkRecCase, p) - getTok(p) - var a = newNodeP(nkIdentDefs, p) - addSon(a, rawIdent(p)) - eat(p, pxColon) - addSon(a, parseTypeDesc(p)) - addSon(a, ast.emptyNode) - addSon(result, a) - eat(p, pxOf) - skipCom(p, result) - while true: - case p.tok.xkind - of pxEof, pxEnd: - break - of pxElse: - b = newNodeP(nkElse, p) - getTok(p) - else: - b = newNodeP(nkOfBranch, p) - while (p.tok.xkind != pxEof) and (p.tok.xkind != pxColon): - addSon(b, rangeExpr(p)) - opt(p, pxComma) - skipCom(p, b) - eat(p, pxColon) - skipCom(p, b) - c = newNodeP(nkRecList, p) - eat(p, pxParLe) - while (p.tok.xkind != pxParRi) and (p.tok.xkind != pxEof): - addSon(c, parseIdentColonEquals(p, rawIdent)) - opt(p, pxSemicolon) - skipCom(p, lastSon(c)) - eat(p, pxParRi) - opt(p, pxSemicolon) - if sonsLen(c) > 0: skipCom(p, lastSon(c)) - else: addSon(c, newNodeP(nkNilLit, p)) - addSon(b, c) - addSon(result, b) - if b.kind == nkElse: break - -proc parseRecordPart(p: var TParser): PNode = - result = ast.emptyNode - while (p.tok.xkind != pxEof) and (p.tok.xkind != pxEnd): - if result.kind == nkEmpty: result = newNodeP(nkRecList, p) - case p.tok.xkind - of pxSymbol: - addSon(result, parseIdentColonEquals(p, rawIdent)) - opt(p, pxSemicolon) - skipCom(p, lastSon(result)) - of pxCase: - addSon(result, parseRecordCase(p)) - of pxComment: - skipCom(p, lastSon(result)) - else: - parMessage(p, errIdentifierExpected, $p.tok) - break - -proc exSymbol(n: var PNode) = - case n.kind - of nkPostfix: - discard - of nkPragmaExpr: - exSymbol(n.sons[0]) - of nkIdent, nkAccQuoted: - var a = newNodeI(nkPostFix, n.info) - addSon(a, newIdentNode(getIdent("*"), n.info)) - addSon(a, n) - n = a - else: internalError(n.info, "exSymbol(): " & $n.kind) - -proc fixRecordDef(n: var PNode) = - case n.kind - of nkRecCase: - fixRecordDef(n.sons[0]) - for i in countup(1, sonsLen(n) - 1): - var length = sonsLen(n.sons[i]) - fixRecordDef(n.sons[i].sons[length - 1]) - of nkRecList, nkRecWhen, nkElse, nkOfBranch, nkElifBranch, nkObjectTy: - for i in countup(0, sonsLen(n) - 1): fixRecordDef(n.sons[i]) - of nkIdentDefs: - for i in countup(0, sonsLen(n) - 3): exSymbol(n.sons[i]) - of nkNilLit, nkEmpty: discard - else: internalError(n.info, "fixRecordDef(): " & $n.kind) - -proc addPragmaToIdent(ident: var PNode, pragma: PNode) = - var pragmasNode: PNode - if ident.kind != nkPragmaExpr: - pragmasNode = newNodeI(nkPragma, ident.info) - var e = newNodeI(nkPragmaExpr, ident.info) - addSon(e, ident) - addSon(e, pragmasNode) - ident = e - else: - pragmasNode = ident.sons[1] - if pragmasNode.kind != nkPragma: - internalError(ident.info, "addPragmaToIdent") - addSon(pragmasNode, pragma) - -proc parseRecordBody(p: var TParser, result, definition: PNode) = - skipCom(p, result) - var a = parseRecordPart(p) - if result.kind != nkTupleTy: fixRecordDef(a) - addSon(result, a) - eat(p, pxEnd) - case p.tok.xkind - of pxSymbol: - if p.tok.ident.id == getIdent("acyclic").id: - if definition != nil: - addPragmaToIdent(definition.sons[0], newIdentNodeP(p.tok.ident, p)) - else: - internalError(result.info, "anonymous record is not supported") - getTok(p) - else: - internalError(result.info, "parseRecordBody") - of pxCommand: - if definition != nil: addPragmaToIdent(definition.sons[0], parseCommand(p)) - else: internalError(result.info, "anonymous record is not supported") - else: - discard - opt(p, pxSemicolon) - skipCom(p, result) - -proc parseRecordOrObject(p: var TParser, kind: TNodeKind, - definition: PNode): PNode = - result = newNodeP(kind, p) - getTok(p) - addSon(result, ast.emptyNode) - if p.tok.xkind == pxParLe: - var a = newNodeP(nkOfInherit, p) - getTok(p) - addSon(a, parseTypeDesc(p)) - addSon(result, a) - eat(p, pxParRi) - else: - addSon(result, ast.emptyNode) - parseRecordBody(p, result, definition) - -proc parseTypeDesc(p: var TParser, definition: PNode = nil): PNode = - var oldcontext = p.context - p.context = conTypeDesc - if p.tok.xkind == pxPacked: getTok(p) - case p.tok.xkind - of pxCommand: - result = parseCommand(p, definition) - of pxProcedure, pxFunction: - result = parseRoutineType(p) - of pxRecord: - getTok(p) - if p.tok.xkind == pxCommand: - result = parseCommand(p) - if result.kind != nkTupleTy: internalError(result.info, "parseTypeDesc") - parseRecordBody(p, result, definition) - var a = lastSon(result) # embed nkRecList directly into nkTupleTy - for i in countup(0, sonsLen(a) - 1): - if i == 0: result.sons[sonsLen(result) - 1] = a.sons[0] - else: addSon(result, a.sons[i]) - else: - result = newNodeP(nkObjectTy, p) - addSon(result, ast.emptyNode) - addSon(result, ast.emptyNode) - parseRecordBody(p, result, definition) - if definition != nil: - addPragmaToIdent(definition.sons[0], newIdentNodeP(getIdent("final"), p)) - else: - internalError(result.info, "anonymous record is not supported") - of pxObject: result = parseRecordOrObject(p, nkObjectTy, definition) - of pxParLe: result = parseEnum(p) - of pxArray: - result = newNodeP(nkBracketExpr, p) - getTok(p) - if p.tok.xkind == pxBracketLe: - addSon(result, newIdentNodeP(getIdent("array"), p)) - getTok(p) - addSon(result, rangeExpr(p)) - eat(p, pxBracketRi) - else: - if p.inParamList: addSon(result, newIdentNodeP(getIdent("openarray"), p)) - else: addSon(result, newIdentNodeP(getIdent("seq"), p)) - eat(p, pxOf) - addSon(result, parseTypeDesc(p)) - of pxSet: - result = newNodeP(nkBracketExpr, p) - getTok(p) - eat(p, pxOf) - addSon(result, newIdentNodeP(getIdent("set"), p)) - addSon(result, parseTypeDesc(p)) - of pxHat: - getTok(p) - if p.tok.xkind == pxCommand: result = parseCommand(p) - elif pfRefs in p.flags: result = newNodeP(nkRefTy, p) - else: result = newNodeP(nkPtrTy, p) - addSon(result, parseTypeDesc(p)) - of pxType: - getTok(p) - result = parseTypeDesc(p) - else: - var a = primary(p) - if p.tok.xkind == pxDotDot: - result = newNodeP(nkBracketExpr, p) - var r = newNodeP(nkRange, p) - addSon(result, newIdentNodeP(getIdent("range"), p)) - getTok(p) - addSon(r, a) - addSon(r, parseExpr(p)) - addSon(result, r) - else: - result = a - p.context = oldcontext - -proc parseTypeDef(p: var TParser): PNode = - result = newNodeP(nkTypeDef, p) - addSon(result, identVis(p)) - addSon(result, ast.emptyNode) # generic params - if p.tok.xkind == pxEquals: - getTok(p) - skipCom(p, result) - addSon(result, parseTypeDesc(p, result)) - else: - addSon(result, ast.emptyNode) - if p.tok.xkind == pxSemicolon: - getTok(p) - skipCom(p, result) - -proc parseTypeSection(p: var TParser): PNode = - result = newNodeP(nkTypeSection, p) - getTok(p) - skipCom(p, result) - while p.tok.xkind == pxSymbol: - addSon(result, parseTypeDef(p)) - -proc parseConstant(p: var TParser): PNode = - result = newNodeP(nkConstDef, p) - addSon(result, identVis(p)) - if p.tok.xkind == pxColon: - getTok(p) - skipCom(p, result) - addSon(result, parseTypeDesc(p)) - else: - addSon(result, ast.emptyNode) - if p.tok.xkind != pxEquals: - parMessage(p, errColonOrEqualsExpected, $(p.tok)) - if p.tok.xkind == pxEquals: - getTok(p) - skipCom(p, result) - addSon(result, parseExpr(p)) - else: - addSon(result, ast.emptyNode) - if p.tok.xkind == pxSemicolon: - getTok(p) - skipCom(p, result) - -proc parseConstSection(p: var TParser): PNode = - result = newNodeP(nkConstSection, p) - getTok(p) - skipCom(p, result) - while p.tok.xkind == pxSymbol: - addSon(result, parseConstant(p)) - -proc parseVar(p: var TParser): PNode = - result = newNodeP(nkVarSection, p) - getTok(p) - skipCom(p, result) - while p.tok.xkind == pxSymbol: - addSon(result, parseIdentColonEquals(p, identVis)) - p.lastVarSection = result - -proc parseRoutine(p: var TParser): PNode = - var noBody: bool - result = newNodeP(nkProcDef, p) - getTok(p) - skipCom(p, result) - expectIdent(p) - addSon(result, identVis(p)) - # patterns, generic parameters: - addSon(result, ast.emptyNode) - addSon(result, ast.emptyNode) - addSon(result, parseParamList(p)) - opt(p, pxSemicolon) - addSon(result, parseRoutineSpecifiers(p, noBody)) - addSon(result, ast.emptyNode) - if (p.section == seInterface) or noBody: - addSon(result, ast.emptyNode) - else: - var stmts = newNodeP(nkStmtList, p) - while true: - case p.tok.xkind - of pxVar: addSon(stmts, parseVar(p)) - of pxConst: addSon(stmts, parseConstSection(p)) - of pxType: addSon(stmts, parseTypeSection(p)) - of pxComment: skipCom(p, result) - of pxBegin: break - else: - parMessage(p, errTokenExpected, "begin") - break - var a = parseStmt(p) - for i in countup(0, sonsLen(a) - 1): addSon(stmts, a.sons[i]) - addSon(result, stmts) - -proc fixExit(p: var TParser, n: PNode): bool = - if (p.tok.ident.id == getIdent("exit").id): - var length = sonsLen(n) - if (length <= 0): return - var a = n.sons[length-1] - if (a.kind == nkAsgn) and (a.sons[0].kind == nkIdent) and - (a.sons[0].ident.id == getIdent("result").id): - delSon(a, 0) - a.kind = nkReturnStmt - result = true - getTok(p) - opt(p, pxSemicolon) - skipCom(p, a) - -proc fixVarSection(p: var TParser, counter: PNode) = - if p.lastVarSection == nil: return - assert(counter.kind == nkIdent) - for i in countup(0, sonsLen(p.lastVarSection) - 1): - var v = p.lastVarSection.sons[i] - for j in countup(0, sonsLen(v) - 3): - if v.sons[j].ident.id == counter.ident.id: - delSon(v, j) - if sonsLen(v) <= 2: - delSon(p.lastVarSection, i) - return - -proc exSymbols(n: PNode) = - case n.kind - of nkEmpty..nkNilLit: discard - of nkProcDef..nkIteratorDef: exSymbol(n.sons[namePos]) - of nkWhenStmt, nkStmtList: - for i in countup(0, sonsLen(n) - 1): exSymbols(n.sons[i]) - of nkVarSection, nkConstSection: - for i in countup(0, sonsLen(n) - 1): exSymbol(n.sons[i].sons[0]) - of nkTypeSection: - for i in countup(0, sonsLen(n) - 1): - exSymbol(n.sons[i].sons[0]) - if n.sons[i].sons[2].kind == nkObjectTy: - fixRecordDef(n.sons[i].sons[2]) - else: discard - -proc parseBegin(p: var TParser, result: PNode) = - getTok(p) - while true: - case p.tok.xkind - of pxComment: addSon(result, parseStmt(p)) - of pxSymbol: - if not fixExit(p, result): addSon(result, parseStmt(p)) - of pxEnd: - getTok(p) - break - of pxSemicolon: getTok(p) - of pxEof: parMessage(p, errExprExpected) - else: - var a = parseStmt(p) - if a.kind != nkEmpty: addSon(result, a) - if sonsLen(result) == 0: addSon(result, newNodeP(nkNilLit, p)) - -proc parseStmt(p: var TParser): PNode = - var oldcontext = p.context - p.context = conStmt - result = ast.emptyNode - case p.tok.xkind - of pxBegin: - result = newNodeP(nkStmtList, p) - parseBegin(p, result) - of pxCommand: result = parseCommand(p) - of pxCurlyDirLe, pxStarDirLe: - if isHandledDirective(p): result = parseDirective(p) - of pxIf: result = parseIf(p) - of pxWhile: result = parseWhile(p) - of pxRepeat: result = parseRepeat(p) - of pxCase: result = parseCase(p) - of pxTry: result = parseTry(p) - of pxProcedure, pxFunction: result = parseRoutine(p) - of pxType: result = parseTypeSection(p) - of pxConst: result = parseConstSection(p) - of pxVar: result = parseVar(p) - of pxFor: - result = parseFor(p) - fixVarSection(p, result.sons[0]) - of pxRaise: result = parseRaise(p) - of pxUses: result = parseUsesStmt(p) - of pxProgram, pxUnit, pxLibrary: - # skip the pointless header - while not (p.tok.xkind in {pxSemicolon, pxEof}): getTok(p) - getTok(p) - of pxInitialization: getTok(p) # just skip the token - of pxImplementation: - p.section = seImplementation - result = newNodeP(nkCommentStmt, p) - result.comment = "# implementation" - getTok(p) - of pxInterface: - p.section = seInterface - getTok(p) - of pxComment: - result = newNodeP(nkCommentStmt, p) - skipCom(p, result) - of pxSemicolon: getTok(p) - of pxSymbol: - if p.tok.ident.id == getIdent("break").id: - result = newNodeP(nkBreakStmt, p) - getTok(p) - skipCom(p, result) - addSon(result, ast.emptyNode) - elif p.tok.ident.id == getIdent("continue").id: - result = newNodeP(nkContinueStmt, p) - getTok(p) - skipCom(p, result) - addSon(result, ast.emptyNode) - elif p.tok.ident.id == getIdent("exit").id: - result = newNodeP(nkReturnStmt, p) - getTok(p) - skipCom(p, result) - addSon(result, ast.emptyNode) - else: - result = parseExprStmt(p) - of pxDot: getTok(p) # BUGFIX for ``end.`` in main program - else: result = parseExprStmt(p) - opt(p, pxSemicolon) - if result.kind != nkEmpty: skipCom(p, result) - p.context = oldcontext - -proc parseUnit(p: var TParser): PNode = - result = newNodeP(nkStmtList, p) - getTok(p) # read first token - while true: - case p.tok.xkind - of pxEof, pxEnd: break - of pxBegin: parseBegin(p, result) - of pxCurlyDirLe, pxStarDirLe: - if isHandledDirective(p): addSon(result, parseDirective(p)) - else: parMessage(p, errXNotAllowedHere, p.tok.ident.s) - else: addSon(result, parseStmt(p)) - opt(p, pxEnd) - opt(p, pxDot) - if p.tok.xkind != pxEof: - addSon(result, parseStmt(p)) # comments after final 'end.' - diff --git a/doc/c2nim.txt b/doc/c2nim.txt deleted file mode 100644 index 237af7fb22..0000000000 --- a/doc/c2nim.txt +++ /dev/null @@ -1,295 +0,0 @@ -======================= - c2nim User's manual -======================= - -:Author: Andreas Rumpf -:Version: |nimrodversion| - -.. contents:: - -Introduction -============ - - "We all make choices. But in the end our choices make us." - - -c2nim is a tool to translate Ansi C code to Nimrod. The output is -human-readable Nimrod code that is meant to be tweaked by hand after the -translation process. c2nim is no real compiler! - -c2nim is preliminary meant to translate C header files. Because of this, the -preprocessor is part of the parser. For example: - -.. code-block:: C - #define abc 123 - #define xyz 789 - -Is translated into: - -.. code-block:: Nimrod - const - abc* = 123 - xyz* = 789 - - -c2nim is meant to translate fragments of C code and thus does not follow -include files. c2nim cannot parse all of Ansi C and many constructs cannot -be represented in Nimrod: for example `duff's device`:idx: cannot be translated -to Nimrod. - - -Preprocessor support -==================== - -Even though the translation process is not perfect, it is often the case that -the translated Nimrod code does not need any tweaking by hand. In other cases -it may be preferable to modify the input file instead of the generated Nimrod -code so that c2nim can parse it properly. c2nim's preprocessor defines the -symbol ``C2NIM`` that can be used to mark code sections: - -.. code-block:: C - #ifndef C2NIM - // C2NIM should ignore this prototype: - int fprintf(FILE* f, const char* frmt, ...); - #endif - -The ``C2NIM`` symbol is only recognized in ``#ifdef`` and ``#ifndef`` -constructs! ``#if defined(C2NIM)`` does **not** work. - -c2nim *processes* ``#ifdef C2NIM`` and ``#ifndef C2NIM`` directives, but other -``#if[def]`` directives are *translated* into Nimrod's ``when`` construct: - -.. code-block:: C - #ifdef DEBUG - # define OUT(x) printf("%s\n", x) - #else - # define OUT(x) - #endif - -Is translated into: - -.. code-block:: Nimrod - when defined(debug): - template OUT*(x: expr): expr = - printf("%s\x0A", x) - else: - template OUT*(x: expr): stmt = - discard - -As can been seen from the example, C's macros with parameters are mapped -to Nimrod's templates. This mapping is the best one can do, but it is of course -not accurate: Nimrod's templates operate on syntax trees whereas C's -macros work on the token level. c2nim cannot translate any macro that contains -the ``##`` token concatenation operator. - -c2nim's preprocessor supports special directives that affect how the output -is generated. They should be put into a ``#ifdef C2NIM`` section so that -ordinary C compilers ignore them. - - -``#skipinclude`` directive --------------------------- -**Note**: There is also a ``--skipinclude`` command line option that can be -used for the same purpose. - -By default, c2nim translates an ``#include`` that is not followed by ``<`` -(like in ``#include ``) to a Nimrod ``import`` statement. This -directive tells c2nim to just skip any ``#include``. - - -``#stdcall`` and ``#cdecl`` directives --------------------------------------- -**Note**: There are also ``--stdcall`` and ``--cdecl`` command line options -that can be used for the same purpose. - -These directives tell c2nim that it should annotate every proc (or proc type) -with the ``stdcall`` / ``cdecl`` calling convention. - - -``#dynlib`` directive ---------------------- -**Note**: There is also a ``--dynlib`` command line option that can be used for -the same purpose. - -This directive tells c2nim that it should annotate every proc that resulted -from a C function prototype with the ``dynlib`` pragma: - -.. code-block:: C - - #ifdef C2NIM - # dynlib iupdll - # cdecl - # if defined(windows) - # define iupdll "iup.dll" - # elif defined(macosx) - # define iupdll "libiup.dylib" - # else - # define iupdll "libiup.so" - # endif - #endif - - int IupConvertXYToPos(PIhandle ih, int x, int y); - -Is translated to: - -.. code-block:: Nimrod - when defined(windows): - const iupdll* = "iup.dll" - elif defined(macosx): - const iupdll* = "libiup.dylib" - else: - const iupdll* = "libiup.so" - - proc IupConvertXYToPos*(ih: PIhandle, x: cint, y: cint): cint {. - importc: "IupConvertXYToPos", cdecl, dynlib: iupdll.} - -Note how the example contains extra C code to declare the ``iupdll`` symbol -in the generated Nimrod code. - - -``#header`` directive ---------------------- -**Note**: There is also a ``--header`` command line option that can be used for -the same purpose. - -The ``#header`` directive tells c2nim that it should annotate every proc that -resulted from a C function prototype and every exported variable and type with -the ``header`` pragma: - -.. code-block:: C - - #ifdef C2NIM - # header "iup.h" - #endif - - int IupConvertXYToPos(PIhandle ih, int x, int y); - -Is translated to: - -.. code-block:: Nimrod - proc IupConvertXYToPos*(ih: PIhandle, x: cint, y: cint): cint {. - importc: "IupConvertXYToPos", header: "iup.h".} - -The ``#header`` and the ``#dynlib`` directives are mutually exclusive. -A binding that uses ``dynlib`` is much more preferable over one that uses -``header``! The Nimrod compiler might drop support for the ``header`` pragma -in the future as it cannot work for backends that do not generate C code. - - -``#prefix`` and ``#suffix`` directives --------------------------------------- - -**Note**: There are also ``--prefix`` and ``--suffix`` command line options -that can be used for the same purpose. - -c2nim does not do any name mangling by default. However the -``#prefix`` and ``#suffix`` directives can be used to strip prefixes and -suffixes from the identifiers in the C code: - -.. code-block:: C - - #ifdef C2NIM - # prefix Iup - # dynlib dllname - # cdecl - #endif - - int IupConvertXYToPos(PIhandle ih, int x, int y); - -Is translated to: - -.. code-block:: Nimrod - - proc ConvertXYToPos*(ih: PIhandle, x: cint, y: cint): cint {. - importc: "IupConvertXYToPos", cdecl, dynlib: dllname.} - - -``#mangle`` directive ---------------------- - -Even more sophisticated name mangling can be achieved by the ``#mangle`` -directive: It takes a PEG pattern and format string that specify how the -identifier should be converted: - -.. code-block:: C - #mangle "'GTK_'{.*}" "TGtk$1" - -For convenience the PEG pattern and the replacement can be single identifiers -too, there is no need to quote them: - -.. code-block:: C - #mangle ssize_t int - // is short for: - #mangle "'ssize_t'" "int" - - -``#private`` directive ----------------------- - -By default c2nim marks every top level identifier (proc name, variable, etc.) -as exported (the export marker is ``*`` in Nimrod). With the ``#private`` -directive identifiers can be marked as private so that the resulting Nimrod -module does not export them. The ``#private`` directive takes a PEG pattern: - -.. code-block:: C - #private "@('_'!.)" // all identifiers ending in '_' are private - -Note: The pattern refers to the original C identifiers, not to the resulting -identifiers after mangling! - - -``#skipcomments`` directive ---------------------------- -**Note**: There is also a ``--skipcomments`` command line option that can be -used for the same purpose. - -The ``#skipcomments`` directive can be put into the C code to make c2nim -ignore comments and not copy them into the generated Nimrod file. - - -``#typeprefixes`` directive ---------------------------- -**Note**: There is also a ``--typeprefixes`` command line option that can be -used for the same purpose. - -The ``#typeprefixes`` directive can be put into the C code to make c2nim -generate the ``T`` or ``P`` prefix for every defined type. - - -``#def`` directive ------------------- - -Often C code contains special macros that affect the declaration of a function -prototype but confuse c2nim's parser: - -.. code-block:: C - // does not parse! - EXTERN(int) f(void); - EXTERN(int) g(void); - -Instead of removing ``EXTERN()`` from the input source file (which cannot be -done reliably even with a regular expression!), one can tell c2nim -that ``EXPORT`` is a macro that should be expanded by c2nim too: - -.. code-block:: C - #ifdef C2NIM - # def EXTERN(x) static x - #endif - // parses now! - EXTERN(int) f(void); - EXTERN(int) g(void); - -``#def`` is very similar to C's ``#define``, so in general the macro definition -can be copied and pasted into a ``#def`` directive. - - -Limitations -=========== - -* C's ``,`` operator (comma operator) is not supported. -* C's ``union`` are translated to Nimrod's objects and only the first field - is included in the object type. This way there is a high chance that it is - binary compatible to the union. -* The condition in a ``do while(condition)`` statement must be ``0``. -* Lots of other small issues... - diff --git a/koch.nim b/koch.nim index 15ee3732de..dff6ede989 100644 --- a/koch.nim +++ b/koch.nim @@ -93,10 +93,9 @@ proc buildTool(toolname, args: string) = copyFile(dest="bin"/ splitFile(toolname).name.exe, source=toolname.exe) proc inno(args: string) = - # make sure we have generated the c2nim and niminst executables: + # make sure we have generated the niminst executables: buildTool("tools/niminst/niminst", args) buildTool("tools/nimgrep", args) - buildTool("compiler/c2nim/c2nim", args) exec("tools" / "niminst" / "niminst --var:version=$# inno compiler/nimrod" % NimrodVersion) diff --git a/todo.txt b/todo.txt index 9b96cec478..d9d91b1ec4 100644 --- a/todo.txt +++ b/todo.txt @@ -1,8 +1,6 @@ version 0.9.6 ============= -- move pas2nim into its own repository -- tester: .elf - overloading of '='; general lift mechanism diff --git a/web/nimrod.ini b/web/nimrod.ini index ed8236c3ee..eb9ffa6b49 100644 --- a/web/nimrod.ini +++ b/web/nimrod.ini @@ -37,8 +37,8 @@ UNIX. We don't believe this to be a coincidence. - Jeremy S. Anderson.""" [Documentation] doc: "endb;intern;apis;lib;manual;tut1;tut2;nimrodc;overview;filters;trmacros" -doc: "tools;c2nim;niminst;nimgrep;gc;estp;idetools;docgen;koch" -pdf: "manual;lib;tut1;tut2;nimrodc;c2nim;niminst;gc" +doc: "tools;niminst;nimgrep;gc;estp;idetools;docgen;koch" +pdf: "manual;lib;tut1;tut2;nimrodc;niminst;gc" srcdoc2: "system.nim;impure/graphics;wrappers/sdl" srcdoc2: "core/macros;pure/marshal;core/typeinfo;core/unsigned" srcdoc2: "impure/re;pure/sockets" From c591db16c854780cae2f97ec096fed9835a8511b Mon Sep 17 00:00:00 2001 From: def Date: Wed, 9 Jul 2014 18:43:00 +0200 Subject: [PATCH 013/234] Add reversed proc --- lib/pure/algorithm.nim | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/lib/pure/algorithm.nim b/lib/pure/algorithm.nim index 86d329763e..7af1b2ad86 100644 --- a/lib/pure/algorithm.nim +++ b/lib/pure/algorithm.nim @@ -34,6 +34,20 @@ proc reverse*[T](a: var openArray[T]) = ## reverses the array `a`. reverse(a, 0, a.high) +proc reversed*[T](a: openArray[T], first, last: int): seq[T] = + ## returns the reverse of the array `a[first..last]`. + result = newSeq[T](last - first) + var x = first + var y = last + while x < last: + result[x] = a[y] + dec(y) + inc(x) + +proc reversed*[T](a: openArray[T]): seq[T] = + ## returns the reverse of the array `a`. + reversed(a, 0, a.high) + proc binarySearch*[T](a: openArray[T], key: T): int = ## binary search for `key` in `a`. Returns -1 if not found. var b = len(a) From 8b796763a37a41be107b1f4aae50b28a56a3cdb9 Mon Sep 17 00:00:00 2001 From: def Date: Wed, 9 Jul 2014 18:54:05 +0200 Subject: [PATCH 014/234] Fix to included last element in reversed --- lib/pure/algorithm.nim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/pure/algorithm.nim b/lib/pure/algorithm.nim index 7af1b2ad86..89c83a8a43 100644 --- a/lib/pure/algorithm.nim +++ b/lib/pure/algorithm.nim @@ -36,10 +36,10 @@ proc reverse*[T](a: var openArray[T]) = proc reversed*[T](a: openArray[T], first, last: int): seq[T] = ## returns the reverse of the array `a[first..last]`. - result = newSeq[T](last - first) + result = newSeq[T](last - first + 1) var x = first var y = last - while x < last: + while x <= last: result[x] = a[y] dec(y) inc(x) From 66fad123916924b42228487067eb155af830bef1 Mon Sep 17 00:00:00 2001 From: def Date: Wed, 9 Jul 2014 20:40:01 +0200 Subject: [PATCH 015/234] Change wordwrap to remove separators at newlines --- lib/pure/strutils.nim | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim index e642f6a99d..51392ba504 100644 --- a/lib/pure/strutils.nim +++ b/lib/pure/strutils.nim @@ -535,7 +535,12 @@ proc wordWrap*(s: string, maxLineWidth = 80, ## word wraps `s`. result = newStringOfCap(s.len + s.len shr 6) var spaceLeft = maxLineWidth + var lastSep = "" for word, isSep in tokenize(s, seps): + if isSep: + lastSep = word + spaceLeft = spaceLeft - len(word) + continue if len(word) > spaceLeft: if splitLongWords and len(word) > maxLineWidth: result.add(substr(word, 0, spaceLeft-1)) @@ -554,7 +559,8 @@ proc wordWrap*(s: string, maxLineWidth = 80, result.add(word) else: spaceLeft = spaceLeft - len(word) - result.add(word) + result.add(lastSep & word) + lastSep.setLen(0) proc unindent*(s: string, eatAllIndent = false): string {. noSideEffect, rtl, extern: "nsuUnindent".} = From ce3d1b302ebf30d93697be9c85112350bb9e4eb0 Mon Sep 17 00:00:00 2001 From: def Date: Wed, 9 Jul 2014 21:25:39 +0200 Subject: [PATCH 016/234] Update news.txt --- web/news.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/web/news.txt b/web/news.txt index eef71a2f7a..d432a0e95a 100644 --- a/web/news.txt +++ b/web/news.txt @@ -20,6 +20,7 @@ News - Added module ``cpuinfo``. - Added module ``threadpool``. - ``sequtils.distnct`` has been renamed to ``sequtils.deduplicate``. + - Added ``algorithm.reversed`` 2014-04-21 Version 0.9.4 released From fc6a799fc68092998f352ef5689eed2b7f847e1b Mon Sep 17 00:00:00 2001 From: def Date: Sat, 12 Jul 2014 03:04:43 +0200 Subject: [PATCH 017/234] Add random() for openarrays --- lib/pure/math.nim | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/pure/math.nim b/lib/pure/math.nim index 2f7a696b90..78154cdad7 100644 --- a/lib/pure/math.nim +++ b/lib/pure/math.nim @@ -279,8 +279,13 @@ proc `mod`*(x, y: float): float = result = if y == 0.0: x else: x - y * (x/y).floor proc random*[T](x: TSlice[T]): T = + ## For a slice `a .. b` returns a value in the range `a .. b-1`. result = random(x.b - x.a) + x.a - + +proc random[T](a: openarray[T]): T = + ## returns a random element from the openarray `a`. + result = a[random(a.low..a.len)] + type TRunningStat* {.pure,final.} = object ## an accumulator for statistical data n*: int ## number of pushed data From 7c51f67e859d364fcfed515351a3c7657386561b Mon Sep 17 00:00:00 2001 From: Grzegorz Adam Hankiewicz Date: Sat, 12 Jul 2014 10:45:32 +0200 Subject: [PATCH 018/234] Improves docstring contents and visibility of paramStr and friends. --- lib/pure/os.nim | 80 ++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 69 insertions(+), 11 deletions(-) diff --git a/lib/pure/os.nim b/lib/pure/os.nim index 0b4538abc7..380c9e6e78 100644 --- a/lib/pure/os.nim +++ b/lib/pure/os.nim @@ -1560,7 +1560,52 @@ proc getTempDir*(): string {.rtl, extern: "nos$1", tags: [FReadEnv].} = when defined(windows): return string(getEnv("TEMP")) & "\\" else: return "/tmp/" -when defined(windows): +when defined(nimdoc): + # Common forward declaration docstring block for parameter retrieval procs. + proc paramCount*(): int {.tags: [FReadIO].} = + ## Returns the number of `command line arguments`:idx: given to the + ## application. + ## + ## If your binary was called without parameters this will return zero. You + ## can later query each individual paramater with `paramStr() <#paramStr>`_ + ## or retrieve all of them in one go with `commandLineParams() + ## <#commandLineParams>`_. + ## + ## **Availability**: On Posix there is no portable way to get the command + ## line from a DLL and thus the proc isn't defined in this environment. You + ## can test for its availability with `defined() `_. + ## Example: + ## + ## .. code-block:: nimrod + ## when defined(paramCount): + ## # Use paramCount() here + ## else: + ## # Do something else! + + proc paramStr*(i: int): TaintedString {.tags: [FReadIO].} = + ## Returns the `i`-th `command line argument`:idx: given to the application. + ## + ## `i` should be in the range `1..paramCount()`, the `EInvalidIndex` + ## exception will be raised for invalid values. Instead of iterating over + ## `paramCount() <#paramCount>`_ with this proc you can call the + ## convenience `commandLineParams() <#commandLineParams>`_. + ## + ## It is possible to call ``paramStr(0)`` but this will return OS specific + ## contents (usually the name of the invoked executable). You should avoid + ## this and call `getAppFilename() <#getAppFilename>`_ instead. + ## + ## **Availability**: On Posix there is no portable way to get the command + ## line from a DLL and thus the proc isn't defined in this environment. You + ## can test for its availability with `defined() `_. + ## Example: + ## + ## .. code-block:: nimrod + ## when defined(paramStr): + ## # Use paramStr() here + ## else: + ## # Do something else! + +elif defined(windows): # Since we support GUI applications with Nimrod, we sometimes generate # a WinMain entry proc. But a WinMain proc has no access to the parsed # command line arguments. The way to get them differs. Thus we parse them @@ -1570,18 +1615,13 @@ when defined(windows): ownArgv {.threadvar.}: seq[string] proc paramCount*(): int {.rtl, extern: "nos$1", tags: [FReadIO].} = - ## Returns the number of `command line arguments`:idx: given to the - ## application. + # Docstring in nimdoc block. if isNil(ownArgv): ownArgv = parseCmdLine($getCommandLine()) result = ownArgv.len-1 proc paramStr*(i: int): TaintedString {.rtl, extern: "nos$1", tags: [FReadIO].} = - ## Returns the `i`-th `command line argument`:idx: given to the - ## application. - ## - ## `i` should be in the range `1..paramCount()`, else - ## the `EOutOfIndex` exception is raised. + # Docstring in nimdoc block. if isNil(ownArgv): ownArgv = parseCmdLine($getCommandLine()) return TaintedString(ownArgv[i]) @@ -1592,13 +1632,31 @@ elif not defined(createNimRtl): cmdLine {.importc: "cmdLine".}: cstringArray proc paramStr*(i: int): TaintedString {.tags: [FReadIO].} = - if i < cmdCount and i >= 0: return TaintedString($cmdLine[i]) + # Docstring in nimdoc block. + if i < cmdCount and i >= 0: result = TaintedString($cmdLine[i]) raise newException(EInvalidIndex, "invalid index") - proc paramCount*(): int {.tags: [FReadIO].} = return cmdCount-1 + proc paramCount*(): int {.tags: [FReadIO].} = + # Docstring in nimdoc block. + result = cmdCount-1 -when defined(paramCount): +when defined(paramCount) or defined(nimdoc): proc commandLineParams*(): seq[TaintedString] = + ## Convenience proc which returns the command line parameters. + ## + ## This returns **only** the parameters. If you want to get the application + ## executable filename, call `getAppFilename() <#getAppFilename>`_. + ## + ## **Availability**: On Posix there is no portable way to get the command + ## line from a DLL and thus the proc isn't defined in this environment. You + ## can test for its availability with `defined() `_. + ## Example: + ## + ## .. code-block:: nimrod + ## when defined(commandLineParams): + ## # Use commandLineParams() here + ## else: + ## # Do something else! result = @[] for i in 1..paramCount(): result.add(paramStr(i)) From b1a494e8b917750f92cb41692fa550e37243a22c Mon Sep 17 00:00:00 2001 From: def Date: Mon, 14 Jul 2014 14:44:58 +0200 Subject: [PATCH 019/234] Add missing complex arithmetic procs --- lib/pure/complex.nim | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/lib/pure/complex.nim b/lib/pure/complex.nim index df08ace723..1392b73aa5 100644 --- a/lib/pure/complex.nim +++ b/lib/pure/complex.nim @@ -113,6 +113,45 @@ proc `*` *(x: TComplex, y: float): TComplex = result.im = x.im * y +proc `+=` *(x: var TComplex, y: TComplex) = + ## Add `y` to `x`. + x.re += y.re + x.im += y.im + +proc `+=` *(x: var TComplex, y: float) = + ## Add `y` to the complex number `x`. + x.re += y + +proc `-=` *(x: var TComplex, y: TComplex) = + ## Subtract `y` from `x`. + x.re -= y.re + x.im -= y.im + +proc `-=` *(x: var TComplex, y: float) = + ## Subtract `y` from the complex number `x`. + x.re -= y + +proc `*=` *(x: var TComplex, y: TComplex) = + ## Multiply `y` to `x`. + let im = x.im * y.re + x.re * y.im + x.re = x.re * y.re - x.im * y.im + x.im = im + +proc `*=` *(x: var TComplex, y: float) = + ## Multiply `y` to the complex number `x`. + x.re *= y + x.im *= y + +proc `/=` *(x: var TComplex, y: TComplex) = + ## Divide `x` by `y` in place. + x = x / y + +proc `/=` *(x : var TComplex, y: float) = + ## Divide complex `x` by float `y` in place. + x.re /= y + x.im /= y + + proc abs*(z: TComplex): float = ## Return the distance from (0,0) to `z`. From 5bfea58ffb9fd731131bbbd3f3d077cb69c5f419 Mon Sep 17 00:00:00 2001 From: def Date: Mon, 14 Jul 2014 15:03:09 +0200 Subject: [PATCH 020/234] Add missing difference and to sets module --- lib/pure/collections/sets.nim | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lib/pure/collections/sets.nim b/lib/pure/collections/sets.nim index 4ba67cb2e4..2f0c4d3d2d 100644 --- a/lib/pure/collections/sets.nim +++ b/lib/pure/collections/sets.nim @@ -167,6 +167,12 @@ proc intersection*[A](s1, s2: TSet[A]): TSet[A] = for item in s1: if item in s2: incl(result, item) +proc difference*[A](s1, s2: TSet[A]): TSet[A] = + ## returns a new set of all items that are contained in `s1`, but not in `s2` + result = s1 + for item in s2: + if contains(result, item): excl(result, item) + proc symmetricDifference*[A](s1, s2: TSet[A]): TSet[A] = ## returns a new set of all items that are contained in either ## `s1` or `s2`, but not both @@ -182,6 +188,10 @@ proc `*`*[A](s1, s2: TSet[A]): TSet[A] {.inline.} = ## alias for `intersection` result = intersection(s1, s2) +proc `-`*[A](s1, s2: TSet[A]): TSet[A] {.inline.} = + ## alias for `difference` + result = difference(s1, s2) + proc `-+-`*[A](s1, s2: TSet[A]): TSet[A] {.inline.} = ## alias for `symmetricDifference` result = symmetricDifference(s1, s2) From 68c3c8ebfafbcd169bceaf2bebed8f7af8dbf124 Mon Sep 17 00:00:00 2001 From: def Date: Mon, 14 Jul 2014 17:56:19 +0200 Subject: [PATCH 021/234] More effificent TSet difference --- lib/pure/collections/sets.nim | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/pure/collections/sets.nim b/lib/pure/collections/sets.nim index 2f0c4d3d2d..f1eed00042 100644 --- a/lib/pure/collections/sets.nim +++ b/lib/pure/collections/sets.nim @@ -169,9 +169,10 @@ proc intersection*[A](s1, s2: TSet[A]): TSet[A] = proc difference*[A](s1, s2: TSet[A]): TSet[A] = ## returns a new set of all items that are contained in `s1`, but not in `s2` - result = s1 - for item in s2: - if contains(result, item): excl(result, item) + result = initSet[A]() + for item in s1: + if not contains(s2, item): + incl(result, item) proc symmetricDifference*[A](s1, s2: TSet[A]): TSet[A] = ## returns a new set of all items that are contained in either From 54d61d2f665d47e361cad6c6c1075a9aca2de4d3 Mon Sep 17 00:00:00 2001 From: def Date: Tue, 15 Jul 2014 02:16:12 +0200 Subject: [PATCH 022/234] Add TSet difference tests --- tests/sets/tsets3.nim | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/tests/sets/tsets3.nim b/tests/sets/tsets3.nim index d2b15d72d1..f599f8e7d6 100644 --- a/tests/sets/tsets3.nim +++ b/tests/sets/tsets3.nim @@ -74,8 +74,27 @@ block symmetricDifference: assert((s3 -+- s3) == initSet[int]()) assert((s3 -+- s1) == s1_s3) +block difference: + let + s1_s2 = difference(s1, s2) + s1_s3 = difference(s1, s3) + s2_s3 = s2 - s3 + + assert s1_s2.len == 2 + assert s1_s3.len == 5 + assert s2_s3.len == 3 + + for i in s1: + assert i in s1_s2 xor i in s2 + assert i in s1_s3 xor i in s3 + for i in s2: + assert i in s2_s3 xor i in s3 + + assert((s2 - s2) == initSet[int]()) + assert((s1 - s3 - s1) == s1 -+- s3) + block disjoint: assert(not disjoint(s1, s2)) assert disjoint(s1, s3) assert(not disjoint(s2, s3)) - assert(not disjoint(s2, s2)) \ No newline at end of file + assert(not disjoint(s2, s2)) From fd0e809934f78111f77f273f3edb39053757b97a Mon Sep 17 00:00:00 2001 From: Araq Date: Tue, 15 Jul 2014 09:58:57 +0200 Subject: [PATCH 023/234] fixes #1362 --- compiler/semstmts.nim | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 3cb9691eb9..4d06b201e8 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -661,7 +661,8 @@ proc semFor(c: PContext, n: PNode): PNode = n.sons[length-2] = semExprNoDeref(c, n.sons[length-2], {efWantIterator}) var call = n.sons[length-2] let isCallExpr = call.kind in nkCallKinds - if isCallExpr and call[0].kind == nkSym and call[0].sym.magic != mNone: + if isCallExpr and call[0].kind == nkSym and + call[0].sym.magic in {mFields, mFieldPairs, mOmpParFor}: if call.sons[0].sym.magic == mOmpParFor: result = semForVars(c, n) result.kind = nkParForStmt From c14e7565f8a3ef49568ea4f9d13a68b3fb54efb3 Mon Sep 17 00:00:00 2001 From: Araq Date: Tue, 15 Jul 2014 20:26:45 +0200 Subject: [PATCH 024/234] fixes #1355 --- compiler/semexprs.nim | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 7f97124e12..7deb46af9a 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -82,7 +82,8 @@ proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode = case skipTypes(s.typ, abstractInst-{tyTypeDesc}).kind of tyNil, tyChar, tyInt..tyInt64, tyFloat..tyFloat128, tyTuple, tySet, tyUInt..tyUInt64: - result = inlineConst(n, s) + if s.magic == mNone: result = inlineConst(n, s) + else: result = newSymNode(s, n.info) of tyArrayConstr, tySequence: # Consider:: # const x = [] From 89c2793fb563172a7930d355d37e5d939db7d6ca Mon Sep 17 00:00:00 2001 From: def Date: Tue, 15 Jul 2014 21:22:39 +0200 Subject: [PATCH 025/234] Stop paramStr from always throwing an exception --- lib/pure/os.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pure/os.nim b/lib/pure/os.nim index 380c9e6e78..a7f4f7d916 100644 --- a/lib/pure/os.nim +++ b/lib/pure/os.nim @@ -1633,7 +1633,7 @@ elif not defined(createNimRtl): proc paramStr*(i: int): TaintedString {.tags: [FReadIO].} = # Docstring in nimdoc block. - if i < cmdCount and i >= 0: result = TaintedString($cmdLine[i]) + if i < cmdCount and i >= 0: return TaintedString($cmdLine[i]) raise newException(EInvalidIndex, "invalid index") proc paramCount*(): int {.tags: [FReadIO].} = From a7911addf71fdfbf5008afd938b49116d462d908 Mon Sep 17 00:00:00 2001 From: Araq Date: Wed, 16 Jul 2014 00:41:03 +0200 Subject: [PATCH 026/234] parseBiggestFloat is now builtin --- compiler/ast.nim | 2 +- compiler/ccgexprs.nim | 3 +- compiler/condsyms.nim | 1 + compiler/vm.nim | 14 +++- compiler/vmdef.nim | 2 +- compiler/vmgen.nim | 18 +++++ lib/pure/parseutils.nim | 164 ++++++++++++++++++++-------------------- lib/system/ansi_c.nim | 5 +- lib/system/jssys.nim | 84 ++++++++++++++++++++ lib/system/sysstr.nim | 111 +++++++++++++++++++++++++-- 10 files changed, 309 insertions(+), 95 deletions(-) diff --git a/compiler/ast.nim b/compiler/ast.nim index 9b8218071c..bdb8d1c23e 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -553,7 +553,7 @@ type mInRange, mInSet, mRepr, mExit, mSetLengthStr, mSetLengthSeq, mIsPartOf, mAstToStr, mParallel, mSwap, mIsNil, mArrToSeq, mCopyStr, mCopyStrLast, - mNewString, mNewStringOfCap, + mNewString, mNewStringOfCap, mParseBiggestFloat, mReset, mArray, mOpenArray, mRange, mSet, mSeq, mVarargs, mOrdinal, diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 4698082f1a..95167e1576 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -1640,7 +1640,8 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) = of mIncl, mExcl, mCard, mLtSet, mLeSet, mEqSet, mMulSet, mPlusSet, mMinusSet, mInSet: genSetOp(p, e, d, op) - of mNewString, mNewStringOfCap, mCopyStr, mCopyStrLast, mExit: + of mNewString, mNewStringOfCap, mCopyStr, mCopyStrLast, mExit, + mParseBiggestFloat: var opr = e.sons[0].sym if lfNoDecl notin opr.loc.flags: discard cgsym(p.module, opr.loc.r.ropeToStr) diff --git a/compiler/condsyms.nim b/compiler/condsyms.nim index 17bb5db55a..76026a59d5 100644 --- a/compiler/condsyms.nim +++ b/compiler/condsyms.nim @@ -50,6 +50,7 @@ proc initDefines*() = defineSymbol("nimunion") defineSymbol("nimnewshared") defineSymbol("nimrequiresnimframe") + defineSymbol("nimparsebiggestfloatmagic") # add platform specific symbols: case targetCPU diff --git a/compiler/vm.nim b/compiler/vm.nim index 66595856ab..aedbb92b43 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -16,7 +16,7 @@ import ast except getstr import strutils, astalgo, msgs, vmdef, vmgen, nimsets, types, passes, unsigned, - parser, vmdeps, idents, trees, renderer, options, transf + parser, vmdeps, idents, trees, renderer, options, transf, parseutils from semfold import leValueConv, ordinalValToString from evaltempl import evalTemplate @@ -776,6 +776,18 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = createStr regs[ra] regs[ra].node.strVal = substr(regs[rb].node.strVal, regs[rc].intVal.int, regs[rd].intVal.int) + of opcParseFloat: + decodeBC(rkInt) + inc pc + assert c.code[pc].opcode == opcParseFloat + let rd = c.code[pc].regA + var rcAddr = addr(regs[rc]) + if rcAddr.kind == rkRegisterAddr: rcAddr = rcAddr.regAddr + elif regs[rc].kind != rkFloat: + myreset(regs[rc]) + regs[rc].kind = rkFloat + regs[ra].intVal = parseBiggestFloat(regs[rb].node.strVal, + rcAddr.floatVal, regs[rd].intVal.int) of opcRangeChck: let rb = instr.regB let rc = instr.regC diff --git a/compiler/vmdef.nim b/compiler/vmdef.nim index c391d8415f..873d8eebd9 100644 --- a/compiler/vmdef.nim +++ b/compiler/vmdef.nim @@ -66,7 +66,7 @@ type opcMulSet, opcPlusSet, opcMinusSet, opcSymdiffSet, opcConcatStr, opcContainsSet, opcRepr, opcSetLenStr, opcSetLenSeq, opcSwap, opcIsNil, opcOf, opcIs, - opcSubStr, opcConv, opcCast, opcQuit, opcReset, + opcSubStr, opcParseFloat, opcConv, opcCast, opcQuit, opcReset, opcNarrowS, opcNarrowU, opcAddStrCh, diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim index c1ec637ddb..fd0c3fc69c 100644 --- a/compiler/vmgen.nim +++ b/compiler/vmgen.nim @@ -852,6 +852,24 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) = c.freeTemp(tmp1) c.freeTemp(tmp2) c.freeTemp(tmp3) + of mParseBiggestFloat: + if dest < 0: dest = c.getTemp(n.typ) + var d2: TRegister + # skip 'nkHiddenAddr': + let d2AsNode = n.sons[2].sons[0] + if needsAsgnPatch(d2AsNode): + d2 = c.getTemp(getSysType(tyFloat)) + else: + d2 = c.genx(d2AsNode) + var + tmp1 = c.genx(n.sons[1]) + tmp3 = c.genx(n.sons[3]) + c.gABC(n, opcParseFloat, dest, tmp1, d2) + c.gABC(n, opcParseFloat, tmp3) + c.freeTemp(tmp1) + c.freeTemp(tmp3) + c.genAsgnPatch(d2AsNode, d2) + c.freeTemp(d2) of mReset: unused(n, dest) var d = c.genx(n.sons[1]) diff --git a/lib/pure/parseutils.nim b/lib/pure/parseutils.nim index 9b3f79a74e..06ee07aa83 100644 --- a/lib/pure/parseutils.nim +++ b/lib/pure/parseutils.nim @@ -231,94 +231,96 @@ proc parseInt*(s: string, number: var int, start = 0): int {. else: number = int(res) -proc parseBiggestFloat*(s: string, number: var BiggestFloat, start = 0): int {. - rtl, extern: "npuParseBiggestFloat", noSideEffect.} = - ## parses a float starting at `start` and stores the value into `number`. - ## Result is the number of processed chars or 0 if a parsing error - ## occurred. +when defined(nimParseBiggestFloatMagic): + proc parseBiggestFloat*(s: string, number: var BiggestFloat, start = 0): int {. + magic: "ParseBiggestFloat", importc: "nimParseBiggestFloat", noSideEffect.} + ## parses a float starting at `start` and stores the value into `number`. + ## Result is the number of processed chars or 0 if a parsing error + ## occurred. +else: + proc tenToThePowerOf(b: int): BiggestFloat = + var b = b + var a = 10.0 + result = 1.0 + while true: + if (b and 1) == 1: + result *= a + b = b shr 1 + if b == 0: break + a *= a - type struct_lconv {.importc: "struct lconv",header:"".} = - object - # Unneeded fields have been omitted. - decimal_point: cstring - - proc localeconv(): ptr struct_lconv {.importc, header: "", - noSideEffect.} - - proc strtod(buf: cstring, endptr: ptr cstring): float64 {.importc, - header: "", noSideEffect.} - - # This routine leverages `strtod()` for the non-trivial task of - # parsing floating point numbers correctly. Because `strtod()` is - # locale-dependent with respect to the radix character, we create - # a copy where the decimal point is replaced with the locale's - # radix character. - - var - i = start - sign = 1.0 - t = "" - hasdigits = false - - # Sign? - if s[i] == '+' or s[i] == '-': - if s[i] == '-': + proc parseBiggestFloat*(s: string, number: var BiggestFloat, start = 0): int {. + rtl, extern: "npuParseBiggestFloat", noSideEffect.} = + ## parses a float starting at `start` and stores the value into `number`. + ## Result is the number of processed chars or 0 if there occured a parsing + ## error. + var + esign = 1.0 + sign = 1.0 + i = start + exponent: int + flags: int + number = 0.0 + if s[i] == '+': inc(i) + elif s[i] == '-': sign = -1.0 - add(t, s[i]) - inc(i) - - # NaN? - if s[i] == 'N' or s[i] == 'n': - if s[i+1] == 'A' or s[i+1] == 'a': - if s[i+2] == 'N' or s[i+2] == 'n': - if s[i+3] notin IdentChars: - number = NaN - return i+3 - start - return 0 - - # Inf? - if s[i] == 'I' or s[i] == 'i': - if s[i+1] == 'N' or s[i+1] == 'n': - if s[i+2] == 'F' or s[i+2] == 'f': - if s[i+3] notin IdentChars: - number = Inf*sign - return i+3 - start - return 0 - - # Integer part? - while s[i] in {'0'..'9'}: - hasdigits = true - add(t, s[i]) - inc(i) - while s[i] == '_': inc(i) - - # Fractional part? - if s[i] == '.': - add(t, localeconv().decimal_point) - inc(i) - while s[i] in {'0'..'9'}: - hasdigits = true - add(t, s[i]) inc(i) - while s[i] == '_': inc(i) - if not hasdigits: - return 0 - - # Exponent? - if s[i] in {'e', 'E'}: - add(t, s[i]) - inc(i) - if s[i] in {'+', '-'}: - add(t, s[i]) - inc(i) - if s[i] notin {'0'..'9'}: + if s[i] == 'N' or s[i] == 'n': + if s[i+1] == 'A' or s[i+1] == 'a': + if s[i+2] == 'N' or s[i+2] == 'n': + if s[i+3] notin IdentChars: + number = NaN + return i+3 - start + return 0 + if s[i] == 'I' or s[i] == 'i': + if s[i+1] == 'N' or s[i+1] == 'n': + if s[i+2] == 'F' or s[i+2] == 'f': + if s[i+3] notin IdentChars: + number = Inf*sign + return i+3 - start return 0 while s[i] in {'0'..'9'}: - add(t, s[i]) + # Read integer part + flags = flags or 1 + number = number * 10.0 + toFloat(ord(s[i]) - ord('0')) inc(i) while s[i] == '_': inc(i) - number = strtod(t, nil) - result = i - start + # Decimal? + if s[i] == '.': + var hd = 1.0 + inc(i) + while s[i] in {'0'..'9'}: + # Read fractional part + flags = flags or 2 + number = number * 10.0 + toFloat(ord(s[i]) - ord('0')) + hd = hd * 10.0 + inc(i) + while s[i] == '_': inc(i) + number = number / hd # this complicated way preserves precision + # Again, read integer and fractional part + if flags == 0: return 0 + # Exponent? + if s[i] in {'e', 'E'}: + inc(i) + if s[i] == '+': + inc(i) + elif s[i] == '-': + esign = -1.0 + inc(i) + if s[i] notin {'0'..'9'}: + return 0 + while s[i] in {'0'..'9'}: + exponent = exponent * 10 + ord(s[i]) - ord('0') + inc(i) + while s[i] == '_': inc(i) + # Calculate Exponent + let hd = tenToThePowerOf(exponent) + if esign > 0.0: number = number * hd + else: number = number / hd + # evaluate sign + number = number * sign + result = i - start + proc parseFloat*(s: string, number: var float, start = 0): int {. rtl, extern: "npuParseFloat", noSideEffect.} = diff --git a/lib/system/ansi_c.nim b/lib/system/ansi_c.nim index da101cc2c6..511a006d30 100644 --- a/lib/system/ansi_c.nim +++ b/lib/system/ansi_c.nim @@ -106,13 +106,10 @@ proc c_fopen(filename, mode: cstring): C_TextFileStar {. importc: "fopen", header: "".} proc c_fclose(f: C_TextFileStar) {.importc: "fclose", header: "".} -proc c_sprintf(buf, frmt: cstring): int {.header: "", +proc c_sprintf(buf, frmt: cstring): cint {.header: "", importc: "sprintf", varargs, noSideEffect.} # we use it only in a way that cannot lead to security issues -proc c_localeconv():ptr cstring {.header: "", - importc: "localeconv", noSideEffect.} - proc c_fread(buf: pointer, size, n: int, f: C_BinaryFileStar): int {. importc: "fread", header: "".} proc c_fseek(f: C_BinaryFileStar, offset: clong, whence: int): int {. diff --git a/lib/system/jssys.nim b/lib/system/jssys.nim index 52f8873cf4..1196a81efd 100644 --- a/lib/system/jssys.nim +++ b/lib/system/jssys.nim @@ -639,3 +639,87 @@ proc addChar(x: string, c: char) {.compilerproc, asmNoStackFrame.} = """ {.pop.} + +proc tenToThePowerOf(b: int): BiggestFloat = + var b = b + var a = 10.0 + result = 1.0 + while true: + if (b and 1) == 1: + result *= a + b = b shr 1 + if b == 0: break + a *= a + +const + IdentChars = {'a'..'z', 'A'..'Z', '0'..'9', '_'} + +# XXX use JS's native way here +proc nimParseBiggestFloat(s: string, number: var BiggestFloat, start = 0): int {. + compilerProc.} = + var + esign = 1.0 + sign = 1.0 + i = start + exponent: int + flags: int + number = 0.0 + if s[i] == '+': inc(i) + elif s[i] == '-': + sign = -1.0 + inc(i) + if s[i] == 'N' or s[i] == 'n': + if s[i+1] == 'A' or s[i+1] == 'a': + if s[i+2] == 'N' or s[i+2] == 'n': + if s[i+3] notin IdentChars: + number = NaN + return i+3 - start + return 0 + if s[i] == 'I' or s[i] == 'i': + if s[i+1] == 'N' or s[i+1] == 'n': + if s[i+2] == 'F' or s[i+2] == 'f': + if s[i+3] notin IdentChars: + number = Inf*sign + return i+3 - start + return 0 + while s[i] in {'0'..'9'}: + # Read integer part + flags = flags or 1 + number = number * 10.0 + toFloat(ord(s[i]) - ord('0')) + inc(i) + while s[i] == '_': inc(i) + # Decimal? + if s[i] == '.': + var hd = 1.0 + inc(i) + while s[i] in {'0'..'9'}: + # Read fractional part + flags = flags or 2 + number = number * 10.0 + toFloat(ord(s[i]) - ord('0')) + hd = hd * 10.0 + inc(i) + while s[i] == '_': inc(i) + number = number / hd # this complicated way preserves precision + # Again, read integer and fractional part + if flags == 0: return 0 + # Exponent? + if s[i] in {'e', 'E'}: + inc(i) + if s[i] == '+': + inc(i) + elif s[i] == '-': + esign = -1.0 + inc(i) + if s[i] notin {'0'..'9'}: + return 0 + while s[i] in {'0'..'9'}: + exponent = exponent * 10 + ord(s[i]) - ord('0') + inc(i) + while s[i] == '_': inc(i) + # Calculate Exponent + let hd = tenToThePowerOf(exponent) + if esign > 0.0: number = number * hd + else: number = number / hd + # evaluate sign + number = number * sign + result = i - start diff --git a/lib/system/sysstr.nim b/lib/system/sysstr.nim index 183ea0c8d1..b3dc9c14eb 100644 --- a/lib/system/sysstr.nim +++ b/lib/system/sysstr.nim @@ -252,15 +252,114 @@ proc nimIntToStr(x: int): string {.compilerRtl.} = proc nimFloatToStr(f: float): string {.compilerproc.} = var buf: array [0..64, char] - var n:int = c_sprintf(buf, "%.16g", f) + var n: int = c_sprintf(buf, "%.16g", f) + var hasDot = false for i in 0..n-1: - if buf[i] notin {'0'..'9','-'}: - return $buf - buf[n] = c_localeconv()[0] - buf[n+1] = '0' - buf[n+2] = '\0' + if buf[i] == ',': + buf[i] = '.' + hasDot = true + elif buf[i] in {'e', 'E', '.'}: + hasDot = true + if not hasDot: + buf[n] = '.' + buf[n+1] = '0' + buf[n+2] = '\0' result = $buf +proc strtod(buf: cstring, endptr: ptr cstring): float64 {.importc, + header: "", noSideEffect.} + +var decimalPoint: char + +proc getDecimalPoint(): char = + result = decimalPoint + if result == '\0': + if strtod("0,5", nil) == 0.5: result = ',' + else: result = '.' + # yes this is threadsafe in practice, spare me: + decimalPoint = result + +const + IdentChars = {'a'..'z', 'A'..'Z', '0'..'9', '_'} + +proc nimParseBiggestFloat(s: string, number: var BiggestFloat, + start = 0): int {.compilerProc.} = + # This routine leverages `strtod()` for the non-trivial task of + # parsing floating point numbers correctly. Because `strtod()` is + # locale-dependent with respect to the radix character, we create + # a copy where the decimal point is replaced with the locale's + # radix character. + var + i = start + sign = 1.0 + t: array[128, char] + ti = 0 + hasdigits = false + + template addToBuf(c) = + if ti < t.high: + t[ti] = c; inc(ti) + + # Sign? + if s[i] == '+' or s[i] == '-': + if s[i] == '-': + sign = -1.0 + t[ti] = s[i] + inc(i); inc(ti) + + # NaN? + if s[i] == 'N' or s[i] == 'n': + if s[i+1] == 'A' or s[i+1] == 'a': + if s[i+2] == 'N' or s[i+2] == 'n': + if s[i+3] notin IdentChars: + number = NaN + return i+3 - start + return 0 + + # Inf? + if s[i] == 'I' or s[i] == 'i': + if s[i+1] == 'N' or s[i+1] == 'n': + if s[i+2] == 'F' or s[i+2] == 'f': + if s[i+3] notin IdentChars: + number = Inf*sign + return i+3 - start + return 0 + + # Integer part? + while s[i] in {'0'..'9'}: + hasdigits = true + addToBuf(s[i]) + inc(i); + while s[i] == '_': inc(i) + + # Fractional part? + if s[i] == '.': + addToBuf(getDecimalPoint()) + inc(i) + while s[i] in {'0'..'9'}: + hasdigits = true + addToBuf(s[i]) + inc(i) + while s[i] == '_': inc(i) + if not hasdigits: + return 0 + + # Exponent? + if s[i] in {'e', 'E'}: + addToBuf(s[i]) + inc(i) + if s[i] in {'+', '-'}: + addToBuf(s[i]) + inc(i) + if s[i] notin {'0'..'9'}: + return 0 + while s[i] in {'0'..'9'}: + addToBuf(s[i]) + inc(i) + while s[i] == '_': inc(i) + number = strtod(t, nil) + result = i - start + proc nimInt64ToStr(x: int64): string {.compilerRtl.} = result = newString(sizeof(x)*4) var i = 0 From e94203ac217460c181b6d098f768d18f3151ef08 Mon Sep 17 00:00:00 2001 From: Araq Date: Wed, 16 Jul 2014 01:09:51 +0200 Subject: [PATCH 027/234] tester should work again --- tests/testament/categories.nim | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tests/testament/categories.nim b/tests/testament/categories.nim index 841eb8159f..02f7dc1d7f 100644 --- a/tests/testament/categories.nim +++ b/tests/testament/categories.nim @@ -312,7 +312,7 @@ proc testBabelPackages(r: var TResults, cat: Category, filter: PackageFilter) = # ---------------------------------------------------------------------------- -const AdditionalCategories = ["debugger", "tools", "examples", "stdlib", "babel-core"] +const AdditionalCategories = ["debugger", "examples", "stdlib", "babel-core"] proc `&.?`(a, b: string): string = # candidate for the stdlib? @@ -336,9 +336,6 @@ proc processCategory(r: var TResults, cat: Category, options: string) = gcTests(r, cat, options) of "debugger": debuggerTests(r, cat, options) - of "tools": - testSpec r, makeTest("compiler/c2nim/c2nim.nim", options, cat) - testSpec r, makeTest("compiler/pas2nim/pas2nim.nim", options, cat) of "manyloc": manyLoc r, cat, options of "threads": From 4dc2925b7a8dbbb20b497f3c151a041b02c5786e Mon Sep 17 00:00:00 2001 From: Araq Date: Wed, 16 Jul 2014 09:00:41 +0200 Subject: [PATCH 028/234] JS compilation works again --- lib/system/jssys.nim | 4 ++-- todo.txt | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/system/jssys.nim b/lib/system/jssys.nim index 1196a81efd..8766906e3a 100644 --- a/lib/system/jssys.nim +++ b/lib/system/jssys.nim @@ -646,10 +646,10 @@ proc tenToThePowerOf(b: int): BiggestFloat = result = 1.0 while true: if (b and 1) == 1: - result *= a + result = result * a b = b shr 1 if b == 0: break - a *= a + a = a * a const IdentChars = {'a'..'z', 'A'..'Z', '0'..'9', '_'} diff --git a/todo.txt b/todo.txt index 16c05186ae..bd8f7f89e4 100644 --- a/todo.txt +++ b/todo.txt @@ -2,7 +2,6 @@ version 0.9.6 ============= - scopes are still broken for generic instantiation! -- integrate the new LL into the devel branch - start experimental branch - overloading of '='; general lift mechanism From ed226eba6dab432ba47f3bb6e4a6b3b1dea64330 Mon Sep 17 00:00:00 2001 From: Araq Date: Wed, 16 Jul 2014 22:32:09 +0200 Subject: [PATCH 029/234] added stack overflow prevention --- lib/nimbase.h | 3 ++- lib/system.nim | 3 ++- lib/system/excpt.nim | 29 ++++++++++++++++++----------- web/news.txt | 3 ++- 4 files changed, 24 insertions(+), 14 deletions(-) diff --git a/lib/nimbase.h b/lib/nimbase.h index cfd33dca18..b430942270 100644 --- a/lib/nimbase.h +++ b/lib/nimbase.h @@ -328,7 +328,8 @@ struct TFrame { NCSTRING procname; NI line; NCSTRING filename; - NI len; + NI16 len; + NI16 calldepth; }; #define nimfr(proc, file) \ diff --git a/lib/system.nim b/lib/system.nim index 3c42385b78..2fb08563aa 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -2001,7 +2001,8 @@ type procname*: cstring ## name of the proc that is currently executing line*: int ## line number of the proc that is currently executing filename*: cstring ## filename of the proc that is currently executing - len*: int ## length of the inspectable slots + len*: int16 ## length of the inspectable slots + calldepth*: int16 ## used for max call depth checking when defined(JS): proc add*(x: var string, y: cstring) {.asmNoStackFrame.} = diff --git a/lib/system/excpt.nim b/lib/system/excpt.nim index 63a61183f6..e1a5a958fe 100644 --- a/lib/system/excpt.nim +++ b/lib/system/excpt.nim @@ -1,7 +1,7 @@ # # # Nimrod's Runtime Library -# (c) Copyright 2012 Andreas Rumpf +# (c) Copyright 2014 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. @@ -44,16 +44,6 @@ var # a global variable for the root of all try blocks currException {.rtlThreadVar.}: ref E_Base -when defined(nimRequiresNimFrame): - proc nimFrame(s: PFrame) {.compilerRtl, inl, exportc: "nimFrame".} = - s.prev = framePtr - framePtr = s -else: - proc pushFrame(s: PFrame) {.compilerRtl, inl, exportc: "nimFrame".} = - # XXX only for backwards compatibility - s.prev = framePtr - framePtr = s - proc popFrame {.compilerRtl, inl.} = framePtr = framePtr.prev @@ -280,6 +270,23 @@ proc getStackTrace(e: ref E_Base): string = else: result = "" +when defined(nimRequiresNimFrame): + proc stackOverflow() {.noinline.} = + writeStackTrace() + showErrorMessage("Stack overflow\n") + quitOrDebug() + + proc nimFrame(s: PFrame) {.compilerRtl, inl, exportc: "nimFrame".} = + s.calldepth = if framePtr == nil: 0 else: framePtr.calldepth+1 + s.prev = framePtr + framePtr = s + if s.calldepth == 2000: stackOverflow() +else: + proc pushFrame(s: PFrame) {.compilerRtl, inl, exportc: "nimFrame".} = + # XXX only for backwards compatibility + s.prev = framePtr + framePtr = s + when defined(endb): var dbgAborting: bool # whether the debugger wants to abort diff --git a/web/news.txt b/web/news.txt index a8d525443f..a913c94ad7 100644 --- a/web/news.txt +++ b/web/news.txt @@ -16,7 +16,8 @@ News now considered for implicit early binding. - ``c2nim`` moved into its own repository and is now a Babel package. - ``pas2nim`` moved into its own repository and is now a Babel package. - + - ``system.$`` for floating point types now produces a human friendly string + representation. Library Additions ----------------- From 94e8e245da0bdab6cf6b04998d229b33a78b9c44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rory=20O=E2=80=99Kane?= Date: Thu, 17 Jul 2014 15:44:18 -0400 Subject: [PATCH 030/234] Fix link to roadmap on site home page https://github.com/Araq/Nimrod/wiki/Feature-Matrix does not exist, while https://github.com/Araq/Nimrod/wiki/Roadmap does. --- web/index.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/index.txt b/web/index.txt index c3459d56bc..947ebb7060 100644 --- a/web/index.txt +++ b/web/index.txt @@ -101,5 +101,5 @@ Roadmap to 1.0 ============== Please have a look at -this `wiki page `_ for +this `wiki page `_ for an up-to-date overview. From 5a3c88d3ad599cc02af9f566e073f868cfaaf559 Mon Sep 17 00:00:00 2001 From: Grzegorz Adam Hankiewicz Date: Fri, 18 Jul 2014 12:54:52 +0200 Subject: [PATCH 031/234] Mentions countLines() may return unexpected values. --- lib/pure/strutils.nim | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim index 51392ba504..949f9e52e7 100644 --- a/lib/pure/strutils.nim +++ b/lib/pure/strutils.nim @@ -280,9 +280,11 @@ iterator split*(s: string, sep: string): string = inc(last, sep.len) iterator splitLines*(s: string): string = - ## Splits the string `s` into its containing lines. Every newline - ## combination (CR, LF, CR-LF) is supported. The result strings contain - ## no trailing ``\n``. + ## Splits the string `s` into its containing lines. + ## + ## Every `character literal `_ newline + ## combination (CR, LF, CR-LF) is supported. The result strings contain no + ## trailing ``\n``. ## ## Example: ## @@ -315,13 +317,25 @@ iterator splitLines*(s: string): string = proc splitLines*(s: string): seq[string] {.noSideEffect, rtl, extern: "nsuSplitLines".} = - ## The same as the `splitLines` iterator, but is a proc that returns a - ## sequence of substrings. + ## The same as the `splitLines <#splitLines.i,string>`_ iterator, but is a + ## proc that returns a sequence of substrings. accumulateResult(splitLines(s)) proc countLines*(s: string): int {.noSideEffect, rtl, extern: "nsuCountLines".} = - ## same as ``len(splitLines(s))``, but much more efficient. + ## Returns the number of new line separators in the string `s`. + ## + ## This is the same as ``len(splitLines(s))``, but much more efficient + ## because it doesn't modify the string creating temporal objects. Every + ## `character literal `_ newline combination + ## (CR, LF, CR-LF) is supported. + ## + ## Despite its name this proc might not actually return the *number of lines* + ## in `s` because the concept of what a line is can vary. For example, a + ## string like ``Hello world`` is a line of text, but the proc will return a + ## value of zero because there are no newline separators. Also, text editors + ## usually don't count trailing newline characters in a text file as a new + ## empty line, but this proc will. var i = 0 while i < s.len: case s[i] From 7f276fa9e033b0de09cddcb767e27c3130d48458 Mon Sep 17 00:00:00 2001 From: Grzegorz Adam Hankiewicz Date: Fri, 18 Jul 2014 13:18:45 +0200 Subject: [PATCH 032/234] Homogenizes docstrings for strutils module. This mostly involves separating the short description string from the full description block, capitalizing it, and adding any worthwhile hyperlinks to other symbols. --- lib/pure/strutils.nim | 250 ++++++++++++++++++++++++++---------------- 1 file changed, 156 insertions(+), 94 deletions(-) diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim index 949f9e52e7..6f8924d83b 100644 --- a/lib/pure/strutils.nim +++ b/lib/pure/strutils.nim @@ -48,9 +48,11 @@ const ## the set of characters a newline terminator can start with AllChars* = {'\x00'..'\xFF'} - ## A set with all the possible characters. Not very useful by its own, you - ## can use it to create *inverted* sets to make the ``find()`` proc find - ## **invalid** characters in strings. Example: + ## A set with all the possible characters. + ## + ## Not very useful by its own, you can use it to create *inverted* sets to + ## make the `find() proc <#find,string,set[char],int>`_ find **invalid** + ## characters in strings. Example: ## ## .. code-block:: nimrod ## let invalid = AllChars - Digits @@ -59,8 +61,11 @@ const proc toLower*(c: char): char {.noSideEffect, procvar, rtl, extern: "nsuToLowerChar".} = - ## Converts `c` into lower case. This works only for the letters A-Z. - ## See `unicode.toLower` for a version that works for any Unicode character. + ## Converts `c` into lower case. + ## + ## This works only for the letters ``A-Z``. See `unicode.toLower + ## `_ for a version that works for any Unicode + ## character. if c in {'A'..'Z'}: result = chr(ord(c) + (ord('a') - ord('A'))) else: @@ -68,16 +73,22 @@ proc toLower*(c: char): char {.noSideEffect, procvar, proc toLower*(s: string): string {.noSideEffect, procvar, rtl, extern: "nsuToLowerStr".} = - ## Converts `s` into lower case. This works only for the letters A-Z. - ## See `unicode.toLower` for a version that works for any Unicode character. + ## Converts `s` into lower case. + ## + ## This works only for the letters ``A-Z``. See `unicode.toLower + ## `_ for a version that works for any Unicode + ## character. result = newString(len(s)) for i in 0..len(s) - 1: result[i] = toLower(s[i]) proc toUpper*(c: char): char {.noSideEffect, procvar, rtl, extern: "nsuToUpperChar".} = - ## Converts `c` into upper case. This works only for the letters a-z. - ## See `unicode.toUpper` for a version that works for any Unicode character. + ## Converts `c` into upper case. + ## + ## This works only for the letters ``A-Z``. See `unicode.toUpper + ## `_ for a version that works for any Unicode + ## character. if c in {'a'..'z'}: result = chr(ord(c) - (ord('a') - ord('A'))) else: @@ -85,8 +96,11 @@ proc toUpper*(c: char): char {.noSideEffect, procvar, proc toUpper*(s: string): string {.noSideEffect, procvar, rtl, extern: "nsuToUpperStr".} = - ## Converts `s` into upper case. This works only for the letters a-z. - ## See `unicode.toUpper` for a version that works for any Unicode character. + ## Converts `s` into upper case. + ## + ## This works only for the letters ``A-Z``. See `unicode.toUpper + ## `_ for a version that works for any Unicode + ## character. result = newString(len(s)) for i in 0..len(s) - 1: result[i] = toUpper(s[i]) @@ -94,13 +108,16 @@ proc toUpper*(s: string): string {.noSideEffect, procvar, proc capitalize*(s: string): string {.noSideEffect, procvar, rtl, extern: "nsuCapitalize".} = ## Converts the first character of `s` into upper case. - ## This works only for the letters a-z. + ## + ## This works only for the letters ``A-Z``. result = toUpper(s[0]) & substr(s, 1) proc normalize*(s: string): string {.noSideEffect, procvar, rtl, extern: "nsuNormalize".} = - ## Normalizes the string `s`. That means to convert it to lower case and - ## remove any '_'. This is needed for Nimrod identifiers for example. + ## Normalizes the string `s`. + ## + ## That means to convert it to lower case and remove any '_'. This is needed + ## for Nimrod identifiers for example. result = newString(s.len) var j = 0 for i in 0..len(s) - 1: @@ -155,6 +172,7 @@ proc cmpIgnoreStyle*(a, b: string): int {.noSideEffect, proc strip*(s: string, leading = true, trailing = true): string {.noSideEffect, rtl, extern: "nsuStrip", operator: 5.} = ## Strips whitespace from `s` and returns the resulting string. + ## ## If `leading` is true, leading whitespace is stripped. ## If `trailing` is true, trailing whitespace is stripped. const @@ -169,8 +187,10 @@ proc strip*(s: string, leading = true, trailing = true): string {.noSideEffect, result = substr(s, first, last) proc toOctal*(c: char): string {.noSideEffect, rtl, extern: "nsuToOctal".} = - ## Converts a character `c` to its octal representation. The resulting - ## string may not have a leading zero. Its length is always exactly 3. + ## Converts a character `c` to its octal representation. + ## + ## The resulting string may not have a leading zero. Its length is always + ## exactly 3. result = newString(3) var val = ord(c) for i in countdown(2, 0): @@ -348,28 +368,30 @@ proc countLines*(s: string): int {.noSideEffect, proc split*(s: string, seps: set[char] = Whitespace): seq[string] {. noSideEffect, rtl, extern: "nsuSplitCharSet".} = - ## The same as the `split` iterator, but is a proc that returns a - ## sequence of substrings. + ## The same as the `split iterator <#split.i,string,set[char]>`_, but is a + ## proc that returns a sequence of substrings. accumulateResult(split(s, seps)) proc split*(s: string, sep: char): seq[string] {.noSideEffect, rtl, extern: "nsuSplitChar".} = - ## The same as the `split` iterator, but is a proc that returns a sequence - ## of substrings. + ## The same as the `split iterator <#split.i,string,char>`_, but is a proc + ## that returns a sequence of substrings. accumulateResult(split(s, sep)) proc split*(s: string, sep: string): seq[string] {.noSideEffect, rtl, extern: "nsuSplitString".} = ## Splits the string `s` into substrings using a string separator. ## - ## Substrings are separated by the string `sep`. + ## Substrings are separated by the string `sep`. This is a wrapper around the + ## `split iterator <#split.i,string,string>`_. accumulateResult(split(s, sep)) proc toHex*(x: BiggestInt, len: int): string {.noSideEffect, rtl, extern: "nsuToHex".} = - ## Converts `x` to its hexadecimal representation. The resulting string - ## will be exactly `len` characters long. No prefix like ``0x`` - ## is generated. `x` is treated as an unsigned value. + ## Converts `x` to its hexadecimal representation. + ## + ## The resulting string will be exactly `len` characters long. No prefix like + ## ``0x`` is generated. `x` is treated as an unsigned value. const HexChars = "0123456789ABCDEF" var @@ -381,9 +403,10 @@ proc toHex*(x: BiggestInt, len: int): string {.noSideEffect, proc intToStr*(x: int, minchars: int = 1): string {.noSideEffect, rtl, extern: "nsuIntToStr".} = - ## Converts `x` to its decimal representation. The resulting string - ## will be minimally `minchars` characters long. This is achieved by - ## adding leading zeros. + ## Converts `x` to its decimal representation. + ## + ## The resulting string will be minimally `minchars` characters long. This is + ## achieved by adding leading zeros. result = $abs(x) for i in 1 .. minchars - len(result): result = '0' & result @@ -392,16 +415,18 @@ proc intToStr*(x: int, minchars: int = 1): string {.noSideEffect, proc parseInt*(s: string): int {.noSideEffect, procvar, rtl, extern: "nsuParseInt".} = - ## Parses a decimal integer value contained in `s`. If `s` is not - ## a valid integer, `EInvalidValue` is raised. + ## Parses a decimal integer value contained in `s`. + ## + ## If `s` is not a valid integer, `EInvalidValue` is raised. var L = parseutils.parseInt(s, result, 0) if L != s.len or L == 0: raise newException(EInvalidValue, "invalid integer: " & s) proc parseBiggestInt*(s: string): BiggestInt {.noSideEffect, procvar, rtl, extern: "nsuParseBiggestInt".} = - ## Parses a decimal integer value contained in `s`. If `s` is not - ## a valid integer, `EInvalidValue` is raised. + ## Parses a decimal integer value contained in `s`. + ## + ## If `s` is not a valid integer, `EInvalidValue` is raised. var L = parseutils.parseBiggestInt(s, result, 0) if L != s.len or L == 0: raise newException(EInvalidValue, "invalid integer: " & s) @@ -417,10 +442,11 @@ proc parseFloat*(s: string): float {.noSideEffect, procvar, proc parseHexInt*(s: string): int {.noSideEffect, procvar, rtl, extern: "nsuParseHexInt".} = - ## Parses a hexadecimal integer value contained in `s`. If `s` is not - ## a valid integer, `EInvalidValue` is raised. `s` can have one of the - ## following optional prefixes: ``0x``, ``0X``, ``#``. - ## Underscores within `s` are ignored. + ## Parses a hexadecimal integer value contained in `s`. + ## + ## If `s` is not a valid integer, `EInvalidValue` is raised. `s` can have one + ## of the following optional prefixes: ``0x``, ``0X``, ``#``. Underscores + ## within `s` are ignored. var i = 0 if s[i] == '0' and (s[i+1] == 'x' or s[i+1] == 'X'): inc(i, 2) elif s[i] == '#': inc(i) @@ -440,26 +466,32 @@ proc parseHexInt*(s: string): int {.noSideEffect, procvar, else: raise newException(EInvalidValue, "invalid integer: " & s) proc parseBool*(s: string): bool = - ## Parses a value into a `bool`. If ``s`` is one of the following values: - ## ``y, yes, true, 1, on``, then returns `true`. If ``s`` is one of the - ## following values: ``n, no, false, 0, off``, then returns `false`. - ## If ``s`` is something else a ``EInvalidValue`` exception is raised. + ## Parses a value into a `bool`. + ## + ## If ``s`` is one of the following values: ``y, yes, true, 1, on``, then + ## returns `true`. If ``s`` is one of the following values: ``n, no, false, + ## 0, off``, then returns `false`. If ``s`` is something else a + ## ``EInvalidValue`` exception is raised. case normalize(s) of "y", "yes", "true", "1", "on": result = true of "n", "no", "false", "0", "off": result = false else: raise newException(EInvalidValue, "cannot interpret as a bool: " & s) proc parseEnum*[T: enum](s: string): T = - ## parses an enum ``T``. Raises ``EInvalidValue`` for an invalid value in - ## `s`. The comparison is done in a style insensitive way. + ## Parses an enum ``T``. + ## + ## Raises ``EInvalidValue`` for an invalid value in `s`. The comparison is + ## done in a style insensitive way. for e in low(T)..high(T): if cmpIgnoreStyle(s, $e) == 0: return e raise newException(EInvalidValue, "invalid enum value: " & s) proc parseEnum*[T: enum](s: string, default: T): T = - ## parses an enum ``T``. Uses `default` for an invalid value in - ## `s`. The comparison is done in a style insensitive way. + ## Parses an enum ``T``. + ## + ## Uses `default` for an invalid value in `s`. The comparison is done in a + ## style insensitive way. for e in low(T)..high(T): if cmpIgnoreStyle(s, $e) == 0: return e @@ -489,10 +521,11 @@ proc repeatStr*(count: int, s: string): string {.noSideEffect, proc align*(s: string, count: int, padding = ' '): string {. noSideEffect, rtl, extern: "nsuAlignString".} = ## Aligns a string `s` with `padding`, so that is of length `count`. + ## ## `padding` characters (by default spaces) are added before `s` resulting in ## right alignment. If ``s.len >= count``, no spaces are added and `s` is - ## returned unchanged. If you need to left align a string use the - ## ``repeatChar`` proc. Example: + ## returned unchanged. If you need to left align a string use the `repeatChar + ## proc <#repeatChar>`_. Example: ## ## .. code-block:: nimrod ## assert align("abc", 4) == " abc" @@ -546,7 +579,7 @@ proc wordWrap*(s: string, maxLineWidth = 80, seps: set[char] = Whitespace, newLine = "\n"): string {. noSideEffect, rtl, extern: "nsuWordWrap".} = - ## word wraps `s`. + ## Word wraps `s`. result = newStringOfCap(s.len + s.len shr 6) var spaceLeft = maxLineWidth var lastSep = "" @@ -578,7 +611,7 @@ proc wordWrap*(s: string, maxLineWidth = 80, proc unindent*(s: string, eatAllIndent = false): string {. noSideEffect, rtl, extern: "nsuUnindent".} = - ## unindents `s`. + ## Unindents `s`. result = newStringOfCap(s.len) var i = 0 var pattern = true @@ -606,6 +639,7 @@ proc unindent*(s: string, eatAllIndent = false): string {. proc startsWith*(s, prefix: string): bool {.noSideEffect, rtl, extern: "nsuStartsWith".} = ## Returns true iff ``s`` starts with ``prefix``. + ## ## If ``prefix == ""`` true is returned. var i = 0 while true: @@ -616,6 +650,7 @@ proc startsWith*(s, prefix: string): bool {.noSideEffect, proc endsWith*(s, suffix: string): bool {.noSideEffect, rtl, extern: "nsuEndsWith".} = ## Returns true iff ``s`` ends with ``suffix``. + ## ## If ``suffix == ""`` true is returned. var i = 0 var j = len(s) - len(suffix) @@ -627,6 +662,7 @@ proc endsWith*(s, suffix: string): bool {.noSideEffect, proc continuesWith*(s, substr: string, start: int): bool {.noSideEffect, rtl, extern: "nsuContinuesWith".} = ## Returns true iff ``s`` continues with ``substr`` at position ``start``. + ## ## If ``substr == ""`` true is returned. var i = 0 while true: @@ -636,6 +672,8 @@ proc continuesWith*(s, substr: string, start: int): bool {.noSideEffect, proc addSep*(dest: var string, sep = ", ", startLen = 0) {.noSideEffect, inline.} = + ## Adds a separator to `dest` only if its length is bigger than `startLen`. + ## ## A shorthand for: ## ## .. code-block:: nimrod @@ -655,15 +693,15 @@ proc addSep*(dest: var string, sep = ", ", startLen = 0) {.noSideEffect, if dest.len > startLen: add(dest, sep) proc allCharsInSet*(s: string, theSet: TCharSet): bool = - ## returns true iff each character of `s` is in the set `theSet`. + ## Returns true iff each character of `s` is in the set `theSet`. for c in items(s): if c notin theSet: return false return true proc abbrev*(s: string, possibilities: openArray[string]): int = - ## returns the index of the first item in `possibilities` if not - ## ambiguous; -1 if no item has been found; -2 if multiple items - ## match. + ## Returns the index of the first item in `possibilities` if not ambiguous. + ## + ## Returns -1 if no item has been found and -2 if multiple items match. result = -1 # none found for i in 0..possibilities.len-1: if possibilities[i].startsWith(s): @@ -677,7 +715,7 @@ proc abbrev*(s: string, possibilities: openArray[string]): int = proc join*(a: openArray[string], sep: string): string {. noSideEffect, rtl, extern: "nsuJoinSep".} = - ## concatenates all strings in `a` separating them with `sep`. + ## Concatenates all strings in `a` separating them with `sep`. if len(a) > 0: var L = sep.len * (a.len-1) for i in 0..high(a): inc(L, a[i].len) @@ -691,7 +729,7 @@ proc join*(a: openArray[string], sep: string): string {. proc join*(a: openArray[string]): string {. noSideEffect, rtl, extern: "nsuJoin".} = - ## concatenates all strings in `a`. + ## Concatenates all strings in `a`. if len(a) > 0: var L = 0 for i in 0..high(a): inc(L, a[i].len) @@ -709,7 +747,7 @@ proc preprocessSub(sub: string, a: var TSkipTable) = for i in 0..m-1: a[sub[i]] = m-i proc findAux(s, sub: string, start: int, a: TSkipTable): int = - # fast "quick search" algorithm: + # Fast "quick search" algorithm: var m = len(sub) n = len(s) @@ -725,32 +763,36 @@ proc findAux(s, sub: string, start: int, a: TSkipTable): int = proc find*(s, sub: string, start: int = 0): int {.noSideEffect, rtl, extern: "nsuFindStr", operator: 6.} = - ## Searches for `sub` in `s` starting at position `start`. Searching is - ## case-sensitive. If `sub` is not in `s`, -1 is returned. + ## Searches for `sub` in `s` starting at position `start`. + ## + ## Searching is case-sensitive. If `sub` is not in `s`, -1 is returned. var a {.noinit.}: TSkipTable preprocessSub(sub, a) result = findAux(s, sub, start, a) proc find*(s: string, sub: char, start: int = 0): int {.noSideEffect, rtl, extern: "nsuFindChar".} = - ## Searches for `sub` in `s` starting at position `start`. Searching is - ## case-sensitive. If `sub` is not in `s`, -1 is returned. + ## Searches for `sub` in `s` starting at position `start`. + ## + ## Searching is case-sensitive. If `sub` is not in `s`, -1 is returned. for i in start..len(s)-1: if sub == s[i]: return i return -1 proc find*(s: string, chars: set[char], start: int = 0): int {.noSideEffect, rtl, extern: "nsuFindCharSet".} = - ## Searches for `chars` in `s` starting at position `start`. If `s` contains - ## none of the characters in `chars`, -1 is returned. + ## Searches for `chars` in `s` starting at position `start`. + ## + ## If `s` contains none of the characters in `chars`, -1 is returned. for i in start..s.len-1: if s[i] in chars: return i return -1 proc rfind*(s, sub: string, start: int = -1): int {.noSideEffect.} = ## Searches for `sub` in `s` in reverse, starting at `start` and going - ## backwards to 0. Searching is case-sensitive. If `sub` is not in `s`, -1 is - ## returned. + ## backwards to 0. + ## + ## Searching is case-sensitive. If `sub` is not in `s`, -1 is returned. let realStart = if start == -1: s.len else: start for i in countdown(realStart-sub.len, 0): for j in 0..sub.len-1: @@ -762,10 +804,11 @@ proc rfind*(s, sub: string, start: int = -1): int {.noSideEffect.} = return -1 proc quoteIfContainsWhite*(s: string): string {.deprecated.} = - ## returns ``'"' & s & '"'`` if `s` contains a space and does not - ## start with a quote, else returns `s` - ## DEPRECATED as it was confused for shell quoting function. - ## For this application use osproc.quoteShell. + ## Returns ``'"' & s & '"'`` if `s` contains a space and does not + ## start with a quote, else returns `s`. + ## + ## **DEPRECATED** as it was confused for shell quoting function. For this + ## application use `osproc.quoteShell `_. if find(s, {' ', '\t'}) >= 0 and s[0] != '"': result = '"' & s & '"' else: @@ -801,7 +844,9 @@ proc replace*(s, sub: string, by = ""): string {.noSideEffect, proc replace*(s: string, sub, by: char): string {.noSideEffect, rtl, extern: "nsuReplaceChar".} = - ## optimized version for characters. + ## Replaces `sub` in `s` by the character `by`. + ## + ## Optimized version of `replace <#replace,string,string>`_ for characters. result = newString(s.len) var i = 0 while i < s.len: @@ -811,9 +856,11 @@ proc replace*(s: string, sub, by: char): string {.noSideEffect, proc replaceWord*(s, sub: string, by = ""): string {.noSideEffect, rtl, extern: "nsuReplaceWord".} = - ## Replaces `sub` in `s` by the string `by`. Each occurance of `sub` - ## has to be surrounded by word boundaries (comparable to ``\\w`` in - ## regular expressions), otherwise it is not replaced. + ## Replaces `sub` in `s` by the string `by`. + ## + ## Each occurance of `sub` has to be surrounded by word boundaries + ## (comparable to ``\\w`` in regular expressions), otherwise it is not + ## replaced. const wordChars = {'a'..'z', 'A'..'Z', '0'..'9', '_', '\128'..'\255'} var a {.noinit.}: TSkipTable result = "" @@ -836,8 +883,9 @@ proc replaceWord*(s, sub: string, by = ""): string {.noSideEffect, proc delete*(s: var string, first, last: int) {.noSideEffect, rtl, extern: "nsuDelete".} = - ## Deletes in `s` the characters at position `first` .. `last`. This modifies - ## `s` itself, it does not return a copy. + ## Deletes in `s` the characters at position `first` .. `last`. + ## + ## This modifies `s` itself, it does not return a copy. var i = first var j = last+1 var newLen = len(s)-j+i @@ -849,10 +897,11 @@ proc delete*(s: var string, first, last: int) {.noSideEffect, proc parseOctInt*(s: string): int {.noSideEffect, rtl, extern: "nsuParseOctInt".} = - ## Parses an octal integer value contained in `s`. If `s` is not - ## a valid integer, `EInvalidValue` is raised. `s` can have one of the - ## following optional prefixes: ``0o``, ``0O``. - ## Underscores within `s` are ignored. + ## Parses an octal integer value contained in `s`. + ## + ## If `s` is not a valid integer, `EInvalidValue` is raised. `s` can have one + ## of the following optional prefixes: ``0o``, ``0O``. Underscores within + ## `s` are ignored. var i = 0 if s[i] == '0' and (s[i+1] == 'o' or s[i+1] == 'O'): inc(i, 2) while true: @@ -866,8 +915,10 @@ proc parseOctInt*(s: string): int {.noSideEffect, proc toOct*(x: BiggestInt, len: int): string {.noSideEffect, rtl, extern: "nsuToOct".} = - ## converts `x` into its octal representation. The resulting string is - ## always `len` characters long. No leading ``0o`` prefix is generated. + ## Converts `x` into its octal representation. + ## + ## The resulting string is always `len` characters long. No leading ``0o`` + ## prefix is generated. var mask: BiggestInt = 7 shift: BiggestInt = 0 @@ -880,8 +931,10 @@ proc toOct*(x: BiggestInt, len: int): string {.noSideEffect, proc toBin*(x: BiggestInt, len: int): string {.noSideEffect, rtl, extern: "nsuToBin".} = - ## converts `x` into its binary representation. The resulting string is - ## always `len` characters long. No leading ``0b`` prefix is generated. + ## Converts `x` into its binary representation. + ## + ## The resulting string is always `len` characters long. No leading ``0b`` + ## prefix is generated. var mask: BiggestInt = 1 shift: BiggestInt = 0 @@ -894,7 +947,8 @@ proc toBin*(x: BiggestInt, len: int): string {.noSideEffect, proc insertSep*(s: string, sep = '_', digits = 3): string {.noSideEffect, rtl, extern: "nsuInsertSep".} = - ## inserts the separator `sep` after `digits` digits from right to left. + ## Inserts the separator `sep` after `digits` digits from right to left. + ## ## Even though the algorithm works with any string `s`, it is only useful ## if `s` contains a number. ## Example: ``insertSep("1000000") == "1_000_000"`` @@ -913,7 +967,9 @@ proc insertSep*(s: string, sep = '_', digits = 3): string {.noSideEffect, proc escape*(s: string, prefix = "\"", suffix = "\""): string {.noSideEffect, rtl, extern: "nsuEscape".} = - ## Escapes a string `s`. This does these operations (at the same time): + ## Escapes a string `s`. + ## + ## This does these operations (at the same time): ## * replaces any ``\`` by ``\\`` ## * replaces any ``'`` by ``\'`` ## * replaces any ``"`` by ``\"`` @@ -937,11 +993,13 @@ proc escape*(s: string, prefix = "\"", suffix = "\""): string {.noSideEffect, proc unescape*(s: string, prefix = "\"", suffix = "\""): string {.noSideEffect, rtl, extern: "nsuUnescape".} = - ## Unescapes a string `s`. This complements ``escape`` as it performs the - ## opposite operations. + ## Unescapes a string `s`. ## - ## If `s` does not begin with ``prefix`` and end with ``suffix`` a EInvalidValue - ## exception will be raised. + ## This complements `escape <#escape>`_ as it performs the opposite + ## operations. + ## + ## If `s` does not begin with ``prefix`` and end with ``suffix`` a + ## EInvalidValue exception will be raised. result = newStringOfCap(s.len) var i = 0 if s[0 .. prefix.len-1] != prefix: @@ -975,9 +1033,10 @@ proc unescape*(s: string, prefix = "\"", suffix = "\""): string {.noSideEffect, proc validIdentifier*(s: string): bool {.noSideEffect, rtl, extern: "nsuValidIdentifier".} = - ## returns true if `s` is a valid identifier. A valid identifier starts - ## with a character of the set `IdentStartChars` and is followed by any - ## number of characters of the set `IdentChars`. + ## Returns true if `s` is a valid identifier. + ## + ## A valid identifier starts with a character of the set `IdentStartChars` + ## and is followed by any number of characters of the set `IdentChars`. if s[0] in IdentStartChars: for i in 1..s.len-1: if s[i] notin IdentChars: return false @@ -985,9 +1044,10 @@ proc validIdentifier*(s: string): bool {.noSideEffect, proc editDistance*(a, b: string): int {.noSideEffect, rtl, extern: "nsuEditDistance".} = - ## returns the edit distance between `a` and `b`. This uses the - ## `Levenshtein`:idx: distance algorithm with only a linear memory overhead. - ## This implementation is highly optimized! + ## Returns the edit distance between `a` and `b`. + ## + ## This uses the `Levenshtein`:idx: distance algorithm with only a linear + ## memory overhead. This implementation is highly optimized! var len1 = a.len var len2 = b.len if len1 > len2: @@ -1086,7 +1146,7 @@ type proc formatBiggestFloat*(f: BiggestFloat, format: TFloatFormat = ffDefault, precision: range[0..32] = 16): string {. noSideEffect, operator: 2, rtl, extern: "nsu$1".} = - ## converts a floating point value `f` to a string. + ## Converts a floating point value `f` to a string. ## ## If ``format == ffDecimal`` then precision is the number of digits to ## be printed after the decimal point. @@ -1117,7 +1177,7 @@ proc formatBiggestFloat*(f: BiggestFloat, format: TFloatFormat = ffDefault, proc formatFloat*(f: float, format: TFloatFormat = ffDefault, precision: range[0..32] = 16): string {. noSideEffect, operator: 2, rtl, extern: "nsu$1".} = - ## converts a floating point value `f` to a string. + ## Converts a floating point value `f` to a string. ## ## If ``format == ffDecimal`` then precision is the number of digits to ## be printed after the decimal point. @@ -1212,6 +1272,8 @@ proc addf*(s: var string, formatstr: string, a: varargs[string, `$`]) {. proc `%` *(formatstr: string, a: openArray[string]): string {.noSideEffect, rtl, extern: "nsuFormatOpenArray".} = + ## Interpolates a format string with the values from `a`. + ## ## The `substitution`:idx: operator performs string substitutions in ## `formatstr` and returns a modified `formatstr`. This is often called ## `string interpolation`:idx:. From 4c4ebc93d7bad902fb999094b5f12cb52ff1fbac Mon Sep 17 00:00:00 2001 From: Simon Jakobi Date: Fri, 18 Jul 2014 23:51:17 +0200 Subject: [PATCH 033/234] sequtils: Correct documentation for keepIf proc --- lib/pure/collections/sequtils.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pure/collections/sequtils.nim b/lib/pure/collections/sequtils.nim index e760c5e02b..bc863b0cdd 100644 --- a/lib/pure/collections/sequtils.nim +++ b/lib/pure/collections/sequtils.nim @@ -186,7 +186,7 @@ proc keepIf*[T](seq1: var seq[T], pred: proc(item: T): bool {.closure.}) = ## ## .. code-block:: nimrod ## var floats = @[13.0, 12.5, 5.8, 2.0, 6.1, 9.9, 10.1] - ## filter(floats, proc(x: float): bool = x > 10) + ## keepIf(floats, proc(x: float): bool = x > 10) ## assert floats == @[13.0, 12.5, 10.1] var pos = 0 for i in 0 .. Date: Sat, 19 Jul 2014 00:09:47 +0200 Subject: [PATCH 034/234] sequtils: Complete mapIt documentation example --- lib/pure/collections/sequtils.nim | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/pure/collections/sequtils.nim b/lib/pure/collections/sequtils.nim index e760c5e02b..70e46cec0d 100644 --- a/lib/pure/collections/sequtils.nim +++ b/lib/pure/collections/sequtils.nim @@ -388,6 +388,7 @@ template mapIt*(seq1, typ, pred: expr): expr = ## let ## nums = @[1, 2, 3, 4] ## strings = nums.mapIt(string, $(4 * it)) + ## assert strings == @["4", "8", "12", "16"] var result {.gensym.}: seq[typ] = @[] for it {.inject.} in items(seq1): result.add(pred) From 5a299507db16c6cd8e55c42fc0a1957a084cd44a Mon Sep 17 00:00:00 2001 From: Varriount Date: Fri, 18 Jul 2014 18:17:09 -0400 Subject: [PATCH 035/234] Update nimrod.ini --- web/nimrod.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/nimrod.ini b/web/nimrod.ini index 7b0a91c19c..544446b11e 100644 --- a/web/nimrod.ini +++ b/web/nimrod.ini @@ -37,7 +37,7 @@ UNIX. We don't believe this to be a coincidence. - Jeremy S. Anderson.""" [Documentation] doc: "endb;intern;apis;lib;manual;tut1;tut2;nimrodc;overview;filters" -doc: "tools;c2nim;niminst;nimgrep;gc;estp;idetools;docgen;koch;backends.txt" +doc: "tools;niminst;nimgrep;gc;estp;idetools;docgen;koch;backends.txt" pdf: "manual;lib;tut1;tut2;nimrodc;niminst;gc" srcdoc2: "system.nim;impure/graphics;wrappers/sdl" srcdoc2: "core/macros;pure/marshal;core/typeinfo;core/unsigned" From eafb79b721a0eb461a3097f5a511c1f73994f995 Mon Sep 17 00:00:00 2001 From: Grzegorz Adam Hankiewicz Date: Sat, 19 Jul 2014 13:41:39 +0200 Subject: [PATCH 036/234] Hyperlinks echo variants with noSideEffect pragma. Refs #1379. --- doc/manual.txt | 6 +++--- lib/system.nim | 16 +++++++++++----- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/doc/manual.txt b/doc/manual.txt index 32b0541e9e..54c1477e8c 100644 --- a/doc/manual.txt +++ b/doc/manual.txt @@ -4970,9 +4970,9 @@ or ``ref T`` or ``ptr T`` this means no locations are modified. It is a static error to mark a proc/iterator to have no side effect if the compiler cannot verify this. -As a special semantic rule, the built-in ``debugEcho`` pretends to be free of -side effects, so that it can be used for debugging routines marked as -``noSideEffect``. +As a special semantic rule, the built-in `debugEcho `_ +pretends to be free of side effects, so that it can be used for debugging +routines marked as ``noSideEffect``. **Future directions**: ``func`` may become a keyword and syntactic sugar for a proc with no side effects: diff --git a/lib/system.nim b/lib/system.nim index 2fb08563aa..b43ae52bb4 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -2026,19 +2026,25 @@ elif hostOS != "standalone": {.pop.} proc echo*[T](x: varargs[T, `$`]) {.magic: "Echo", tags: [FWriteIO], gcsafe.} - ## special built-in that takes a variable number of arguments. Each argument + ## Writes and flushes the parameters to the standard output. + ## + ## Special built-in that takes a variable number of arguments. Each argument ## is converted to a string via ``$``, so it works for user-defined ## types that have an overloaded ``$`` operator. ## It is roughly equivalent to ``writeln(stdout, x); flush(stdout)``, but ## available for the JavaScript target too. + ## ## Unlike other IO operations this is guaranteed to be thread-safe as - ## ``echo`` is very often used for debugging convenience. + ## ``echo`` is very often used for debugging convenience. If you want to use + ## ``echo`` inside a `proc without side effects + ## `_ you can use `debugEcho <#debugEcho>`_ + ## instead. proc debugEcho*[T](x: varargs[T, `$`]) {.magic: "Echo", noSideEffect, tags: [], raises: [].} - ## Same as ``echo``, but as a special semantic rule, ``debugEcho`` pretends - ## to be free of side effects, so that it can be used for debugging routines - ## marked as ``noSideEffect``. + ## Same as `echo <#echo>`_, but as a special semantic rule, ``debugEcho`` + ## pretends to be free of side effects, so that it can be used for debugging + ## routines marked as `noSideEffect `_. template newException*(exceptn: typedesc, message: string): expr = ## creates an exception object of type ``exceptn`` and sets its ``msg`` field From be616fc4322ea44078aede9cef12fbc27ad68973 Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Sat, 19 Jul 2014 13:22:58 +0100 Subject: [PATCH 037/234] Fixes #1219. --- lib/pure/parsecfg.nim | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/pure/parsecfg.nim b/lib/pure/parsecfg.nim index 727a8efd83..1d61a967b3 100644 --- a/lib/pure/parsecfg.nim +++ b/lib/pure/parsecfg.nim @@ -350,7 +350,8 @@ proc next*(c: var TCfgParser): TCfgEvent {.rtl, extern: "npc$1".} = rawGetTok(c, c.tok) if c.tok.kind == tkBracketRi: rawGetTok(c, c.tok) - else: + else: + reset(result) result.kind = cfgError result.msg = errorStr(c, "']' expected, but found: " & c.tok.literal) of tkInvalid, tkEquals, tkColon, tkBracketRi: From 60a2d8ad5848ee7d694f64a5978f0bb4fc207ccc Mon Sep 17 00:00:00 2001 From: Simon Jakobi Date: Sat, 19 Jul 2014 14:37:47 +0200 Subject: [PATCH 038/234] Remove unnecessary import --- tests/stdlib/testequivalence.nim | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/stdlib/testequivalence.nim b/tests/stdlib/testequivalence.nim index 7c5d9e3e90..7acaad3408 100644 --- a/tests/stdlib/testequivalence.nim +++ b/tests/stdlib/testequivalence.nim @@ -1,7 +1,6 @@ discard """ output: '''''' """ -import unittest import sets doAssert(toSet(@[1,2,3]) <= toSet(@[1,2,3,4]), "equivalent or subset") From 8968b5114fcbf7c9d4052b06e2a6012aa88a757d Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Sun, 20 Jul 2014 15:11:03 +0100 Subject: [PATCH 039/234] Fixes #1065. --- lib/pure/parseurl.nim | 4 +- lib/pure/uri.nim | 350 +++++++++++++++++++++++++++++++++++++++++- web/news.txt | 4 +- 3 files changed, 348 insertions(+), 10 deletions(-) diff --git a/lib/pure/parseurl.nim b/lib/pure/parseurl.nim index 357d1df0ff..67c6de9050 100644 --- a/lib/pure/parseurl.nim +++ b/lib/pure/parseurl.nim @@ -20,7 +20,7 @@ type scheme, username, password, hostname, port, path, query, anchor: string] -proc parseUrl*(url: string): TUrl = +proc parseUrl*(url: string): TUrl {.deprecated.} = var i = 0 var scheme, username, password: string = "" @@ -86,7 +86,7 @@ proc parseUrl*(url: string): TUrl = return (scheme, username, password, hostname, port, path, query, anchor) -proc `$`*(u: TUrl): string = +proc `$`*(u: TUrl): string {.deprecated.} = ## turns the URL `u` into its string representation. result = "" if u.scheme.len > 0: diff --git a/lib/pure/uri.nim b/lib/pure/uri.nim index ee1226a359..7ec8230338 100644 --- a/lib/pure/uri.nim +++ b/lib/pure/uri.nim @@ -7,17 +7,24 @@ # distribution, for details about the copyright. # -## **Note**: This module will be deprecated in the future and merged into a -## new ``url`` module. +## This module implements URI parsing as specified by RFC 3986. -import strutils +import strutils, parseutils type TUrl* = distinct string -proc `$`*(url: TUrl): string = return string(url) + TUri* = object + scheme*, username*, password*: string + hostname*, port*, path*, query*, anchor*: string -proc `/`*(a, b: TUrl): TUrl = +proc `$`*(url: TUrl): string {.deprecated.} = + ## **Deprecated since 0.9.6**: Use ``TUri`` instead. + return string(url) + +proc `/`*(a, b: TUrl): TUrl {.deprecated.} = ## Joins two URLs together, separating them with / if needed. + ## + ## **Deprecated since 0.9.6**: Use ``TUri`` instead. var urlS = $a var bS = $b if urlS == "": return b @@ -29,9 +36,338 @@ proc `/`*(a, b: TUrl): TUrl = urlS.add(bs) result = TUrl(urlS) -proc add*(url: var TUrl, a: TUrl) = +proc add*(url: var TUrl, a: TUrl) {.deprecated.} = ## Appends url to url. + ## + ## **Deprecated since 0.9.6**: Use ``TUri`` instead. url = url / a +proc parseAuthority(authority: string, result: var TUri) = + var i = 0 + var inPort = false + while true: + case authority[i] + of '@': + result.password = result.port + result.port = "" + result.username = result.hostname + result.hostname = "" + inPort = false + of ':': + inPort = true + of '\0': break + else: + if inPort: + result.port.add(authority[i]) + else: + result.hostname.add(authority[i]) + i.inc + +proc parsePath(uri: string, i: var int, result: var TUri) = + + i.inc parseUntil(uri, result.path, {'?', '#'}, i) + + # The 'mailto' scheme's PATH actually contains the hostname/username + if result.scheme.ToLower() == "mailto": + parseAuthority(result.path, result) + result.path = "" + + if uri[i] == '?': + i.inc # Skip '?' + i.inc parseUntil(uri, result.query, {'#'}, i) + + if uri[i] == '#': + i.inc # Skip '#' + i.inc parseUntil(uri, result.anchor, {}, i) + +proc initUri(): TUri = + result = TUri(scheme: "", username: "", password: "", hostname: "", port: "", + path: "", query: "", anchor: "") + +proc parseUri*(uri: string): TUri = + ## Parses a URI. + result = initUri() + + var i = 0 + + # Check if this is a reference URI (relative URI) + if uri[i] == '/': + parsePath(uri, i, result) + return + + # Scheme + i.inc parseWhile(uri, result.scheme, Letters + Digits + {'+', '-', '.'}, i) + if uri[i] != ':': + # Assume this is a reference URI (relative URI) + i = 0 + result.scheme = "" + parsePath(uri, i, result) + return + i.inc # Skip ':' + + # Authority + if uri[i] == '/' and uri[i+1] == '/': + i.inc(2) # Skip // + var authority = "" + i.inc parseUntil(uri, authority, {'/', '?', '#'}, i) + if authority == "": + raise newException(EInvalidValue, "Expected authority got nothing.") + parseAuthority(authority, result) + + # Path + parsePath(uri, i, result) + +proc removeDotSegments(path: string): string = + var collection: seq[string] = @[] + let endsWithSlash = path[path.len-1] == '/' + var i = 0 + var currentSegment = "" + while true: + case path[i] + of '/': + collection.add(currentSegment) + currentSegment = "" + of '.': + if path[i+1] == '.' and path[i+2] == '/': + if collection.len > 0: + discard collection.pop() + i.inc 3 + continue + elif path[i+1] == '/': + i.inc 2 + continue + currentSegment.add path[i] + of '\0': + if currentSegment != "": + collection.add currentSegment + break + else: + currentSegment.add path[i] + i.inc + + result = collection.join("/") + if endsWithSlash: result.add '/' + +proc merge(base, reference: TUri): string = + # http://tools.ietf.org/html/rfc3986#section-5.2.3 + if base.hostname != "" and base.path == "": + '/' & reference.path + else: + let lastSegment = rfind(base.path, "/") + if lastSegment == -1: + reference.path + else: + base.path[0 .. lastSegment] & reference.path + +proc combine*(base: TUri, reference: TUri): TUri = + ## Combines a base URI with a reference URI. + ## + ## This uses the algorithm specified in + ## `section 5.2.2 of RFC 3986 `_. + ## + ## This means that the slashes inside the base URI's path as well as reference + ## URI's path affect the resulting URI. + ## + ## For building URIs you may wish to use \`/\` instead. + ## + ## Examples: + ## + ## .. code-block:: nimrod + ## let foo = combine(parseUri("http://example.com/foo/bar"), parseUri("/baz")) + ## assert foo.path == "/baz" + ## + ## let bar = combine(parseUri("http://example.com/foo/bar"), parseUri("baz")) + ## assert foo.path == "/foo/baz" + ## + ## let bar = combine(parseUri("http://example.com/foo/bar/"), parseUri("baz")) + ## assert foo.path == "/foo/bar/baz" + + template setAuthority(dest, src: expr): stmt = + dest.hostname = src.hostname + dest.username = src.username + dest.port = src.port + dest.password = src.password + + result = initUri() + if reference.scheme != base.scheme and reference.scheme != "": + result = reference + result.path = removeDotSegments(result.path) + else: + if reference.hostname != "": + setAuthority(result, reference) + result.path = removeDotSegments(reference.path) + result.query = reference.query + else: + if reference.path == "": + result.path = base.path + if reference.query != "": + result.query = reference.query + else: + result.query = base.query + else: + if reference.path.startsWith("/"): + result.path = removeDotSegments(reference.path) + else: + result.path = removeDotSegments(merge(base, reference)) + result.query = reference.query + setAuthority(result, base) + result.scheme = base.scheme + result.anchor = reference.anchor + +proc combine*(uris: varargs[TUri]): TUri = + ## Combines multiple URIs together. + result = uris[0] + for i in 1 .. 0: + result.add(u.scheme) + result.add("://") + if u.username.len > 0: + result.add(u.username) + if u.password.len > 0: + result.add(":") + result.add(u.password) + result.add("@") + result.add(u.hostname) + if u.port.len > 0: + result.add(":") + result.add(u.port) + if u.path.len > 0: + if u.path[0] != '/': result.add("/") + result.add(u.path) + result.add(u.query) + result.add(u.anchor) + when isMainModule: - assert($("http://".TUrl / "localhost:5000".TUrl) == "http://localhost:5000") + block: + let test = parseUri("http://localhost:8080/test") + doAssert test.scheme == "http" + doAssert test.port == "8080" + doAssert test.path == "/test" + doAssert test.hostname == "localhost" + + block: + let test = parseUri("foo://username:password@example.com:8042/over/there" & + "/index.dtb?type=animal&name=narwhal#nose") + doAssert test.scheme == "foo" + doAssert test.username == "username" + doAssert test.password == "password" + doAssert test.hostname == "example.com" + doAssert test.port == "8042" + doAssert test.path == "/over/there/index.dtb" + doAssert test.query == "type=animal&name=narwhal" + doAssert test.anchor == "nose" + + block: + let test = parseUri("urn:example:animal:ferret:nose") + doAssert test.scheme == "urn" + doAssert test.path == "example:animal:ferret:nose" + + block: + let test = parseUri("mailto:username@example.com?subject=Topic") + doAssert test.scheme == "mailto" + doAssert test.username == "username" + doAssert test.hostname == "example.com" + doAssert test.query == "subject=Topic" + + block: + let test = parseUri("magnet:?xt=urn:sha1:72hsga62ba515sbd62&dn=foobar") + doAssert test.scheme == "magnet" + doAssert test.query == "xt=urn:sha1:72hsga62ba515sbd62&dn=foobar" + + block: + let test = parseUri("/test/foo/bar?q=2#asdf") + doAssert test.scheme == "" + doAssert test.path == "/test/foo/bar" + doAssert test.query == "q=2" + doAssert test.anchor == "asdf" + + block: + let test = parseUri("test/no/slash") + doAssert test.path == "test/no/slash" + + # Remove dot segments tests + block: + doAssert removeDotSegments("/foo/bar/baz") == "/foo/bar/baz" + + # Combine tests + block: + let concat = combine(parseUri("http://google.com/foo/bar/"), parseUri("baz")) + doAssert concat.path == "/foo/bar/baz" + doAssert concat.hostname == "google.com" + doAssert concat.scheme == "http" + + block: + let concat = combine(parseUri("http://google.com/foo"), parseUri("/baz")) + doAssert concat.path == "/baz" + doAssert concat.hostname == "google.com" + doAssert concat.scheme == "http" + + block: + let concat = combine(parseUri("http://google.com/foo/test"), parseUri("bar")) + doAssert concat.path == "/foo/bar" + + block: + let concat = combine(parseUri("http://google.com/foo/test"), parseUri("/bar")) + doAssert concat.path == "/bar" + + block: + let concat = combine(parseUri("http://google.com/foo/test"), parseUri("bar")) + doAssert concat.path == "/foo/bar" + + block: + let concat = combine(parseUri("http://google.com/foo/test/"), parseUri("bar")) + doAssert concat.path == "/foo/test/bar" + + block: + let concat = combine(parseUri("http://google.com/foo/test/"), parseUri("bar/")) + doAssert concat.path == "/foo/test/bar/" + + block: + let concat = combine(parseUri("http://google.com/foo/test/"), parseUri("bar/"), + parseUri("baz")) + doAssert concat.path == "/foo/test/bar/baz" + + # `/` tests + block: + let test = parseUri("http://example.com/foo") / "bar/asd" + doAssert test.path == "/foo/bar/asd" + + block: + let test = parseUri("http://example.com/foo/") / "/bar/asd" + doAssert test.path == "/foo/bar/asd" + + diff --git a/web/news.txt b/web/news.txt index a913c94ad7..62a923dcd5 100644 --- a/web/news.txt +++ b/web/news.txt @@ -18,6 +18,8 @@ News - ``pas2nim`` moved into its own repository and is now a Babel package. - ``system.$`` for floating point types now produces a human friendly string representation. + - ``uri.TUrl`` as well as the ``parseurl`` module are now deprecated in favour + of the new ``TUri`` type in the ``uri`` module. Library Additions ----------------- @@ -26,7 +28,7 @@ News - Added module ``threadpool``. - ``sequtils.distnct`` has been renamed to ``sequtils.deduplicate``. - Added ``algorithm.reversed`` - + - Added ``uri.combine`` and ``uri.parseUri``. 2014-04-21 Version 0.9.4 released ================================= From ca47a0fc21277c9a868f600487e7e7dbc385662a Mon Sep 17 00:00:00 2001 From: PavelVozenilek Date: Tue, 22 Jul 2014 10:33:14 +0200 Subject: [PATCH 040/234] typo fix --- lib/system.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/system.nim b/lib/system.nim index 2fb08563aa..6e5d5ef2d8 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -783,7 +783,7 @@ proc contains*[T](s: TSlice[T], value: T): bool {.noSideEffect, inline.} = result = s.a <= value and value <= s.b template `in` * (x, y: expr): expr {.immediate.} = contains(y, x) - ## Suger for contains + ## Sugar for contains ## ## .. code-block:: Nimrod ## assert(1 in (1..3) == true) From 919c136e9bb7a6969d6400357af3ba86ceca2921 Mon Sep 17 00:00:00 2001 From: PavelVozenilek Date: Tue, 22 Jul 2014 11:28:21 +0200 Subject: [PATCH 041/234] replaced var with let in system.nim Nitpicking. --- lib/system.nim | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/system.nim b/lib/system.nim index 2fb08563aa..a0c9e66d5f 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -1052,7 +1052,7 @@ proc add *[T](x: var seq[T], y: openArray[T]) {.noSideEffect.} = ## containers should also call their adding proc `add` for consistency. ## Generic code becomes much easier to write if the Nimrod naming scheme is ## respected. - var xl = x.len + let xl = x.len setLen(x, xl + y.len) for i in 0..high(y): x[xl+i] = y[i] @@ -1066,20 +1066,20 @@ proc shallowCopy*[T](x: var T, y: T) {.noSideEffect, magic: "ShallowCopy".} proc del*[T](x: var seq[T], i: int) {.noSideEffect.} = ## deletes the item at index `i` by putting ``x[high(x)]`` into position `i`. ## This is an O(1) operation. - var xl = x.len + let xl = x.len shallowCopy(x[i], x[xl-1]) setLen(x, xl-1) proc delete*[T](x: var seq[T], i: int) {.noSideEffect.} = ## deletes the item at index `i` by moving ``x[i+1..]`` by one position. ## This is an O(n) operation. - var xl = x.len + let xl = x.len for j in i..xl-2: shallowCopy(x[j], x[j+1]) setLen(x, xl-1) proc insert*[T](x: var seq[T], item: T, i = 0) {.noSideEffect.} = ## inserts `item` into `x` at position `i`. - var xl = x.len + let xl = x.len setLen(x, xl+1) var j = xl-1 while j >= i: From d195f08da0144b04d57f90715a371008ba063d6d Mon Sep 17 00:00:00 2001 From: Araq Date: Tue, 22 Jul 2014 20:15:20 +0200 Subject: [PATCH 042/234] fixes #1395 --- lib/system.nim | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/system.nim b/lib/system.nim index 2fb08563aa..0a16efbb58 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -814,9 +814,9 @@ proc `of` *[T, S](x: T, y: S): bool {.magic: "Of", noSideEffect.} ## Checks if `x` has a type of `y` ## ## .. code-block:: Nimrod - ## assert(EFloatingPoint is EBase) - ## assert(EIO is ESystem) - ## assert(EDivByZero is EBase) + ## assert(EFloatingPoint of EBase) + ## assert(EIO of ESystem) + ## assert(EDivByZero of EBase) proc cmp*[T](x, y: T): int {.procvar.} = ## Generic compare proc. Returns a value < 0 iff x < y, a value > 0 iff x > y From 6219ad6a66fc164a2dc27f9285590648d68bab3a Mon Sep 17 00:00:00 2001 From: Araq Date: Tue, 22 Jul 2014 20:15:57 +0200 Subject: [PATCH 043/234] fixes #1391 --- lib/system/sysstr.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/system/sysstr.nim b/lib/system/sysstr.nim index b3dc9c14eb..9db8ce378e 100644 --- a/lib/system/sysstr.nim +++ b/lib/system/sysstr.nim @@ -258,7 +258,7 @@ proc nimFloatToStr(f: float): string {.compilerproc.} = if buf[i] == ',': buf[i] = '.' hasDot = true - elif buf[i] in {'e', 'E', '.'}: + elif buf[i] in {'a'..'z', 'A'..'Z', '.'}: hasDot = true if not hasDot: buf[n] = '.' From e27c675293b2241c0794020de80c4d46b2423d91 Mon Sep 17 00:00:00 2001 From: Araq Date: Tue, 22 Jul 2014 20:22:29 +0200 Subject: [PATCH 044/234] fixes subtle interaction between closures and 'yield' --- compiler/lambdalifting.nim | 102 ++++++++++++++++++++++++++----------- 1 file changed, 73 insertions(+), 29 deletions(-) diff --git a/compiler/lambdalifting.nim b/compiler/lambdalifting.nim index ee380b305d..bdad0e4711 100644 --- a/compiler/lambdalifting.nim +++ b/compiler/lambdalifting.nim @@ -130,7 +130,8 @@ type PEnv = ref TEnv TEnv {.final.} = object of TObject attachedNode, replacementNode: PNode - createdVar: PSym # if != nil it is a used environment + createdVar: PNode # if != nil it is a used environment; for closure + # iterators this can be 'envParam.env' createdVarComesFromIter: bool capturedVars: seq[PSym] # captured variables in this environment up, next: PEnv # outer scope and next to keep all in a list @@ -253,10 +254,10 @@ proc addCapturedVar(e: PEnv, v: PSym) = e.capturedVars.add(v) addField(e.obj, v) -proc newCall(a, b: PSym): PNode = +proc newCall(a: PSym, b: PNode): PNode = result = newNodeI(nkCall, a.info) result.add newSymNode(a) - result.add newSymNode(b) + result.add b proc isInnerProc(s, outerProc: PSym): bool = if s.kind in {skProc, skMethod, skConverter, skClosureIterator}: @@ -433,21 +434,27 @@ proc transformOuterConv(n: PNode): PNode = if dest.callConv == ccClosure and source.callConv == ccDefault: result = generateThunk(n.sons[1], dest) -proc makeClosure(prc, env: PSym, info: TLineInfo): PNode = +proc makeClosure(prc: PSym; env: PNode; info: TLineInfo): PNode = result = newNodeIT(nkClosure, info, prc.typ) result.add(newSymNode(prc)) if env == nil: result.add(newNodeIT(nkNilLit, info, getSysType(tyNil))) else: - result.add(newSymNode(env)) + result.add(env) -proc newClosureCreationVar(e: PEnv): PSym = - result = newSym(skVar, getIdent(envName), e.fn, e.attachedNode.info) - incl(result.flags, sfShadowed) - result.typ = newType(tyRef, e.fn) - result.typ.rawAddSon(e.obj) +proc newClosureCreationVar(e: PEnv): PNode = + var v = newSym(skVar, getIdent(envName), e.fn, e.attachedNode.info) + incl(v.flags, sfShadowed) + v.typ = newType(tyRef, e.fn) + v.typ.rawAddSon(e.obj) + if e.fn.kind == skClosureIterator: + let it = initIter(e.fn) + addUniqueField(it.obj, v) + result = indirectAccess(newSymNode(it.closureParam), v, v.info) + else: + result = newSymNode(v) -proc getClosureVar(e: PEnv): PSym = +proc getClosureVar(e: PEnv): PNode = if e.createdVar == nil: result = newClosureCreationVar(e) e.createdVar = result @@ -470,7 +477,7 @@ proc transformInnerProc(o: POuterContext; e: PEnv, n: PNode): PNode = let s = n.sym if s == e.fn: # recursive calls go through (lambda, hiddenParam): - result = makeClosure(s, getEnvParam(s), n.info) + result = makeClosure(s, getEnvParam(s).newSymNode, n.info) elif isInnerProc(s, o.fn) and s.typ.callConv == ccClosure: # ugh: call to some other inner proc; result = makeClosure(s, findEnv(o, s).getClosureVar, n.info) @@ -552,13 +559,18 @@ proc searchForInnerProcs(o: POuterContext, n: PNode, env: PEnv) = # of closure creation; however for simplicity we merge closures between # branches, in fact, only loop bodies are of interest here as only they # yield observable changes in semantics. For Zahary we also - # include ``nkBlock``. - var body = n.len-1 - for i in countup(0, body - 1): searchForInnerProcs(o, n.sons[i], env) - # special handling for the loop body: - let ex = closureCreationPoint(n.sons[body]) - searchForInnerProcs(o, n.sons[body], newEnv(o, env, ex, env.fn)) - n.sons[body] = ex + # include ``nkBlock``. We don't do this for closure iterators because + # 'yield' can produce wrong code otherwise (XXX show example): + if env.fn.kind != skClosureIterator: + var body = n.len-1 + for i in countup(0, body - 1): searchForInnerProcs(o, n.sons[i], env) + # special handling for the loop body: + let ex = closureCreationPoint(n.sons[body]) + searchForInnerProcs(o, n.sons[body], newEnv(o, env, ex, env.fn)) + n.sons[body] = ex + else: + for i in countup(0, sonsLen(n) - 1): + searchForInnerProcs(o, n.sons[i], env) of nkVarSection, nkLetSection: # we need to compute a mapping var->declaredBlock. Note: The definition # counts, not the block where it is captured! @@ -601,11 +613,12 @@ proc newAsgnStmt(le, ri: PNode, info: TLineInfo): PNode = result.sons[0] = le result.sons[1] = ri -proc rawClosureCreation(o: POuterContext, scope: PEnv; env: PSym): PNode = +proc rawClosureCreation(o: POuterContext, scope: PEnv; env: PNode): PNode = result = newNodeI(nkStmtList, env.info) - var v = newNodeI(nkVarSection, env.info) - addVar(v, newSymNode(env)) - result.add(v) + if env.kind == nkSym: + var v = newNodeI(nkVarSection, env.info) + addVar(v, env) + result.add(v) # add 'new' statement: result.add(newCall(getSysSym"internalNew", env)) @@ -632,14 +645,14 @@ proc rawClosureCreation(o: POuterContext, scope: PEnv; env: PSym): PNode = newSymNode(getEnvParam(scope.fn)), env.info)) else: result.add(newAsgnStmt(indirectAccess(env, scope.upField, env.info), - newSymNode(getClosureVar(scope.up)), env.info)) + getClosureVar(scope.up), env.info)) proc generateClosureCreation(o: POuterContext, scope: PEnv): PNode = var env = getClosureVar(scope) result = rawClosureCreation(o, scope, env) proc generateIterClosureCreation(o: POuterContext; env: PEnv; - scope: PNode): PSym = + scope: PNode): PNode = if env.createdVarComesFromIter or env.createdVar.isNil: # we have to create a new closure: result = newClosureCreationVar(env) @@ -716,8 +729,25 @@ proc liftIterSym*(n: PNode): PNode = addVar(v, newSymNode(env)) result.add(v) # add 'new' statement: - result.add newCall(getSysSym"internalNew", env) - result.add makeClosure(iter, env, n.info) + let envAsNode = env.newSymNode + result.add newCall(getSysSym"internalNew", envAsNode) + result.add makeClosure(iter, envAsNode, n.info) + +when false: + proc transformRemainingLocals(n: PNode; it: TIter): PNode = + assert it.fn.kind == skClosureIterator + result = n + case n.kind + of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit: discard + of nkSym: + let local = n.sym + if interestingIterVar(local) and it.fn == local.owner: + addUniqueField(it.obj, local) + result = indirectAccess(newSymNode(it.closureParam), local, n.info) + else: + result = newNodeI(n.kind, n.info, n.len) + for i in 0.. 0 or env.upField != nil) @@ -748,6 +778,12 @@ proc finishEnvironments(o: POuterContext) = if scope.sons[0].kind == nkEmpty: # change the empty node to contain the closure construction: scope.sons[0] = env.replacementNode + when false: + if env.fn.kind == skClosureIterator: + scope.sons[0] = transformRemainingLocals(env.replacementNode, + initIter(env.fn)) + else: + scope.sons[0] = env.replacementNode env = env.next proc transformOuterProcBody(o: POuterContext, n: PNode; it: TIter): PNode = @@ -863,6 +899,14 @@ proc transformOuterProc(o: POuterContext, n: PNode; it: TIter): PNode = let newBody = transformOuterProcBody(o, body, initIter(local)) if newBody != nil: local.ast.sons[bodyPos] = newBody + when false: + if n.sons[1].kind == nkSym: + var local = n.sons[1].sym + if it.fn.kind == skClosureIterator and interestingIterVar(local) and + it.fn == local.owner: + # every local goes through the closure: + addUniqueField(it.obj, local) + n.sons[1] = indirectAccess(newSymNode(it.closureParam), local, n.info) of nkHiddenStdConv, nkHiddenSubConv, nkConv: let x = transformOuterProc(o, n.sons[1], it) if x != nil: n.sons[1] = x @@ -962,7 +1006,7 @@ proc liftForLoop*(body: PNode): PNode = addVar(v, newSymNode(env)) result.add(v) # add 'new' statement: - result.add(newCall(getSysSym"internalNew", env)) + result.add(newCall(getSysSym"internalNew", env.newSymNode)) var loopBody = newNodeI(nkStmtList, body.info, 3) var whileLoop = newNodeI(nkWhileStmt, body.info, 2) @@ -981,7 +1025,7 @@ proc liftForLoop*(body: PNode): PNode = addSon(vpart, ast.emptyNode) # no explicit type if not env.isNil: - call.sons[0] = makeClosure(call.sons[0].sym, env, body.info) + call.sons[0] = makeClosure(call.sons[0].sym, env.newSymNode, body.info) addSon(vpart, call) addSon(v2, vpart) From 725cf0e22d4f8185e8b6d182f7e8a959b77e049a Mon Sep 17 00:00:00 2001 From: Araq Date: Tue, 22 Jul 2014 20:23:19 +0200 Subject: [PATCH 045/234] '[]' for crit bit trees doesn't need the 'var' parameter --- lib/pure/collections/critbits.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pure/collections/critbits.nim b/lib/pure/collections/critbits.nim index 40a02b6511..1fde1f4193 100644 --- a/lib/pure/collections/critbits.nim +++ b/lib/pure/collections/critbits.nim @@ -131,7 +131,7 @@ proc `[]=`*[T](c: var TCritBitTree[T], key: string, val: T) = var n = rawInsert(c, key) n.val = val -proc `[]`*[T](c: var TCritBitTree[T], key: string): T {.inline.} = +proc `[]`*[T](c: TCritBitTree[T], key: string): T {.inline.} = ## retrieves the value at ``c[key]``. If `key` is not in `t`, ## default empty value for the type `B` is returned ## and no exception is raised. One can check with ``hasKey`` whether the key From ed68286c592b0f2ff0d27496c740b9e9f6b761a7 Mon Sep 17 00:00:00 2001 From: Flaviu Tamas Date: Tue, 22 Jul 2014 15:34:49 -0400 Subject: [PATCH 046/234] Fix #1392 --- compiler/ccgexprs.nim | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 95167e1576..691feeb472 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -1578,15 +1578,15 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) = of mGetTypeInfo: genGetTypeInfo(p, e, d) of mSwap: genSwap(p, e, d) of mUnaryLt: - if not (optOverflowCheck in p.options): unaryExpr(p, e, d, "$1 - 1") + if not (optOverflowCheck in p.options): unaryExpr(p, e, d, "($1 - 1)") else: unaryExpr(p, e, d, "#subInt($1, 1)") of mPred: # XXX: range checking? - if not (optOverflowCheck in p.options): binaryExpr(p, e, d, "$1 - $2") + if not (optOverflowCheck in p.options): binaryExpr(p, e, d, "($1 - $2)") else: binaryExpr(p, e, d, "#subInt($1, $2)") of mSucc: # XXX: range checking? - if not (optOverflowCheck in p.options): binaryExpr(p, e, d, "$1 + $2") + if not (optOverflowCheck in p.options): binaryExpr(p, e, d, "($1 + $2)") else: binaryExpr(p, e, d, "#addInt($1, $2)") of mInc: if not (optOverflowCheck in p.options): From 15734009ca9077cfc8c4139b8258b2db2d7492dd Mon Sep 17 00:00:00 2001 From: Reimer Behrends Date: Wed, 23 Jul 2014 03:20:50 +0200 Subject: [PATCH 047/234] More robust implementation for finding the beginning of the stack. This patch inserts an extra stack frame above the function that calls the actual Nimrod code and ensures that a reference to this frame is stored as the stack bottom. --- compiler/cgen.nim | 25 +++++++++++++++++-------- lib/system.nim | 6 ++++++ 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/compiler/cgen.nim b/compiler/cgen.nim index e2f3b5ab0a..d7a9d3c9d9 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -954,8 +954,7 @@ proc genMainProc(m: BModule) = "\tsystemInit();$N" & "$1" & "$2" & - "$3" & - "$4" + "$3" MainProcs = "\tNimMain();$N" @@ -963,10 +962,19 @@ proc genMainProc(m: BModule) = MainProcsWithResult = MainProcs & "\treturn nim_program_result;$N" + # The use of a volatile function pointer to call NimMainInner + # prevents inlining of the NimMainInner function and dependent + # functions, which might otherwise merge their stack frames. NimMainBody = - "N_CDECL(void, NimMain)(void) {$N" & + "N_CDECL(void, NimMainInner)(void) {$N" & "\tPreMain();$N" & "$1" & + "}$N$N" & + "N_CDECL(void, NimMain)(void) {$N" & + "\tvoid (*volatile inner)();$N" & + "\tinner = NimMainInner;$N" & + "$2" & + "\t(*inner)();$N" & "}$N$N" PosixNimMain = @@ -1034,14 +1042,15 @@ proc genMainProc(m: BModule) = if optEndb in gOptions: gBreakpoints.app(m.genFilenames) - let initStackBottomCall = if emulatedThreadVars() or - platform.targetOS == osStandalone: "".toRope - else: ropecg(m, "\t#initStackBottom();$N") + let initStackBottomCall = + if emulatedThreadVars() or + platform.targetOS == osStandalone: "".toRope + else: ropecg(m, "\t#initStackBottomWith((void *)&inner);$N") inc(m.labels) appcg(m, m.s[cfsProcs], "void PreMain() {$N" & PreMainBody & "}$N$N", [ - mainDatInit, initStackBottomCall, gBreakpoints, otherModsInit]) + mainDatInit, gBreakpoints, otherModsInit]) - appcg(m, m.s[cfsProcs], nimMain, [mainModInit, toRope(m.labels)]) + appcg(m, m.s[cfsProcs], nimMain, [mainModInit, initStackBottomCall, toRope(m.labels)]) if optNoMain notin gGlobalOptions: appcg(m, m.s[cfsProcs], otherMain, []) diff --git a/lib/system.nim b/lib/system.nim index 753205777e..361e944629 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -2115,6 +2115,12 @@ when not defined(JS): #and not defined(NimrodVM): locals = addr(locals) setStackBottom(locals) + proc initStackBottomWith(locals: pointer) {.inline, compilerproc.} = + # We need to keep initStackBottom around for now to avoid + # bootstrapping problems. + when defined(setStackBottom): + setStackBottom(locals) + var strDesc: TNimType From 5e2614a7d63647ece5774725a85e9482b9f02057 Mon Sep 17 00:00:00 2001 From: def Date: Wed, 23 Jul 2014 15:47:46 +0200 Subject: [PATCH 048/234] Add newSeqWith --- lib/system.nim | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/lib/system.nim b/lib/system.nim index 2fb08563aa..96c6112825 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -476,6 +476,23 @@ proc newSeq*[T](len = 0): seq[T] = ## #inputStrings[3] = "out of bounds" newSeq(result, len) +template newSeqWith*(len: int, init: expr): expr = + ## creates a new sequence, calling `init` to initialize each value. Example: + ## + ## .. code-block:: nimrod + ## var seq2D = newSeqWith(20, newSeq[bool](10)) + ## seq2D[0][0] = true + ## seq2D[1][0] = true + ## seq2D[0][1] = true + ## + ## import math + ## var seqRand = newSeqWith(20, random(10)) + ## echo seqRand + var result {.gensym.} = newSeq[type(init)](len) + for i in 0 .. Date: Wed, 23 Jul 2014 16:32:20 +0200 Subject: [PATCH 049/234] Add count procedures to strutils --- lib/pure/strutils.nim | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim index 6f8924d83b..acb803a4c0 100644 --- a/lib/pure/strutils.nim +++ b/lib/pure/strutils.nim @@ -803,6 +803,44 @@ proc rfind*(s, sub: string, start: int = -1): int {.noSideEffect.} = if result != -1: return return -1 +proc count*(s: string, sub: string): int {.noSideEffect, + rtl, extern: "nsuCountString".} = + ## Count the occurences of a substring `sub` in the string `s`. Overlapping + ## occurences of `sub` do not count. + var i = 0 + while true: + i = s.find(sub, i) + if i < 0: + break + i += sub.len + inc result + +proc count*(s: string, sub: char): int {.noSideEffect, + rtl, extern: "nsuCountChar".} = + ## Count the occurences of the character `sub` in the string `s`. + for c in s: + if c == sub: + inc result + +proc count*(s: string, subs: set[char]): int {.noSideEffect, + rtl, extern: "nsuCountCharSet".} = + ## Count the occurences of the group of character `subs` in the string `s`. + for c in s: + if c in subs: + inc result + +proc countOverlapping*(s: string, sub: string): int {.noSideEffect, + rtl, extern: "nsuCountOverlapping".} = + ## Count the occurences of a substring `sub` in the string `s`. Overlapping + ## occurences of `sub` do count. + var i = 0 + while true: + i = s.find(sub, i) + if i < 0: + break + inc i + inc result + proc quoteIfContainsWhite*(s: string): string {.deprecated.} = ## Returns ``'"' & s & '"'`` if `s` contains a space and does not ## start with a quote, else returns `s`. @@ -1354,3 +1392,8 @@ when isMainModule: doAssert parseEnum[TMyEnum]("enu_D") == enuD doAssert parseEnum("invalid enum value", enC) == enC + + doAssert count("foofoofoo", "foofoo") == 1 + doAssert countOverlapping("foofoofoo", "foofoo") == 2 + doAssert count("foofoofoo", 'f') == 3 + doAssert count("foofoofoobar", {'f','b'}) == 4 From 272fd42c970d48d526f0d5ab8dc4fef4d8f177e7 Mon Sep 17 00:00:00 2001 From: Nick Greenfield Date: Wed, 23 Jul 2014 11:25:21 -0700 Subject: [PATCH 050/234] Add automatic MAP_POPULATE flag for opening read_only (MAP_PRIVATE) and shared (MAP_SHARED) mmap files. --- lib/posix/posix.nim | 2 ++ lib/pure/memfiles.nim | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/posix/posix.nim b/lib/posix/posix.nim index 8e66336c2e..17bcc420ed 100644 --- a/lib/posix/posix.nim +++ b/lib/posix/posix.nim @@ -1375,6 +1375,8 @@ var ## Share changes. MAP_PRIVATE* {.importc, header: "".}: cint ## Changes are private. + MAP_POPULATE* {.importc, header: "".}: cint + ## Populate (prefault) page tables for a mapping. MAP_FIXED* {.importc, header: "".}: cint ## Interpret addr exactly. MS_ASYNC* {.importc, header: "".}: cint diff --git a/lib/pure/memfiles.nim b/lib/pure/memfiles.nim index 31fefc6c82..ffeb0beffe 100644 --- a/lib/pure/memfiles.nim +++ b/lib/pure/memfiles.nim @@ -54,7 +54,7 @@ proc mapMem*(m: var TMemFile, mode: TFileMode = fmRead, nil, mappedSize, if readonly: PROT_READ else: PROT_READ or PROT_WRITE, - if readonly: MAP_PRIVATE else: MAP_SHARED, + if readonly: (MAP_PRIVATE or MAP_POPULATE) else: (MAP_SHARED or MAP_POPULATE), m.handle, offset) if result == cast[pointer](MAP_FAILED): osError(osLastError()) @@ -207,7 +207,7 @@ proc open*(filename: string, mode: TFileMode = fmRead, nil, result.size, if readonly: PROT_READ else: PROT_READ or PROT_WRITE, - if readonly: MAP_PRIVATE else: MAP_SHARED, + if readonly: (MAP_PRIVATE or MAP_POPULATE) else: (MAP_SHARED or MAP_POPULATE), result.handle, offset) From cba75db4e36b3af0d39b5717141a971e6d558554 Mon Sep 17 00:00:00 2001 From: Nick Greenfield Date: Wed, 23 Jul 2014 11:31:03 -0700 Subject: [PATCH 051/234] Do not automatically use MAP_POPULATE for opening mmap files. Adds use_map_populate keyword to memfiles.open and memfiles.mapMem to govern MAP_POPULATE use. This is set to false by default. --- lib/pure/memfiles.nim | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/pure/memfiles.nim b/lib/pure/memfiles.nim index ffeb0beffe..06f2c215e4 100644 --- a/lib/pure/memfiles.nim +++ b/lib/pure/memfiles.nim @@ -30,14 +30,17 @@ type when defined(windows): fHandle: int - mapHandle: int + mapHandle: int else: handle: cint proc mapMem*(m: var TMemFile, mode: TFileMode = fmRead, - mappedSize = -1, offset = 0): pointer = + mappedSize = -1, offset = 0, + use_map_populate = false): pointer = var readonly = mode == fmRead + if not use_map_populate: + MAP_POPULATE = 0 when defined(windows): result = mapViewOfFileEx( m.mapHandle, @@ -72,7 +75,8 @@ proc unmapMem*(f: var TMemFile, p: pointer, size: int) = proc open*(filename: string, mode: TFileMode = fmRead, - mappedSize = -1, offset = 0, newFileSize = -1): TMemFile = + mappedSize = -1, offset = 0, newFileSize = -1, + use_map_populate = false): TMemFile = ## opens a memory mapped file. If this fails, ``EOS`` is raised. ## `newFileSize` can only be set if the file does not exist and is opened ## with write access (e.g., with fmReadWrite). `mappedSize` and `offset` @@ -94,6 +98,8 @@ proc open*(filename: string, mode: TFileMode = fmRead, # The file can be resized only when write mode is used: assert newFileSize == -1 or mode != fmRead var readonly = mode == fmRead + if not use_map_populate: + MAP_POPULATE = 0 template rollback = result.mem = nil From 3a57052e57a6e6d2a7b4b6fa8babdd750620d687 Mon Sep 17 00:00:00 2001 From: Nick Greenfield Date: Wed, 23 Jul 2014 11:36:35 -0700 Subject: [PATCH 052/234] Revert "Do not automatically use MAP_POPULATE for opening mmap files." This reverts commit cba75db4e36b3af0d39b5717141a971e6d558554. The prior commit yields a compiler error 'error: lvalue required as left operand of assignment; MAP_POPULATE = ((int) 0);'. So for now this branch *always* adds MAP_POPULATE when using the open and mapMem procs. --- lib/pure/memfiles.nim | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/lib/pure/memfiles.nim b/lib/pure/memfiles.nim index 06f2c215e4..ffeb0beffe 100644 --- a/lib/pure/memfiles.nim +++ b/lib/pure/memfiles.nim @@ -30,17 +30,14 @@ type when defined(windows): fHandle: int - mapHandle: int + mapHandle: int else: handle: cint proc mapMem*(m: var TMemFile, mode: TFileMode = fmRead, - mappedSize = -1, offset = 0, - use_map_populate = false): pointer = + mappedSize = -1, offset = 0): pointer = var readonly = mode == fmRead - if not use_map_populate: - MAP_POPULATE = 0 when defined(windows): result = mapViewOfFileEx( m.mapHandle, @@ -75,8 +72,7 @@ proc unmapMem*(f: var TMemFile, p: pointer, size: int) = proc open*(filename: string, mode: TFileMode = fmRead, - mappedSize = -1, offset = 0, newFileSize = -1, - use_map_populate = false): TMemFile = + mappedSize = -1, offset = 0, newFileSize = -1): TMemFile = ## opens a memory mapped file. If this fails, ``EOS`` is raised. ## `newFileSize` can only be set if the file does not exist and is opened ## with write access (e.g., with fmReadWrite). `mappedSize` and `offset` @@ -98,8 +94,6 @@ proc open*(filename: string, mode: TFileMode = fmRead, # The file can be resized only when write mode is used: assert newFileSize == -1 or mode != fmRead var readonly = mode == fmRead - if not use_map_populate: - MAP_POPULATE = 0 template rollback = result.mem = nil From a0df72fcdc8c180b14d4e030c083a6ef1b5320b3 Mon Sep 17 00:00:00 2001 From: Nick Greenfield Date: Wed, 23 Jul 2014 12:06:13 -0700 Subject: [PATCH 053/234] Only try to import MAP_POPULATE on Linux, define flag as 0 otherwise. --- lib/posix/posix.nim | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/lib/posix/posix.nim b/lib/posix/posix.nim index 17bcc420ed..5bd43fe9cf 100644 --- a/lib/posix/posix.nim +++ b/lib/posix/posix.nim @@ -1375,8 +1375,6 @@ var ## Share changes. MAP_PRIVATE* {.importc, header: "".}: cint ## Changes are private. - MAP_POPULATE* {.importc, header: "".}: cint - ## Populate (prefault) page tables for a mapping. MAP_FIXED* {.importc, header: "".}: cint ## Interpret addr exactly. MS_ASYNC* {.importc, header: "".}: cint @@ -1581,6 +1579,16 @@ var MSG_OOB* {.importc, header: "".}: cint ## Out-of-band data. + +when defined(linux): + var + MAP_POPULATE* {.importc, header: "".}: cint + ## Populate (prefault) page tables for a mapping. +else: + var + MAP_POPULATE*: cint = 0 + + when defined(macosx): var MSG_HAVEMORE* {.importc, header: "".}: cint From 26ba9e6d3286adddaff0d3c13e91d973f443bf51 Mon Sep 17 00:00:00 2001 From: jfhg Date: Wed, 23 Jul 2014 22:47:16 +0200 Subject: [PATCH 054/234] fix build on DragonFly BSD and FreeBSD --- lib/pure/osproc.nim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/pure/osproc.nim b/lib/pure/osproc.nim index 04a0c2403a..c74fa1ceb6 100644 --- a/lib/pure/osproc.nim +++ b/lib/pure/osproc.nim @@ -763,7 +763,7 @@ elif not defined(useNimRtl): discard write(data.pErrorPipe[writeIdx], addr error, sizeof(error)) exitnow(1) - when defined(macosx): + when defined(macosx) or defined(freebsd): var environ {.importc.}: cstringArray proc startProcessAfterFork(data: ptr TStartProcessData) = @@ -793,7 +793,7 @@ elif not defined(useNimRtl): discard fcntl(data.pErrorPipe[writeIdx], F_SETFD, FD_CLOEXEC) if data.optionPoUsePath: - when defined(macosx): + when defined(macosx) or defined(freebsd): # MacOSX doesn't have execvpe, so we need workaround. # On MacOSX we can arrive here only from fork, so this is safe: environ = data.sysEnv From 2577c92ec757f57d9238c362922f01bb807aff54 Mon Sep 17 00:00:00 2001 From: Joshua Cearley Date: Wed, 23 Jul 2014 21:30:03 -0500 Subject: [PATCH 055/234] Add better support for unsigned ints via typeinfo. --- lib/core/typeinfo.nim | 53 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/lib/core/typeinfo.nim b/lib/core/typeinfo.nim index edb4d11885..93b90e120a 100644 --- a/lib/core/typeinfo.nim +++ b/lib/core/typeinfo.nim @@ -420,6 +420,59 @@ proc setBiggestInt*(x: TAny, y: biggestInt) = of tyUInt32: cast[ptr uint32](x.value)[] = uint32(y) else: assert false +proc getUInt*(x: TAny): uint = + ## retrieve the uint value out of `x`, `x` needs to represent an uint. + assert skipRange(x.rawtype).kind == tyUInt + result = cast[ptr uint](x.value)[] + +proc getUInt8*(x: TAny): uint8 = + ## retrieve the uint8 value out of `x`, `x` needs to represent an + ## uint8. + assert skipRange(x.rawtype).kind == tyUInt8 + result = cast[ptr uint8](x.value)[] + +proc getUInt16*(x: TAny): uint16 = + ## retrieve the uint16 value out of `x`, `x` needs to represent an + ## uint16. + assert skipRange(x.rawtype).kind == tyUInt16 + result = cast[ptr uint16](x.value)[] + +proc getUInt32*(x: TAny): uint32 = + ## retrieve the uint32 value out of `x`, `x` needs to represent an + ## uint32. + assert skipRange(x.rawtype).kind == tyUInt32 + result = cast[ptr uint32](x.value)[] + +proc getUInt64*(x: TAny): uint64 = + ## retrieve the uint64 value out of `x`, `x` needs to represent an + ## uint64. + assert skipRange(x.rawtype).kind == tyUInt64 + result = cast[ptr uint64](x.value)[] + +proc getBiggestUint*(x: TAny): uint64 = + ## retrieve the unsigned integer value out of `x`. `x` needs to + ## represent an unsigned integer. + var t = skipRange(x.rawtype) + case t.kind + of akUInt: result = uint64(cast[ptr uint](x.value)[]) + of akUInt8: result = uint64(cast[ptr uint8](x.value)[]) + of akUInt16: result = uint64(cast[ptr uint16](x.value)[]) + of akUInt32: result = uint64(cast[ptr uint32](x.value)[]) + of akUInt64: result = uint64(cast[ptr uint64](x.value)[]) + else: assert false + +proc setBiggestUint*(x: TAny; y: uint64) = + ## sets the unsigned integer value of `c`. `c` needs to represent an + ## unsigned integer. + var t = skipRange(x.rawtype) + case t.kind: + of akUInt: result = cast[ptr uint](x.value)[] = uint(y) + of akUInt8: result = cast[ptr uint8](x.value)[] = uint8(y) + of akUInt16: result = cast[ptr uint16](x.value)[] = uint16(y) + of akUInt32: result = cast[ptr uint32](x.value)[] = uint32(y) + of akUInt64: result = cast[ptr uint64](x.value)[] = uint64(y) + else: assert false + proc getChar*(x: TAny): char = ## retrieve the char value out of `x`. `x` needs to represent a char. var t = skipRange(x.rawtype) From 18003ff1966fc54ed1b2b39988dda6961ce35c80 Mon Sep 17 00:00:00 2001 From: Clay Sweetser Date: Thu, 24 Jul 2014 18:17:20 -0400 Subject: [PATCH 056/234] Added stylistic consistancy. --- lib/pure/collections/tables.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pure/collections/tables.nim b/lib/pure/collections/tables.nim index 146cb76c9a..dcf2ab4811 100644 --- a/lib/pure/collections/tables.nim +++ b/lib/pure/collections/tables.nim @@ -335,7 +335,7 @@ proc `$`*[A, B](t: PTable[A, B]): string = proc `==`*[A, B](s, t: PTable[A, B]): bool = if isNil(s): result = isNil(t) elif isNil(t): result = false - else: equalsImpl() + else: result = equalsImpl() proc newTableFrom*[A, B, C](collection: A, index: proc(x: B): C): PTable[C, B] = ## Index the collection with the proc provided. From 030c2d6deb6f8538627009ad4fc77e56e4f2b714 Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Sat, 26 Jul 2014 02:14:26 +0100 Subject: [PATCH 057/234] Fixes base64 crash. --- lib/pure/base64.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pure/base64.nim b/lib/pure/base64.nim index 4e59a6ca63..7b3b0e6f5a 100644 --- a/lib/pure/base64.nim +++ b/lib/pure/base64.nim @@ -58,7 +58,7 @@ template encodeInternal(s: expr, lineLen: int, newLine: string): stmt {.immediat if r+4 != result.len: setLen(result, r+4) else: - assert(r == result.len) + #assert(r == result.len) proc encode*[T:TInteger|char](s: openarray[T], lineLen = 75, newLine="\13\10"): string = ## encodes `s` into base64 representation. After `lineLen` characters, a From b10bf62963349828068f735771a87f0d4a5214d8 Mon Sep 17 00:00:00 2001 From: Grzegorz Adam Hankiewicz Date: Sat, 26 Jul 2014 11:57:26 +0200 Subject: [PATCH 058/234] Documents pretty command. --- doc/advopt.txt | 1 + doc/nimrodc.txt | 52 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/doc/advopt.txt b/doc/advopt.txt index 08465e4572..7a11e90419 100644 --- a/doc/advopt.txt +++ b/doc/advopt.txt @@ -12,6 +12,7 @@ Advanced commands: module dependency graph //dump dump all defined conditionals and search paths //check checks the project for syntax and semantic + //pretty homogenizes source code style //idetools compiler support for IDEs: possible options: --track:FILE,LINE,COL track a file/cursor position --trackDirty:DIRTY_FILE,ORIG_FILE,LINE,COL diff --git a/doc/nimrodc.txt b/doc/nimrodc.txt index 428c42f39d..90fad7f9c8 100644 --- a/doc/nimrodc.txt +++ b/doc/nimrodc.txt @@ -540,6 +540,58 @@ in C/C++). **Note**: This pragma will not exist for the LLVM backend. +Source code style +================= + +Nimrod allows you to `mix freely case and underscores as identifier separators +`_, so variables named ``MyPrecioussInt`` and +``my_preciouss_int`` are equivalent: + +.. code-block:: Nimrod + var MyPrecioussInt = 3 + # Following line compiles fine! + echo my_preciouss_int + +Since this can lead to many variants of the same source code (you can use +`nimgrep `_ instead of your typical ``grep`` to ignore style +problems) the compiler provides the command ``pretty`` to help unifying the +style of source code. Running ``nimrod pretty ugly_test.nim`` with this +example will generate a secondary file named ``ugly_test.pretty.nim`` with the +following content: + +.. code-block:: Nimrod + var MyPrecioussInt = 3 + # Following line compiles fine! + echo MyPrecioussInt + +During execution the ``pretty`` command will also run on Nimrod's standard +library, since it doesn't differentiate the standard library as something +special, and hence will warn of many *errors* which are out of your hand to +fix, creating respective ``.pretty.nim`` files all the way. You can ignore +these errors if they don't belong to your source and simply compare your +original version to the new pretty one. In fact, running ``pretty`` on our test +file will show the following:: + + Hint: ugly_test [Processing] + ugly_test.nim(1, 4) Error: name should be: myPrecioussInt + ugly_test.nim(1, 4) Error: name should be: myPrecioussInt + +At the moment ``pretty`` will homogenize the style of symbols but will leave +important changes for you to review. In this case the command is warning that a +variable name should not start with a capital letter, which is usually reserved +to `object types `_. To learn about the accepted `camel case +style `_ read `Coding Guidelines in +the Internals of Nimrod Compiler `_ or `Coding +Guidelines `_ and `NEP 1 +: Style Guide for Nimrod Code +`_ +from the Nimrod `GitHub wiki`_. + +This command is safe to run because it will never attempt to overwrite your +existing sources, but the respective ``.pretty.nim`` files **will** be +overwritten without notice. + + DynlibOverride ============== From 90e3c99baec7204bd5d6aba423bc0ffa5a97392b Mon Sep 17 00:00:00 2001 From: Grzegorz Adam Hankiewicz Date: Sat, 26 Jul 2014 16:58:34 +0200 Subject: [PATCH 059/234] Adds TSet.isValid(). --- lib/pure/collections/sets.nim | 101 ++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) diff --git a/lib/pure/collections/sets.nim b/lib/pure/collections/sets.nim index f1eed00042..090bc971ff 100644 --- a/lib/pure/collections/sets.nim +++ b/lib/pure/collections/sets.nim @@ -27,6 +27,20 @@ type data: TKeyValuePairSeq[A] counter: int +proc isValid*[A](s: TSet[A]): bool = + ## Returns `true` if the set has been initialized with `initSet <#initSet>`_. + ## + ## Most operations over an uninitialized set will crash at runtime and + ## `assert `_ in debug builds. You can use this proc in + ## your own methods to verify that sets passed to your procs are correctly + ## initialized. Example: + ## + ## .. code-block :: nimrod + ## proc savePreferences(options: TSet[string]) = + ## assert options.isValid, "Pass an initialized set!" + ## # Do stuff here, may crash in release builds! + result = not s.data.isNil + proc len*[A](s: TSet[A]): int = ## returns the number of keys in `s`. result = s.counter @@ -37,6 +51,7 @@ proc card*[A](s: TSet[A]): int = iterator items*[A](s: TSet[A]): A = ## iterates over any key in the table `t`. + assert s.isValid, "The set needs to be initialized." for h in 0..high(s.data): if s.data[h].slot == seFilled: yield s.data[h].key @@ -73,12 +88,14 @@ proc mget*[A](s: var TSet[A], key: A): var A = ## value as 'key' or raises the ``EInvalidKey`` exception. This is useful ## when one overloaded 'hash' and '==' but still needs reference semantics ## for sharing. + assert s.isValid, "The set needs to be initialized." var index = rawGet(s, key) if index >= 0: result = t.data[index].key else: raise newException(EInvalidKey, "key not found: " & $key) proc contains*[A](s: TSet[A], key: A): bool = ## returns true iff `key` is in `s`. + assert s.isValid, "The set needs to be initialized." var index = rawGet(s, key) result = index >= 0 @@ -110,14 +127,18 @@ template containsOrInclImpl() {.dirty.} = proc incl*[A](s: var TSet[A], key: A) = ## includes an element `key` in `s`. + assert s.isValid, "The set needs to be initialized." inclImpl() proc incl*[A](s: var TSet[A], other: TSet[A]) = ## includes everything in `other` in `s` + assert s.isValid, "The set `s` needs to be initialized." + assert other.isValid, "The set `other` needs to be initialized." for item in other: incl(s, item) proc excl*[A](s: var TSet[A], key: A) = ## excludes `key` from the set `s`. + assert s.isValid, "The set needs to be initialized." var index = rawGet(s, key) if index >= 0: s.data[index].slot = seDeleted @@ -125,11 +146,14 @@ proc excl*[A](s: var TSet[A], key: A) = proc excl*[A](s: var TSet[A], other: TSet[A]) = ## excludes everything in `other` from `s`. + assert s.isValid, "The set `s` needs to be initialized." + assert other.isValid, "The set `other` needs to be initialized." for item in other: excl(s, item) proc containsOrIncl*[A](s: var TSet[A], key: A): bool = ## returns true if `s` contains `key`, otherwise `key` is included in `s` ## and false is returned. + assert s.isValid, "The set needs to be initialized." containsOrInclImpl() proc initSet*[A](initialSize=64): TSet[A] = @@ -153,22 +177,29 @@ template dollarImpl(): stmt {.dirty.} = proc `$`*[A](s: TSet[A]): string = ## The `$` operator for hash sets. + assert s.isValid, "The set needs to be initialized." dollarImpl() proc union*[A](s1, s2: TSet[A]): TSet[A] = ## returns a new set of all items that are contained in at ## least one of `s1` and `s2` + assert s1.isValid, "The set `s1` needs to be initialized." + assert s2.isValid, "The set `s2` needs to be initialized." result = s1 incl(result, s2) proc intersection*[A](s1, s2: TSet[A]): TSet[A] = ## returns a new set of all items that are contained in both `s1` and `s2` + assert s1.isValid, "The set `s1` needs to be initialized." + assert s2.isValid, "The set `s2` needs to be initialized." result = initSet[A](min(s1.data.len, s2.data.len)) for item in s1: if item in s2: incl(result, item) proc difference*[A](s1, s2: TSet[A]): TSet[A] = ## returns a new set of all items that are contained in `s1`, but not in `s2` + assert s1.isValid, "The set `s1` needs to be initialized." + assert s2.isValid, "The set `s2` needs to be initialized." result = initSet[A]() for item in s1: if not contains(s2, item): @@ -177,6 +208,8 @@ proc difference*[A](s1, s2: TSet[A]): TSet[A] = proc symmetricDifference*[A](s1, s2: TSet[A]): TSet[A] = ## returns a new set of all items that are contained in either ## `s1` or `s2`, but not both + assert s1.isValid, "The set `s1` needs to be initialized." + assert s2.isValid, "The set `s2` needs to be initialized." result = s1 for item in s2: if containsOrIncl(result, item): excl(result, item) @@ -199,6 +232,8 @@ proc `-+-`*[A](s1, s2: TSet[A]): TSet[A] {.inline.} = proc disjoint*[A](s1, s2: TSet[A]): bool = ## returns true iff `s1` and `s2` have no items in common + assert s1.isValid, "The set `s1` needs to be initialized." + assert s2.isValid, "The set `s2` needs to be initialized." for item in s1: if item in s2: return false return true @@ -314,3 +349,69 @@ proc `==`*[A](s, t: TSet[A]): bool = proc map*[A, B](data: TSet[A], op: proc (x: A): B {.closure.}): TSet[B] = result = initSet[B]() for item in data: result.incl(op(item)) + +proc testModule() = + ## Internal micro test to validate docstrings and such. + block isValidTest: + var options: TSet[string] + proc savePreferences(options: TSet[string]) = + assert options.isValid, "Pass an initialized set!" + options = initSet[string]() + options.savePreferences + + block lenTest: + var values: TSet[int] + assert(not values.isValid) + assert values.len == 0 + assert values.card == 0 + + block setIterator: + type pair = tuple[a, b: int] + var a, b = initSet[pair]() + a.incl((2, 3)) + a.incl((3, 2)) + a.incl((2, 3)) + for x, y in a.items: + b.incl((x - 2, y + 1)) + assert a.len == b.card + assert a.len == 2 + echo b + + block setContains: + var values = initSet[int]() + assert(not values.contains(2)) + values.incl(2) + assert values.contains(2) + values.excl(2) + assert(not values.contains(2)) + + block toSeqAndString: + var a = toSet[int]([2, 4, 5]) + var b = initSet[int]() + for x in [2, 4, 5]: b.incl(x) + assert($a == $b) + + block setOperations: + var + a = toset[string](["a", "b"]) + b = toset[string](["b", "c"]) + c = union(a, b) + assert c == toSet[string](["a", "b", "c"]) + var d = intersection(a, b) + assert d == toSet[string](["b"]) + var e = difference(a, b) + assert e == toSet[string](["a"]) + var f = symmetricDifference(a, b) + assert f == toSet[string](["a", "c"]) + # Alias test. + assert a + b == toSet[string](["a", "b", "c"]) + assert a * b == toSet[string](["b"]) + assert a - b == toSet[string](["a"]) + assert a -+- b == toSet[string](["a", "c"]) + assert disjoint(a, b) == false + assert disjoint(a, b - a) == true + + + echo "Micro tests run successfully." + +when isMainModule and not defined(release): testModule() From cdecac11c2f2311349083049a5947c467ef0e92b Mon Sep 17 00:00:00 2001 From: Grzegorz Adam Hankiewicz Date: Sat, 26 Jul 2014 18:58:51 +0200 Subject: [PATCH 060/234] Adds TOrderedSet.isValid(). --- lib/pure/collections/sets.nim | 58 +++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/lib/pure/collections/sets.nim b/lib/pure/collections/sets.nim index 090bc971ff..9e6aa80afd 100644 --- a/lib/pure/collections/sets.nim +++ b/lib/pure/collections/sets.nim @@ -249,6 +249,21 @@ type data: TOrderedKeyValuePairSeq[A] counter, first, last: int +proc isValid*[A](s: TOrderedSet[A]): bool = + ## Returns `true` if the ordered set has been initialized with `initSet + ## <#initOrderedSet>`_. + ## + ## Most operations over an uninitialized ordered set will crash at runtime + ## and `assert `_ in debug builds. You can use this proc + ## in your own methods to verify that ordered sets passed to your procs are + ## correctly initialized. Example: + ## + ## .. code-block :: nimrod + ## proc saveTarotCards(cards: TOrderedSet[int]) = + ## assert cards.isValid, "Pass an initialized set!" + ## # Do stuff here, may crash in release builds! + result = not s.data.isNil + proc len*[A](s: TOrderedSet[A]): int {.inline.} = ## returns the number of keys in `s`. result = s.counter @@ -266,6 +281,7 @@ template forAllOrderedPairs(yieldStmt: stmt) {.dirty, immediate.} = iterator items*[A](s: TOrderedSet[A]): A = ## iterates over any key in the set `s` in insertion order. + assert s.isValid, "The set needs to be initialized." forAllOrderedPairs: yield s.data[h].key @@ -274,6 +290,7 @@ proc rawGet[A](s: TOrderedSet[A], key: A): int = proc contains*[A](s: TOrderedSet[A], key: A): bool = ## returns true iff `key` is in `s`. + assert s.isValid, "The set needs to be initialized." var index = rawGet(s, key) result = index >= 0 @@ -300,15 +317,19 @@ proc enlarge[A](s: var TOrderedSet[A]) = proc incl*[A](s: var TOrderedSet[A], key: A) = ## includes an element `key` in `s`. + assert s.isValid, "The set needs to be initialized." inclImpl() proc incl*[A](s: var TSet[A], other: TOrderedSet[A]) = ## includes everything in `other` in `s` + assert s.isValid, "The set `s` needs to be initialized." + assert other.isValid, "The set `other` needs to be initialized." for item in other: incl(s, item) proc containsOrIncl*[A](s: var TOrderedSet[A], key: A): bool = ## returns true if `s` contains `key`, otherwise `key` is included in `s` ## and false is returned. + assert s.isValid, "The set needs to be initialized." containsOrInclImpl() proc initOrderedSet*[A](initialSize=64): TOrderedSet[A] = @@ -327,6 +348,7 @@ proc toOrderedSet*[A](keys: openArray[A]): TOrderedSet[A] = proc `$`*[A](s: TOrderedSet[A]): string = ## The `$` operator for ordered hash sets. + assert s.isValid, "The set needs to be initialized." dollarImpl() proc `<`*[A](s, t: TSet[A]): bool = @@ -411,6 +433,42 @@ proc testModule() = assert disjoint(a, b) == false assert disjoint(a, b - a) == true + block isValidTest: + var cards: TOrderedSet[string] + proc saveTarotCards(cards: TOrderedSet[string]) = + assert cards.isValid, "Pass an initialized set!" + cards = initOrderedSet[string]() + cards.saveTarotCards + + block lenTest: + var values: TOrderedSet[int] + assert(not values.isValid) + assert values.len == 0 + assert values.card == 0 + + block setIterator: + type pair = tuple[a, b: int] + var a, b = initOrderedSet[pair]() + a.incl((2, 3)) + a.incl((3, 2)) + a.incl((2, 3)) + for x, y in a.items: + b.incl((x - 2, y + 1)) + assert a.len == b.card + assert a.len == 2 + + block setContains: + var values = initOrderedSet[int]() + assert(not values.contains(2)) + values.incl(2) + assert values.contains(2) + + block toSeqAndString: + var a = toOrderedSet[int]([2, 4, 5]) + var b = initOrderedSet[int]() + for x in [2, 4, 5]: b.incl(x) + assert($a == $b) + # assert(a == b) # https://github.com/Araq/Nimrod/issues/1413 echo "Micro tests run successfully." From dd47fa90375f9bd6172625ec8f97f04cdb04e990 Mon Sep 17 00:00:00 2001 From: Grzegorz Adam Hankiewicz Date: Sat, 26 Jul 2014 18:59:59 +0200 Subject: [PATCH 061/234] Moves TSet procs to their code block. --- lib/pure/collections/sets.nim | 42 +++++++++++++++++------------------ 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/lib/pure/collections/sets.nim b/lib/pure/collections/sets.nim index 9e6aa80afd..c3895b8fab 100644 --- a/lib/pure/collections/sets.nim +++ b/lib/pure/collections/sets.nim @@ -238,6 +238,27 @@ proc disjoint*[A](s1, s2: TSet[A]): bool = if item in s2: return false return true +proc `<`*[A](s, t: TSet[A]): bool = + ## Is s a strict subset of t? + s.counter != t.counter and s <= t + +proc `<=`*[A](s, t: TSet[A]): bool = + ## Is s a subset of t? + result = false + if s.counter > t.counter: return + result = true + for item in s: + if not(t.contains(item)): + result = false + return + +proc `==`*[A](s, t: TSet[A]): bool = + s.counter == t.counter and s <= t + +proc map*[A, B](data: TSet[A], op: proc (x: A): B {.closure.}): TSet[B] = + result = initSet[B]() + for item in data: result.incl(op(item)) + # ------------------------------ ordered set ------------------------------ type @@ -351,27 +372,6 @@ proc `$`*[A](s: TOrderedSet[A]): string = assert s.isValid, "The set needs to be initialized." dollarImpl() -proc `<`*[A](s, t: TSet[A]): bool = - ## Is s a strict subset of t? - s.counter != t.counter and s <= t - -proc `<=`*[A](s, t: TSet[A]): bool = - ## Is s a subset of t? - result = false - if s.counter > t.counter: return - result = true - for item in s: - if not(t.contains(item)): - result = false - return - -proc `==`*[A](s, t: TSet[A]): bool = - s.counter == t.counter and s <= t - -proc map*[A, B](data: TSet[A], op: proc (x: A): B {.closure.}): TSet[B] = - result = initSet[B]() - for item in data: result.incl(op(item)) - proc testModule() = ## Internal micro test to validate docstrings and such. block isValidTest: From 6c3b967de358e0b6504ccd8e138799369aab9d1c Mon Sep 17 00:00:00 2001 From: Grzegorz Adam Hankiewicz Date: Sat, 26 Jul 2014 19:12:57 +0200 Subject: [PATCH 062/234] Adds test cases for remaining TSet procs. --- lib/pure/collections/sets.nim | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/pure/collections/sets.nim b/lib/pure/collections/sets.nim index c3895b8fab..4af2b7ad49 100644 --- a/lib/pure/collections/sets.nim +++ b/lib/pure/collections/sets.nim @@ -425,6 +425,10 @@ proc testModule() = assert e == toSet[string](["a"]) var f = symmetricDifference(a, b) assert f == toSet[string](["a", "c"]) + assert d < a and d < b + assert((a < a) == false) + assert d <= a and d <= b + assert((a <= a)) # Alias test. assert a + b == toSet[string](["a", "b", "c"]) assert a * b == toSet[string](["b"]) @@ -433,6 +437,11 @@ proc testModule() = assert disjoint(a, b) == false assert disjoint(a, b - a) == true + block mapSet: + var a = toSet[int]([1, 2, 3]) + var b = a.map(proc (x: int): string = $x) + assert b == toSet[string](["1", "2", "3"]) + block isValidTest: var cards: TOrderedSet[string] proc saveTarotCards(cards: TOrderedSet[string]) = From d21b682268d22e38186ddd8a24b5ad8d78442e5c Mon Sep 17 00:00:00 2001 From: Grzegorz Adam Hankiewicz Date: Sat, 26 Jul 2014 21:40:10 +0200 Subject: [PATCH 063/234] Adds TOrderedSet.init(), wraps initOrderedSet around it. --- lib/pure/collections/sets.nim | 57 ++++++++++++++++++++++++++++++----- 1 file changed, 49 insertions(+), 8 deletions(-) diff --git a/lib/pure/collections/sets.nim b/lib/pure/collections/sets.nim index 4af2b7ad49..4cdc8cf514 100644 --- a/lib/pure/collections/sets.nim +++ b/lib/pure/collections/sets.nim @@ -266,7 +266,11 @@ type slot: TSlotEnum, next: int, key: A] TOrderedKeyValuePairSeq[A] = seq[TOrderedKeyValuePair[A]] TOrderedSet* {. - final, myShallow.}[A] = object ## set that remembers insertion order + final, myShallow.}[A] = object ## \ + ## A generic hash set that remembers insertion order. + ## + ## Use `init() <#init,TOrderedSet[A]>`_ or `initOrderedSet[type]() + ## <#initOrderedSet>`_ before calling other procs on it. data: TOrderedKeyValuePairSeq[A] counter, first, last: int @@ -353,14 +357,41 @@ proc containsOrIncl*[A](s: var TOrderedSet[A], key: A): bool = assert s.isValid, "The set needs to be initialized." containsOrInclImpl() -proc initOrderedSet*[A](initialSize=64): TOrderedSet[A] = - ## creates a new ordered hash set that is empty. `initialSize` needs to be - ## a power of two. +proc init*[A](s: var TOrderedSet[A], initialSize=64) = + ## Initializes an ordered hash set. + ## + ## The `initialSize` parameter needs to be a power of too. You can use + ## `math.nextPowerOfTwo() `_ to guarantee that at + ## runtime. All set variables have to be initialized before you can use them + ## with other procs from this module with the exception of `isValid() + ## <#isValid,TOrderedSet[A]>`_ and `len() <#len,TOrderedSet[A]>`_. + ## + ## You can call this method on a previously initialized ordered hash set to + ## discard its values. At the moment this is the only method to remove + ## elements from an ordered hash set. Example: + ## + ## .. code-block :: + ## var a: TOrderedSet[int] + ## a.init(4) + ## a.incl(2) + ## a.init + ## assert a.len == 0 and a.isValid assert isPowerOfTwo(initialSize) - result.counter = 0 - result.first = -1 - result.last = -1 - newSeq(result.data, initialSize) + s.counter = 0 + s.first = -1 + s.last = -1 + newSeq(s.data, initialSize) + +proc initOrderedSet*[A](initialSize=64): TOrderedSet[A] = + ## Convenience wrapper around `init() <#init,TOrderedSet[A]>`_. + ## + ## Returns an empty ordered hash set you can assign directly in ``var`` + ## blocks in a single line. Example: + ## + ## .. code-block :: + ## var a = initOrderedSet[int](4) + ## a.incl(2) + result.init(initialSize) proc toOrderedSet*[A](keys: openArray[A]): TOrderedSet[A] = ## creates a new ordered hash set that contains the given `keys`. @@ -479,6 +510,16 @@ proc testModule() = assert($a == $b) # assert(a == b) # https://github.com/Araq/Nimrod/issues/1413 + block initBlocks: + var a: TOrderedSet[int] + a.init(4) + a.incl(2) + a.init + assert a.len == 0 and a.isValid + a = initOrderedSet[int](4) + a.incl(2) + assert a.len == 1 + echo "Micro tests run successfully." when isMainModule and not defined(release): testModule() From 0bfe956c05f1bbf21b96b4c7319adfabfced600d Mon Sep 17 00:00:00 2001 From: Grzegorz Adam Hankiewicz Date: Sat, 26 Jul 2014 22:10:15 +0200 Subject: [PATCH 064/234] Adds TSet.init(), wraps initSet around it. --- lib/pure/collections/sets.nim | 52 +++++++++++++++++++++++++++++++---- 1 file changed, 46 insertions(+), 6 deletions(-) diff --git a/lib/pure/collections/sets.nim b/lib/pure/collections/sets.nim index 4cdc8cf514..988a68b980 100644 --- a/lib/pure/collections/sets.nim +++ b/lib/pure/collections/sets.nim @@ -23,7 +23,11 @@ type TSlotEnum = enum seEmpty, seFilled, seDeleted TKeyValuePair[A] = tuple[slot: TSlotEnum, key: A] TKeyValuePairSeq[A] = seq[TKeyValuePair[A]] - TSet* {.final, myShallow.}[A] = object ## a generic hash set + TSet* {.final, myShallow.}[A] = object ## \ + ## A generic hash set. + ## + ## Use `init() <#init,TSet[A]>`_ or `initSet[type]() <#initSet>`_ before + ## calling other procs on it. data: TKeyValuePairSeq[A] counter: int @@ -156,12 +160,39 @@ proc containsOrIncl*[A](s: var TSet[A], key: A): bool = assert s.isValid, "The set needs to be initialized." containsOrInclImpl() -proc initSet*[A](initialSize=64): TSet[A] = - ## creates a new hash set that is empty. `initialSize` needs to be - ## a power of two. +proc init*[A](s: var TSet[A], initialSize=64) = + ## Initializes a hash set. + ## + ## The `initialSize` parameter needs to be a power of too. You can use + ## `math.nextPowerOfTwo() `_ to guarantee that at + ## runtime. All set variables have to be initialized before you can use them + ## with other procs from this module with the exception of `isValid() + ## <#isValid,TSet[A]>`_ and `len() <#len,TSet[A]>`_. + ## + ## You can call this method on a previously initialized hash set, which will + ## discard all its values. This might be more convenient than iterating over + ## existing values and calling `excl() <#excl,TSet[A],A>`_ on them. Example: + ## + ## .. code-block :: + ## var a: TSet[int] + ## a.init(4) + ## a.incl(2) + ## a.init + ## assert a.len == 0 and a.isValid assert isPowerOfTwo(initialSize) - result.counter = 0 - newSeq(result.data, initialSize) + s.counter = 0 + newSeq(s.data, initialSize) + +proc initSet*[A](initialSize=64): TSet[A] = + ## Convenience wrapper around `init() <#init,TSet[A]>`_. + ## + ## Returns an empty hash set you can assign directly in ``var`` blocks in a + ## single line. Example: + ## + ## .. code-block :: + ## var a = initSet[int](4) + ## a.incl(2) + result.init(initialSize) proc toSet*[A](keys: openArray[A]): TSet[A] = ## creates a new hash set that contains the given `keys`. @@ -520,6 +551,15 @@ proc testModule() = a.incl(2) assert a.len == 1 + var b: TSet[int] + b.init(4) + b.incl(2) + b.init + assert b.len == 0 and b.isValid + b = initSet[int](4) + b.incl(2) + assert b.len == 1 + echo "Micro tests run successfully." when isMainModule and not defined(release): testModule() From 48a13a76c8d754496b604f96bb2cf3238ff24937 Mon Sep 17 00:00:00 2001 From: Grzegorz Adam Hankiewicz Date: Sat, 26 Jul 2014 22:42:32 +0200 Subject: [PATCH 065/234] Adds more docstrings to the sets module. --- lib/pure/collections/sets.nim | 435 +++++++++++++++++++++++++++++----- 1 file changed, 374 insertions(+), 61 deletions(-) diff --git a/lib/pure/collections/sets.nim b/lib/pure/collections/sets.nim index 988a68b980..f63805e4e7 100644 --- a/lib/pure/collections/sets.nim +++ b/lib/pure/collections/sets.nim @@ -9,6 +9,10 @@ ## The ``sets`` module implements an efficient hash set and ordered hash set. ## +## Hash sets are different from the `built in set type +## `_. Sets allow you to store any value that can be +## `hashed `_ and they don't contain duplicate entries. +## ## **Note**: The data types declared here have *value semantics*: This means ## that ``=`` performs a copy of the set. @@ -26,8 +30,8 @@ type TSet* {.final, myShallow.}[A] = object ## \ ## A generic hash set. ## - ## Use `init() <#init,TSet[A]>`_ or `initSet[type]() <#initSet>`_ before - ## calling other procs on it. + ## Use `init() <#init,TSet[A],int>`_ or `initSet[type]() <#initSet>`_ + ## before calling other procs on it. data: TKeyValuePairSeq[A] counter: int @@ -36,7 +40,7 @@ proc isValid*[A](s: TSet[A]): bool = ## ## Most operations over an uninitialized set will crash at runtime and ## `assert `_ in debug builds. You can use this proc in - ## your own methods to verify that sets passed to your procs are correctly + ## your own procs to verify that sets passed to your procs are correctly ## initialized. Example: ## ## .. code-block :: nimrod @@ -46,15 +50,42 @@ proc isValid*[A](s: TSet[A]): bool = result = not s.data.isNil proc len*[A](s: TSet[A]): int = - ## returns the number of keys in `s`. + ## Returns the number of keys in `s`. + ## + ## Due to an implementation detail you can call this proc on variables which + ## have not been initialized yet. The proc will return zero as the length + ## then. Example: + ## + ## .. code-block:: + ## + ## var values: TSet[int] + ## assert(not values.isValid) + ## assert values.len == 0 result = s.counter proc card*[A](s: TSet[A]): int = - ## alias for `len`. + ## Alias for `len() <#len,TSet[A]>`_. result = s.counter iterator items*[A](s: TSet[A]): A = - ## iterates over any key in the table `t`. + ## Iterates over keys in the set `s`. + ## + ## If you need a sequence with the keys you can use `sequtils.toSeq() + ## `_ on the iterator. Usage example: + ## + ## .. code-block:: + ## type + ## pair = tuple[a, b: int] + ## var + ## a, b = initSet[pair]() + ## a.incl((2, 3)) + ## a.incl((3, 2)) + ## a.incl((2, 3)) + ## for x, y in a.items: + ## b.incl((x - 2, y + 1)) + ## assert a.len == 2 + ## echo b + ## # --> {(a: 1, b: 3), (a: 0, b: 4)} assert s.isValid, "The set needs to be initialized." for h in 0..high(s.data): if s.data[h].slot == seFilled: yield s.data[h].key @@ -98,7 +129,17 @@ proc mget*[A](s: var TSet[A], key: A): var A = else: raise newException(EInvalidKey, "key not found: " & $key) proc contains*[A](s: TSet[A], key: A): bool = - ## returns true iff `key` is in `s`. + ## Returns true iff `key` is in `s`. + ## + ## Example: + ## + ## .. code-block:: + ## var values = initSet[int]() + ## assert(not values.contains(2)) + ## values.incl(2) + ## assert values.contains(2) + ## values.excl(2) + ## assert(not values.contains(2)) assert s.isValid, "The set needs to be initialized." var index = rawGet(s, key) result = index >= 0 @@ -130,18 +171,43 @@ template containsOrInclImpl() {.dirty.} = inc(s.counter) proc incl*[A](s: var TSet[A], key: A) = - ## includes an element `key` in `s`. + ## Includes an element `key` in `s`. + ## + ## This doesn't do anything if `key` is already in `s`. Example: + ## + ## .. code-block:: + ## var values = initSet[int]() + ## values.incl(2) + ## values.incl(2) + ## assert values.len == 1 assert s.isValid, "The set needs to be initialized." inclImpl() proc incl*[A](s: var TSet[A], other: TSet[A]) = - ## includes everything in `other` in `s` + ## Includes all elements from `other` into `s`. + ## + ## Example: + ## + ## .. code-block:: + ## var values = initSet[int]() + ## values.incl(2) + ## var others = toSet([6, 7]) + ## values.incl(others) + ## assert values.len == 3 assert s.isValid, "The set `s` needs to be initialized." assert other.isValid, "The set `other` needs to be initialized." for item in other: incl(s, item) proc excl*[A](s: var TSet[A], key: A) = - ## excludes `key` from the set `s`. + ## Excludes `key` from the set `s`. + ## + ## This doesn't do anything if `key` is not found in `s`. Example: + ## + ## .. code-block:: + ## var s = toSet([2, 3, 6, 7]) + ## s.excl(2) + ## s.excl(2) + ## assert s.len == 3 assert s.isValid, "The set needs to be initialized." var index = rawGet(s, key) if index >= 0: @@ -149,14 +215,33 @@ proc excl*[A](s: var TSet[A], key: A) = dec(s.counter) proc excl*[A](s: var TSet[A], other: TSet[A]) = - ## excludes everything in `other` from `s`. + ## Excludes everything in `other` from `s`. + ## + ## Example: + ## + ## .. code-block:: + ## var + ## numbers = toSet([1, 2, 3, 4, 5]) + ## even = toSet([2, 4, 6, 8]) + ## numbers.excl(even) + ## echo numbers + ## # --> {1, 3, 5} assert s.isValid, "The set `s` needs to be initialized." assert other.isValid, "The set `other` needs to be initialized." for item in other: excl(s, item) proc containsOrIncl*[A](s: var TSet[A], key: A): bool = - ## returns true if `s` contains `key`, otherwise `key` is included in `s` - ## and false is returned. + ## Includes `key` in the set `s` and tells if `key` was added to `s`. + ## + ## The difference with regards to the `incl() <#incl,TSet[A],A>`_ proc is + ## that this proc returns `true` if `key` was already present in `s`. The + ## proc will return false if `key` was added as a new value to `s` during + ## this call. Example: + ## + ## .. code-block:: + ## var values = initSet[int]() + ## assert values.containsOrIncl(2) == false + ## assert values.containsOrIncl(2) == true assert s.isValid, "The set needs to be initialized." containsOrInclImpl() @@ -169,7 +254,7 @@ proc init*[A](s: var TSet[A], initialSize=64) = ## with other procs from this module with the exception of `isValid() ## <#isValid,TSet[A]>`_ and `len() <#len,TSet[A]>`_. ## - ## You can call this method on a previously initialized hash set, which will + ## You can call this proc on a previously initialized hash set, which will ## discard all its values. This might be more convenient than iterating over ## existing values and calling `excl() <#excl,TSet[A],A>`_ on them. Example: ## @@ -184,7 +269,8 @@ proc init*[A](s: var TSet[A], initialSize=64) = newSeq(s.data, initialSize) proc initSet*[A](initialSize=64): TSet[A] = - ## Convenience wrapper around `init() <#init,TSet[A]>`_. + ## Wrapper around `init() <#init,TSet[A],int>`_ for initialization of hash + ## sets. ## ## Returns an empty hash set you can assign directly in ``var`` blocks in a ## single line. Example: @@ -195,7 +281,14 @@ proc initSet*[A](initialSize=64): TSet[A] = result.init(initialSize) proc toSet*[A](keys: openArray[A]): TSet[A] = - ## creates a new hash set that contains the given `keys`. + ## Creates a new hash set that contains the given `keys`. + ## + ## Example: + ## + ## .. code-block:: + ## var numbers = toSet([1, 2, 3, 4, 5]) + ## assert numbers.contains(2) + ## assert numbers.contains(4) result = initSet[A](nextPowerOfTwo(keys.len+10)) for key in items(keys): result.incl(key) @@ -207,20 +300,51 @@ template dollarImpl(): stmt {.dirty.} = result.add("}") proc `$`*[A](s: TSet[A]): string = - ## The `$` operator for hash sets. + ## Converts the set `s` to a string, mostly for logging purposes. + ## + ## Don't use this proc for serialization, the representation may change at + ## any moment and values are not escaped. Example: + ## + ## Example: + ## + ## .. code-block:: + ## echo toSet([2, 4, 5]) + ## # --> {2, 4, 5} + ## echo toSet(["no", "esc'aping", "is \" provided"]) + ## # --> {no, esc'aping, is " provided} assert s.isValid, "The set needs to be initialized." dollarImpl() proc union*[A](s1, s2: TSet[A]): TSet[A] = - ## returns a new set of all items that are contained in at - ## least one of `s1` and `s2` + ## Returns the union of the sets `s1` and `s2`. + ## + ## The union of two sets is represented mathematically as *A ∪ B* and is the + ## set of all objects that are members of `s1`, `s2` or both. Example: + ## + ## .. code-block:: + ## var + ## a = toSet(["a", "b"]) + ## b = toSet(["b", "c"]) + ## c = union(a, b) + ## assert c == toSet(["a", "b", "c"]) assert s1.isValid, "The set `s1` needs to be initialized." assert s2.isValid, "The set `s2` needs to be initialized." result = s1 incl(result, s2) proc intersection*[A](s1, s2: TSet[A]): TSet[A] = - ## returns a new set of all items that are contained in both `s1` and `s2` + ## Returns the intersection of the sets `s1` and `s2`. + ## + ## The intersection of two sets is represented mathematically as *A ∩ B* and + ## is the set of all objects that are members of `s1` and `s2` at the same + ## time. Example: + ## + ## .. code-block:: + ## var + ## a = toSet(["a", "b"]) + ## b = toSet(["b", "c"]) + ## c = intersection(a, b) + ## assert c == toSet(["b"]) assert s1.isValid, "The set `s1` needs to be initialized." assert s2.isValid, "The set `s2` needs to be initialized." result = initSet[A](min(s1.data.len, s2.data.len)) @@ -228,7 +352,18 @@ proc intersection*[A](s1, s2: TSet[A]): TSet[A] = if item in s2: incl(result, item) proc difference*[A](s1, s2: TSet[A]): TSet[A] = - ## returns a new set of all items that are contained in `s1`, but not in `s2` + ## Returns the difference of the sets `s1` and `s2`. + ## + ## The difference of two sets is represented mathematically as *A \ B* and is + ## the set of all objects that are members of `s1` and not members of `s2`. + ## Example: + ## + ## .. code-block:: + ## var + ## a = toSet(["a", "b"]) + ## b = toSet(["b", "c"]) + ## c = difference(a, b) + ## assert c == toSet(["a"]) assert s1.isValid, "The set `s1` needs to be initialized." assert s2.isValid, "The set `s2` needs to be initialized." result = initSet[A]() @@ -237,8 +372,18 @@ proc difference*[A](s1, s2: TSet[A]): TSet[A] = incl(result, item) proc symmetricDifference*[A](s1, s2: TSet[A]): TSet[A] = - ## returns a new set of all items that are contained in either - ## `s1` or `s2`, but not both + ## Returns the symmetric difference of the sets `s1` and `s2`. + ## + ## The symmetric difference of two sets is represented mathematically as *A △ + ## B* or *A ⊖ B* and is the set of all objects that are members of `s1` or + ## `s2` but not both at the same time. Example: + ## + ## .. code-block:: + ## var + ## a = toSet(["a", "b"]) + ## b = toSet(["b", "c"]) + ## c = symmetricDifference(a, b) + ## assert c == toSet(["a", "c"]) assert s1.isValid, "The set `s1` needs to be initialized." assert s2.isValid, "The set `s2` needs to be initialized." result = s1 @@ -246,23 +391,32 @@ proc symmetricDifference*[A](s1, s2: TSet[A]): TSet[A] = if containsOrIncl(result, item): excl(result, item) proc `+`*[A](s1, s2: TSet[A]): TSet[A] {.inline.} = - ## alias for `union` + ## Alias for `union(s1, s2) <#union>`_. result = union(s1, s2) proc `*`*[A](s1, s2: TSet[A]): TSet[A] {.inline.} = - ## alias for `intersection` + ## Alias for `intersection(s1, s2) <#intersection>`_. result = intersection(s1, s2) proc `-`*[A](s1, s2: TSet[A]): TSet[A] {.inline.} = - ## alias for `difference` + ## Alias for `difference(s1, s2) <#difference>`_. result = difference(s1, s2) proc `-+-`*[A](s1, s2: TSet[A]): TSet[A] {.inline.} = - ## alias for `symmetricDifference` + ## Alias for `symmetricDifference(s1, s2) <#symmetricDifference>`_. result = symmetricDifference(s1, s2) proc disjoint*[A](s1, s2: TSet[A]): bool = - ## returns true iff `s1` and `s2` have no items in common + ## Returns true iff the sets `s1` and `s2` have no items in common. + ## + ## Example: + ## + ## .. code-block:: + ## var + ## a = toSet(["a", "b"]) + ## b = toSet(["b", "c"]) + ## assert disjoint(a, b) == false + ## assert disjoint(a, b - a) == true assert s1.isValid, "The set `s1` needs to be initialized." assert s2.isValid, "The set `s2` needs to be initialized." for item in s1: @@ -270,11 +424,33 @@ proc disjoint*[A](s1, s2: TSet[A]): bool = return true proc `<`*[A](s, t: TSet[A]): bool = - ## Is s a strict subset of t? + ## Returns true if `s` is a strict or proper subset of `t`. + ## + ## A strict or proper subset `s` has all of its members in `t` but `t` has + ## more elements than `s`. Example: + ## + ## .. code-block:: + ## var + ## a = toSet(["a", "b"]) + ## b = toSet(["b", "c"]) + ## c = intersection(a, b) + ## assert c < a and c < b + ## assert((a < a) == false) s.counter != t.counter and s <= t proc `<=`*[A](s, t: TSet[A]): bool = - ## Is s a subset of t? + ## Returns true if `s` is subset of `t`. + ## + ## A subset `s` has all of its members in `t` and `t` doesn't necessarily + ## have more members than `s`. That is, `s` can be equal to `t`. Example: + ## + ## .. code-block:: + ## var + ## a = toSet(["a", "b"]) + ## b = toSet(["b", "c"]) + ## c = intersection(a, b) + ## assert c <= a and c <= b + ## assert((a <= a)) result = false if s.counter > t.counter: return result = true @@ -284,9 +460,27 @@ proc `<=`*[A](s, t: TSet[A]): bool = return proc `==`*[A](s, t: TSet[A]): bool = + ## Returns true if both `s` and `t` have the same members and set size. + ## + ## Example: + ## + ## .. code-block:: + ## var + ## a = toSet([1, 2]) + ## b = toSet([1]) + ## b.incl(2) + ## assert a == b s.counter == t.counter and s <= t proc map*[A, B](data: TSet[A], op: proc (x: A): B {.closure.}): TSet[B] = + ## Returns a new set after applying `op` on each of the elements of `data`. + ## + ## You can use this proc to transform the elements from a set. Example: + ## + ## .. code-block:: + ## var a = toSet([1, 2, 3]) + ## var b = a.map(proc (x: int): string = $x) + ## assert b == toSet(["1", "2", "3"]) result = initSet[B]() for item in data: result.incl(op(item)) @@ -300,7 +494,7 @@ type final, myShallow.}[A] = object ## \ ## A generic hash set that remembers insertion order. ## - ## Use `init() <#init,TOrderedSet[A]>`_ or `initOrderedSet[type]() + ## Use `init() <#init,TOrderedSet[A],int>`_ or `initOrderedSet[type]() ## <#initOrderedSet>`_ before calling other procs on it. data: TOrderedKeyValuePairSeq[A] counter, first, last: int @@ -311,7 +505,7 @@ proc isValid*[A](s: TOrderedSet[A]): bool = ## ## Most operations over an uninitialized ordered set will crash at runtime ## and `assert `_ in debug builds. You can use this proc - ## in your own methods to verify that ordered sets passed to your procs are + ## in your own procs to verify that ordered sets passed to your procs are ## correctly initialized. Example: ## ## .. code-block :: nimrod @@ -321,11 +515,21 @@ proc isValid*[A](s: TOrderedSet[A]): bool = result = not s.data.isNil proc len*[A](s: TOrderedSet[A]): int {.inline.} = - ## returns the number of keys in `s`. + ## Returns the number of keys in `s`. + ## + ## Due to an implementation detail you can call this proc on variables which + ## have not been initialized yet. The proc will return zero as the length + ## then. Example: + ## + ## .. code-block:: + ## + ## var values: TOrderedSet[int] + ## assert(not values.isValid) + ## assert values.len == 0 result = s.counter proc card*[A](s: TOrderedSet[A]): int {.inline.} = - ## alias for `len`. + ## Alias for `len() <#len,TOrderedSet[A]>`_. result = s.counter template forAllOrderedPairs(yieldStmt: stmt) {.dirty, immediate.} = @@ -336,7 +540,23 @@ template forAllOrderedPairs(yieldStmt: stmt) {.dirty, immediate.} = h = nxt iterator items*[A](s: TOrderedSet[A]): A = - ## iterates over any key in the set `s` in insertion order. + ## Iterates over keys in the ordered set `s` in insertion order. + ## + ## If you need a sequence with the keys you can use `sequtils.toSeq() + ## `_ on the iterator. Usage example: + ## + ## .. code-block:: + ## var a = initOrderedSet[int]() + ## for value in [9, 2, 1, 5, 1, 8, 4, 2]: + ## a.incl(value) + ## for value in a.items: + ## echo "Got ", value + ## # --> Got 9 + ## # --> Got 2 + ## # --> Got 1 + ## # --> Got 5 + ## # --> Got 8 + ## # --> Got 4 assert s.isValid, "The set needs to be initialized." forAllOrderedPairs: yield s.data[h].key @@ -345,7 +565,15 @@ proc rawGet[A](s: TOrderedSet[A], key: A): int = rawGetImpl() proc contains*[A](s: TOrderedSet[A], key: A): bool = - ## returns true iff `key` is in `s`. + ## Returns true iff `key` is in `s`. + ## + ## Example: + ## + ## .. code-block:: + ## var values = initOrderedSet[int]() + ## assert(not values.contains(2)) + ## values.incl(2) + ## assert values.contains(2) assert s.isValid, "The set needs to be initialized." var index = rawGet(s, key) result = index >= 0 @@ -372,19 +600,45 @@ proc enlarge[A](s: var TOrderedSet[A]) = swap(s.data, n) proc incl*[A](s: var TOrderedSet[A], key: A) = - ## includes an element `key` in `s`. + ## Includes an element `key` in `s`. + ## + ## This doesn't do anything if `key` is already in `s`. Example: + ## + ## .. code-block:: + ## var values = initOrderedSet[int]() + ## values.incl(2) + ## values.incl(2) + ## assert values.len == 1 assert s.isValid, "The set needs to be initialized." inclImpl() proc incl*[A](s: var TSet[A], other: TOrderedSet[A]) = - ## includes everything in `other` in `s` + ## Includes all elements from `other` into `s`. + ## + ## Example: + ## + ## .. code-block:: + ## var values = initOrderedSet[int]() + ## values.incl(2) + ## var others = toOrderedSet([6, 7]) + ## values.incl(others) + ## assert values.len == 3 assert s.isValid, "The set `s` needs to be initialized." assert other.isValid, "The set `other` needs to be initialized." for item in other: incl(s, item) proc containsOrIncl*[A](s: var TOrderedSet[A], key: A): bool = - ## returns true if `s` contains `key`, otherwise `key` is included in `s` - ## and false is returned. + ## Includes `key` in the set `s` and tells if `key` was added to `s`. + ## + ## The difference with regards to the `incl() <#incl,TOrderedSet[A],A>`_ proc + ## is that this proc returns `true` if `key` was already present in `s`. The + ## proc will return false if `key` was added as a new value to `s` during + ## this call. Example: + ## + ## .. code-block:: + ## var values = initOrderedSet[int]() + ## assert values.containsOrIncl(2) == false + ## assert values.containsOrIncl(2) == true assert s.isValid, "The set needs to be initialized." containsOrInclImpl() @@ -397,9 +651,9 @@ proc init*[A](s: var TOrderedSet[A], initialSize=64) = ## with other procs from this module with the exception of `isValid() ## <#isValid,TOrderedSet[A]>`_ and `len() <#len,TOrderedSet[A]>`_. ## - ## You can call this method on a previously initialized ordered hash set to - ## discard its values. At the moment this is the only method to remove - ## elements from an ordered hash set. Example: + ## You can call this proc on a previously initialized ordered hash set to + ## discard its values. At the moment this is the only proc to remove elements + ## from an ordered hash set. Example: ## ## .. code-block :: ## var a: TOrderedSet[int] @@ -414,7 +668,8 @@ proc init*[A](s: var TOrderedSet[A], initialSize=64) = newSeq(s.data, initialSize) proc initOrderedSet*[A](initialSize=64): TOrderedSet[A] = - ## Convenience wrapper around `init() <#init,TOrderedSet[A]>`_. + ## Wrapper around `init() <#init,TOrderedSet[A],int>`_ for initialization of + ## ordered hash sets. ## ## Returns an empty ordered hash set you can assign directly in ``var`` ## blocks in a single line. Example: @@ -425,12 +680,30 @@ proc initOrderedSet*[A](initialSize=64): TOrderedSet[A] = result.init(initialSize) proc toOrderedSet*[A](keys: openArray[A]): TOrderedSet[A] = - ## creates a new ordered hash set that contains the given `keys`. + ## Creates a new ordered hash set that contains the given `keys`. + ## + ## Example: + ## + ## .. code-block:: + ## var numbers = toOrderedSet([1, 2, 3, 4, 5]) + ## assert numbers.contains(2) + ## assert numbers.contains(4) result = initOrderedSet[A](nextPowerOfTwo(keys.len+10)) for key in items(keys): result.incl(key) proc `$`*[A](s: TOrderedSet[A]): string = - ## The `$` operator for ordered hash sets. + ## Converts the ordered hash set `s` to a string, mostly for logging purposes. + ## + ## Don't use this proc for serialization, the representation may change at + ## any moment and values are not escaped. Example: + ## + ## Example: + ## + ## .. code-block:: + ## echo toOrderedSet([2, 4, 5]) + ## # --> {2, 4, 5} + ## echo toOrderedSet(["no", "esc'aping", "is \" provided"]) + ## # --> {no, esc'aping, is " provided} assert s.isValid, "The set needs to be initialized." dollarImpl() @@ -459,7 +732,7 @@ proc testModule() = b.incl((x - 2, y + 1)) assert a.len == b.card assert a.len == 2 - echo b + #echo b block setContains: var values = initSet[int]() @@ -469,40 +742,73 @@ proc testModule() = values.excl(2) assert(not values.contains(2)) + values.incl(4) + var others = toSet([6, 7]) + values.incl(others) + assert values.len == 3 + + values.init + assert values.containsOrIncl(2) == false + assert values.containsOrIncl(2) == true + var + a = toSet([1, 2]) + b = toSet([1]) + b.incl(2) + assert a == b + + block exclusions: + var s = toSet([2, 3, 6, 7]) + s.excl(2) + s.excl(2) + assert s.len == 3 + + var + numbers = toSet([1, 2, 3, 4, 5]) + even = toSet([2, 4, 6, 8]) + numbers.excl(even) + #echo numbers + # --> {1, 3, 5} + block toSeqAndString: - var a = toSet[int]([2, 4, 5]) + var a = toSet([2, 4, 5]) var b = initSet[int]() for x in [2, 4, 5]: b.incl(x) assert($a == $b) + #echo a + #echo toSet(["no", "esc'aping", "is \" provided"]) + + #block orderedToSeqAndString: + # echo toOrderedSet([2, 4, 5]) + # echo toOrderedSet(["no", "esc'aping", "is \" provided"]) block setOperations: var - a = toset[string](["a", "b"]) - b = toset[string](["b", "c"]) + a = toSet(["a", "b"]) + b = toSet(["b", "c"]) c = union(a, b) - assert c == toSet[string](["a", "b", "c"]) + assert c == toSet(["a", "b", "c"]) var d = intersection(a, b) - assert d == toSet[string](["b"]) + assert d == toSet(["b"]) var e = difference(a, b) - assert e == toSet[string](["a"]) + assert e == toSet(["a"]) var f = symmetricDifference(a, b) - assert f == toSet[string](["a", "c"]) + assert f == toSet(["a", "c"]) assert d < a and d < b assert((a < a) == false) assert d <= a and d <= b assert((a <= a)) # Alias test. - assert a + b == toSet[string](["a", "b", "c"]) - assert a * b == toSet[string](["b"]) - assert a - b == toSet[string](["a"]) - assert a -+- b == toSet[string](["a", "c"]) + assert a + b == toSet(["a", "b", "c"]) + assert a * b == toSet(["b"]) + assert a - b == toSet(["a"]) + assert a -+- b == toSet(["a", "c"]) assert disjoint(a, b) == false assert disjoint(a, b - a) == true block mapSet: - var a = toSet[int]([1, 2, 3]) + var a = toSet([1, 2, 3]) var b = a.map(proc (x: int): string = $x) - assert b == toSet[string](["1", "2", "3"]) + assert b == toSet(["1", "2", "3"]) block isValidTest: var cards: TOrderedSet[string] @@ -528,6 +834,13 @@ proc testModule() = assert a.len == b.card assert a.len == 2 + #block orderedSetIterator: + # var a = initOrderedSet[int]() + # for value in [9, 2, 1, 5, 1, 8, 4, 2]: + # a.incl(value) + # for value in a.items: + # echo "Got ", value + block setContains: var values = initOrderedSet[int]() assert(not values.contains(2)) @@ -535,7 +848,7 @@ proc testModule() = assert values.contains(2) block toSeqAndString: - var a = toOrderedSet[int]([2, 4, 5]) + var a = toOrderedSet([2, 4, 5]) var b = initOrderedSet[int]() for x in [2, 4, 5]: b.incl(x) assert($a == $b) From b87ec14579ac89b56be9d0b5788f3788f836245a Mon Sep 17 00:00:00 2001 From: Grzegorz Adam Hankiewicz Date: Sun, 27 Jul 2014 00:21:23 +0200 Subject: [PATCH 066/234] Factors common documentation in fragment to avoid repetition. --- doc/manual.txt | 32 +------------------------------- doc/sets_fragment.txt | 40 ++++++++++++++++++++++++++++++++++++++++ doc/tut1.txt | 41 +---------------------------------------- 3 files changed, 42 insertions(+), 71 deletions(-) create mode 100644 doc/sets_fragment.txt diff --git a/doc/manual.txt b/doc/manual.txt index 54c1477e8c..53700ae807 100644 --- a/doc/manual.txt +++ b/doc/manual.txt @@ -1221,38 +1221,8 @@ branch switch ``system.reset`` has to be used. Set type -------- -The set type models the mathematical notion of a set. The set's -basetype can only be an ordinal type. The reason is that sets are implemented -as high performance bit vectors. - -Sets can be constructed via the set constructor: ``{}`` is the empty set. The -empty set is type compatible with any special set type. The constructor -can also be used to include elements (and ranges of elements) in the set: - -.. code-block:: nimrod - - {'a'..'z', '0'..'9'} # This constructs a set that contains the - # letters from 'a' to 'z' and the digits - # from '0' to '9' - -These operations are supported by sets: - -================== ======================================================== -operation meaning -================== ======================================================== -``A + B`` union of two sets -``A * B`` intersection of two sets -``A - B`` difference of two sets (A without B's elements) -``A == B`` set equality -``A <= B`` subset relation (A is subset of B or equal to B) -``A < B`` strong subset relation (A is a real subset of B) -``e in A`` set membership (A contains element e) -``A -+- B`` symmetric set difference (= (A - B) + (B - A)) -``card(A)`` the cardinality of A (number of elements in A) -``incl(A, elem)`` same as A = A + {elem} -``excl(A, elem)`` same as A = A - {elem} -================== ======================================================== +.. include:: sets_fragment.txt Reference and pointer types --------------------------- diff --git a/doc/sets_fragment.txt b/doc/sets_fragment.txt new file mode 100644 index 0000000000..fba3552690 --- /dev/null +++ b/doc/sets_fragment.txt @@ -0,0 +1,40 @@ +The set type models the mathematical notion of a set. The set's +basetype can only be an ordinal type. The reason is that sets are implemented +as high performance bit vectors. + +Sets can be constructed via the set constructor: ``{}`` is the empty set. The +empty set is type compatible with any concrete set type. The constructor +can also be used to include elements (and ranges of elements): + +.. code-block:: nimrod + type + TCharSet = set[char] + var + x: TCharSet + x = {'a'..'z', '0'..'9'} # This constructs a set that contains the + # letters from 'a' to 'z' and the digits + # from '0' to '9' + +These operations are supported by sets: + +================== ======================================================== +operation meaning +================== ======================================================== +``A + B`` union of two sets +``A * B`` intersection of two sets +``A - B`` difference of two sets (A without B's elements) +``A == B`` set equality +``A <= B`` subset relation (A is subset of B or equal to B) +``A < B`` strong subset relation (A is a real subset of B) +``e in A`` set membership (A contains element e) +``e notin A`` A does not contain element e +``contains(A, e)`` A contains element e +``A -+- B`` symmetric set difference (= (A - B) + (B - A)) +``card(A)`` the cardinality of A (number of elements in A) +``incl(A, elem)`` same as ``A = A + {elem}`` +``excl(A, elem)`` same as ``A = A - {elem}`` +================== ======================================================== + +Sets are often used to define a type for the *flags* of a procedure. This is +a much cleaner (and type safe) solution than just defining integer +constants that should be ``or``'ed together. diff --git a/doc/tut1.txt b/doc/tut1.txt index a2aa835ee5..55eb0ebd74 100644 --- a/doc/tut1.txt +++ b/doc/tut1.txt @@ -1117,47 +1117,8 @@ avoid this common programming error. Sets ---- -The set type models the mathematical notion of a set. The set's -basetype can only be an ordinal type. The reason is that sets are implemented -as high performance bit vectors. - -Sets can be constructed via the set constructor: ``{}`` is the empty set. The -empty set is type compatible with any concrete set type. The constructor -can also be used to include elements (and ranges of elements): - -.. code-block:: nimrod - type - TCharSet = set[char] - var - x: TCharSet - x = {'a'..'z', '0'..'9'} # This constructs a set that contains the - # letters from 'a' to 'z' and the digits - # from '0' to '9' - -These operations are supported by sets: - -================== ======================================================== -operation meaning -================== ======================================================== -``A + B`` union of two sets -``A * B`` intersection of two sets -``A - B`` difference of two sets (A without B's elements) -``A == B`` set equality -``A <= B`` subset relation (A is subset of B or equal to B) -``A < B`` strong subset relation (A is a real subset of B) -``e in A`` set membership (A contains element e) -``e notin A`` A does not contain element e -``contains(A, e)`` A contains element e -``A -+- B`` symmetric set difference (= (A - B) + (B - A)) -``card(A)`` the cardinality of A (number of elements in A) -``incl(A, elem)`` same as ``A = A + {elem}`` -``excl(A, elem)`` same as ``A = A - {elem}`` -================== ======================================================== - -Sets are often used to define a type for the *flags* of a procedure. This is -a much cleaner (and type safe) solution than just defining integer -constants that should be ``or``'ed together. +.. include:: sets_fragment.txt Arrays ------ From e9417b55cfea809638de7f09865115e3ec6907c9 Mon Sep 17 00:00:00 2001 From: Grzegorz Adam Hankiewicz Date: Sun, 27 Jul 2014 09:42:49 +0200 Subject: [PATCH 067/234] Adds definition of card term to sets module. --- lib/pure/collections/sets.nim | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/pure/collections/sets.nim b/lib/pure/collections/sets.nim index f63805e4e7..42cdc682fb 100644 --- a/lib/pure/collections/sets.nim +++ b/lib/pure/collections/sets.nim @@ -65,6 +65,9 @@ proc len*[A](s: TSet[A]): int = proc card*[A](s: TSet[A]): int = ## Alias for `len() <#len,TSet[A]>`_. + ## + ## Card stands for the `cardinality + ## `_ of a set. result = s.counter iterator items*[A](s: TSet[A]): A = @@ -530,6 +533,9 @@ proc len*[A](s: TOrderedSet[A]): int {.inline.} = proc card*[A](s: TOrderedSet[A]): int {.inline.} = ## Alias for `len() <#len,TOrderedSet[A]>`_. + ## + ## Card stands for the `cardinality + ## `_ of a set. result = s.counter template forAllOrderedPairs(yieldStmt: stmt) {.dirty, immediate.} = From f345b0278bf6ac2db389a17297ff03fde7891743 Mon Sep 17 00:00:00 2001 From: Grzegorz Adam Hankiewicz Date: Sun, 27 Jul 2014 20:24:39 +0200 Subject: [PATCH 068/234] Adds os.copyDirWithPermissions(). --- lib/pure/os.nim | 39 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/lib/pure/os.nim b/lib/pure/os.nim index a7f4f7d916..b189ec224d 100644 --- a/lib/pure/os.nim +++ b/lib/pure/os.nim @@ -1363,7 +1363,13 @@ proc createDir*(dir: string) {.rtl, extern: "nos$1", tags: [FWriteDir].} = proc copyDir*(source, dest: string) {.rtl, extern: "nos$1", tags: [FWriteIO, FReadIO].} = - ## Copies a directory from `source` to `dest`. If this fails, `EOS` is raised. + ## Copies a directory from `source` to `dest`. + ## + ## If this fails, `EOS` is raised. On the Windows platform this proc will + ## copy the attributes from `source` into `dest`. On other platforms created + ## files and directories will inherit the default permissions of a newly + ## created file/directory for the user. To preserve attributes recursively on + ## these platforms use `copyDirWithPermissions() <#copyDirWithPermissions>`_. createDir(dest) for kind, path in walkDir(source): var noSource = path.substr(source.len()+1) @@ -1523,6 +1529,37 @@ proc copyFileWithPermissions*(source, dest: string, if not ignorePermissionErrors: raise +proc copyDirWithPermissions*(source, dest: string, + ignorePermissionErrors = true) {.rtl, extern: "nos$1", + tags: [FWriteIO, FReadIO].} = + ## Copies a directory from `source` to `dest` preserving file permissions. + ## + ## If this fails, `EOS` is raised. This is a wrapper proc around `copyDir() + ## <#copyDir>`_ and `copyFileWithPermissions() <#copyFileWithPermissions>`_ + ## on non Windows platforms. On Windows this proc is just a wrapper for + ## `copyDir() <#copyDir>`_ since that proc already copies attributes. + ## + ## On non Windows systems permissions are copied after the file or directory + ## itself has been copied, which won't happen atomically and could lead to a + ## race condition. If `ignorePermissionErrors` is true, errors while + ## reading/setting file attributes will be ignored, otherwise will raise + ## `OSError`. + createDir(dest) + when not defined(Windows): + try: + setFilePermissions(dest, getFilePermissions(source)) + except: + if not ignorePermissionErrors: + raise + for kind, path in walkDir(source): + var noSource = path.substr(source.len()+1) + case kind + of pcFile: + copyFileWithPermissions(path, dest / noSource, ignorePermissionErrors) + of pcDir: + copyDirWithPermissions(path, dest / noSource, ignorePermissionErrors) + else: discard + proc inclFilePermissions*(filename: string, permissions: set[TFilePermission]) {. rtl, extern: "nos$1", tags: [FReadDir, FWriteDir].} = From d597767d70992cd879eec88a1c025b93187b5352 Mon Sep 17 00:00:00 2001 From: Grzegorz Adam Hankiewicz Date: Sun, 27 Jul 2014 20:27:38 +0200 Subject: [PATCH 069/234] Adds hyperlinks to copyFile* docstrings. --- lib/pure/os.nim | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/lib/pure/os.nim b/lib/pure/os.nim index b189ec224d..a70bfa7f10 100644 --- a/lib/pure/os.nim +++ b/lib/pure/os.nim @@ -955,11 +955,12 @@ proc copyFile*(source, dest: string) {.rtl, extern: "nos$1", ## ## If this fails, `EOS` is raised. On the Windows platform this proc will ## copy the source file's attributes into dest. On other platforms you need - ## to use getFilePermissions and setFilePermissions to copy them by hand (or - ## use the convenience copyFileWithPermissions() proc), otherwise `dest` will - ## inherit the default permissions of a newly created file for the user. If - ## `dest` already exists, the file attributes will be preserved and the - ## content overwritten. + ## to use `getFilePermissions() <#getFilePermissions>`_ and + ## `setFilePermissions() <#setFilePermissions>`_ to copy them by hand (or use + ## the convenience `copyFileWithPermissions() <#copyFileWithPermissions>`_ + ## proc), otherwise `dest` will inherit the default permissions of a newly + ## created file for the user. If `dest` already exists, the file attributes + ## will be preserved and the content overwritten. when defined(Windows): when useWinUnicode: let s = newWideCString(source) @@ -1513,14 +1514,17 @@ proc copyFileWithPermissions*(source, dest: string, ignorePermissionErrors = true) = ## Copies a file from `source` to `dest` preserving file permissions. ## - ## This is a wrapper proc around copyFile, getFilePermissions and - ## setFilePermissions on non Windows platform. On windows this proc is just a - ## wrapper for copyFile since that proc already copies attributes. + ## This is a wrapper proc around `copyFile() <#copyFile>`_, + ## `getFilePermissions() <#getFilePermissions>`_ and `setFilePermissions() + ## <#setFilePermissions>`_ on non Windows platform. On Windows this proc is + ## just a wrapper for `copyFile() <#copyFile>`_ since that proc already + ## copies attributes. ## - ## On non windows systems permissions are copied after the file itself has + ## On non Windows systems permissions are copied after the file itself has ## been copied, which won't happen atomically and could lead to a race - ## condition. If ignorePermissionErrors is true, errors while reading/setting - ## file attributes will be ignored, otherwise will raise `OSError`. + ## condition. If `ignorePermissionErrors` is true, errors while + ## reading/setting file attributes will be ignored, otherwise will raise + ## `OSError`. copyFile(source, dest) when not defined(Windows): try: From 2ade6ab94da40043186fbc2fbbf038c0f497b4e4 Mon Sep 17 00:00:00 2001 From: Grzegorz Adam Hankiewicz Date: Sun, 27 Jul 2014 22:27:21 +0200 Subject: [PATCH 070/234] Documents nimcache file naming scheme. Refs #852. --- doc/backends.txt | 60 ++++++++++++++++++++++++++++++++++++++++++++++++ doc/nimrodc.txt | 10 ++++---- 2 files changed, 66 insertions(+), 4 deletions(-) diff --git a/doc/backends.txt b/doc/backends.txt index 26576e7331..adcd741490 100644 --- a/doc/backends.txt +++ b/doc/backends.txt @@ -322,6 +322,66 @@ earlier, JavaScript doesn't require an initialisation call to ``NimMain`` or similar function and you can call the exported Nimrod proc directly. +Nimcache naming logic +--------------------- + +The `nimcache`:idx: directory is generated during compilation and will hold +either temporary or final files depending on your backend target. The default +name for the directory is ``nimcache`` but you can use the ``--nimcache`` +`compiler switch `_ to change it. + +Nimcache and C like targets +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The C like backends will place their temporary ``.c``, ``.cpp`` or ``.m`` files +in the ``nimcache`` directory. The name of this files follows this logic: + +* Filenames for your project will be renamed from ``.nim`` to have the + extension of your target backend (from now on ``.c`` for these examples), but + otherwise nothing else will change. This will quickly break if your project + consists of a main ``proj.nim`` file which includes a ``utils/proj.nim`` + file: both ``proj.nim`` files will generate the same name ``proj.c`` output + in the ``nimcache`` directory overwriting themselves! + +* Filenames for modules found in the standard library will be named + ``stdlib_module.c``. Unless you are doing something special, you + will end up with at least ``stdlib_system.c``, since the `system + module `_ is always imported automatically. Same for + the `hashes module `_ which will be named + ``stdlib_hashes.c`` + +* Filenames for modules not part of the standard library and found + through additional paths specified with the ``--path`` compiler + switch will use as prefix their parent directory. For example, + the `rstgen module `_ will generate ``docutils_rstgen.c`` + because the `lib/packages/docutils directory + `_ is + not included in the standard library and you need to either write + ``import packages/docutils/rstgen`` or add + ``--path:"$lib/pkages/docutils`` to the compiler switches to be + able to use it. + +* Filenames for modules imported from `babel packages + `_ will end up with + ``babelPackageName_module.c``. For example, if you import the + ``argument_parser`` module from the same name babel package you will end up + with a ``argument_parser_argument_parser.c`` file under ``nimcache``. + +To find out about what paths are part of the default standard library, create a +dummy ``hello.nim`` file and run ``nimrod dump hello.nim``. This will display +the defined simbols and the list of paths for the standard library. + + +Nimcache and the Javascript target +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Unless you explicitly use the ``-o:filename.js`` switch as mentioned in the +previous examples, the compiler will create a ``filename.js`` file in the +``nimcache`` directory using the name of your input nimrod file. There are no +other temporary files generated, the output is always a single self contained +``.js`` file. + + Memory management ================= diff --git a/doc/nimrodc.txt b/doc/nimrodc.txt index 428c42f39d..1962eb0f0f 100644 --- a/doc/nimrodc.txt +++ b/doc/nimrodc.txt @@ -152,10 +152,12 @@ the first matching file is used. Generated C code directory -------------------------- -The generated files that Nimrod produces all go into a subdirectory called -``nimcache`` in your project directory. This makes it easy to delete all -generated files. - +The generated files that Nimrod produces all go into a subdirectory called +``nimcache`` in your project directory. This makes it easy to delete all +generated files. Files generated in this directory follow a naming logic which +you can read about in the `Nimrod Backend Integration document +`_. + However, the generated C code is not platform independent. C code generated for Linux does not compile on Windows, for instance. The comment on top of the C file lists the OS, CPU and CC the file has been compiled for. From bb34d0380a0538f2784701ed05679e31155dc232 Mon Sep 17 00:00:00 2001 From: Grzegorz Adam Hankiewicz Date: Sun, 27 Jul 2014 22:55:03 +0200 Subject: [PATCH 071/234] Makes ios example work again with new paths. Refs #852. --- .../project.pbxproj | 20 ++++++------------- .../ios/scripts/xcode_prebuild.sh | 2 +- 2 files changed, 7 insertions(+), 15 deletions(-) mode change 100644 => 100755 examples/cross_calculator/ios/scripts/xcode_prebuild.sh diff --git a/examples/cross_calculator/ios/cross-calculator.xcodeproj/project.pbxproj b/examples/cross_calculator/ios/cross-calculator.xcodeproj/project.pbxproj index 36b43d31bf..71cebc18a9 100644 --- a/examples/cross_calculator/ios/cross-calculator.xcodeproj/project.pbxproj +++ b/examples/cross_calculator/ios/cross-calculator.xcodeproj/project.pbxproj @@ -13,7 +13,7 @@ D531424D15BC87B6005EFF20 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = D531424A15BC87B6005EFF20 /* AppDelegate.m */; }; D531424E15BC87B6005EFF20 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = D531424B15BC87B6005EFF20 /* main.m */; }; D531427215BC94B1005EFF20 /* backend.m in Sources */ = {isa = PBXBuildFile; fileRef = D531426F15BC94B1005EFF20 /* backend.m */; }; - D531427415BC94B1005EFF20 /* system.m in Sources */ = {isa = PBXBuildFile; fileRef = D531427115BC94B1005EFF20 /* system.m */; }; + D531427415BC94B1005EFF20 /* stdlib_system.m in Sources */ = {isa = PBXBuildFile; fileRef = D531427115BC94B1005EFF20 /* stdlib_system.m */; }; D5B6F94815FA8D4C0084A85B /* NRViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D5B6F94615FA8D4C0084A85B /* NRViewController.m */; }; /* End PBXBuildFile section */ @@ -30,7 +30,7 @@ D531426715BC91EF005EFF20 /* tags.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; name = tags.sh; path = scripts/tags.sh; sourceTree = ""; }; D531426815BC91EF005EFF20 /* xcode_prebuild.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; name = xcode_prebuild.sh; path = scripts/xcode_prebuild.sh; sourceTree = ""; }; D531426F15BC94B1005EFF20 /* backend.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = backend.m; path = build/nimcache/backend.m; sourceTree = ""; }; - D531427115BC94B1005EFF20 /* system.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = system.m; path = build/nimcache/system.m; sourceTree = ""; }; + D531427115BC94B1005EFF20 /* stdlib_system.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = stdlib_system.m; path = build/nimcache/stdlib_system.m; sourceTree = ""; }; D592E19015C7120F005258EA /* backend.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = backend.h; path = build/nimcache/backend.h; sourceTree = ""; }; D592E19115C71415005258EA /* nimbase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = nimbase.h; path = build/nimcache/nimbase.h; sourceTree = ""; }; D5B6F94515FA8D4C0084A85B /* NRViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NRViewController.h; path = src/NRViewController.h; sourceTree = ""; }; @@ -135,7 +135,7 @@ D592E19015C7120F005258EA /* backend.h */, D531426F15BC94B1005EFF20 /* backend.m */, D592E19115C71415005258EA /* nimbase.h */, - D531427115BC94B1005EFF20 /* system.m */, + D531427115BC94B1005EFF20 /* stdlib_system.m */, ); name = nimrod; sourceTree = ""; @@ -229,7 +229,7 @@ D531424D15BC87B6005EFF20 /* AppDelegate.m in Sources */, D531424E15BC87B6005EFF20 /* main.m in Sources */, D531427215BC94B1005EFF20 /* backend.m in Sources */, - D531427415BC94B1005EFF20 /* system.m in Sources */, + D531427415BC94B1005EFF20 /* stdlib_system.m in Sources */, D5B6F94815FA8D4C0084A85B /* NRViewController.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -259,11 +259,7 @@ GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 3.0; - OTHER_LDFLAGS = ( - "-weak_library", - /usr/lib/libSystem.B.dylib, - ); + IPHONEOS_DEPLOYMENT_TARGET = 4.3; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; }; @@ -284,12 +280,8 @@ GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 3.0; + IPHONEOS_DEPLOYMENT_TARGET = 4.3; OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; - OTHER_LDFLAGS = ( - "-weak_library", - /usr/lib/libSystem.B.dylib, - ); SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; diff --git a/examples/cross_calculator/ios/scripts/xcode_prebuild.sh b/examples/cross_calculator/ios/scripts/xcode_prebuild.sh old mode 100644 new mode 100755 index c6d38f1641..90bafd74e4 --- a/examples/cross_calculator/ios/scripts/xcode_prebuild.sh +++ b/examples/cross_calculator/ios/scripts/xcode_prebuild.sh @@ -22,7 +22,7 @@ DEST_NIMBASE=build/nimcache/nimbase.h if [ -d src ] then $PATH_TO_NIMROD objc --noMain --app:lib \ - --nimcache:build/nimcache --compileOnly \ + --nimcache:./build/nimcache --compileOnly \ --header --cpu:i386 ../nimrod_backend/backend.nim if [ "${PATH_TO_NIMBASE}" -nt "${DEST_NIMBASE}" ] then From c78b1070a8dec61ae6aa660fe724bf9fb67fb6a9 Mon Sep 17 00:00:00 2001 From: def Date: Mon, 28 Jul 2014 16:48:07 +0200 Subject: [PATCH 072/234] overlapping as a parameter for count instead --- lib/pure/strutils.nim | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim index acb803a4c0..1d17de2338 100644 --- a/lib/pure/strutils.nim +++ b/lib/pure/strutils.nim @@ -803,16 +803,20 @@ proc rfind*(s, sub: string, start: int = -1): int {.noSideEffect.} = if result != -1: return return -1 -proc count*(s: string, sub: string): int {.noSideEffect, +proc count*(s: string, sub: string, overlapping: bool = false): int {.noSideEffect, rtl, extern: "nsuCountString".} = - ## Count the occurences of a substring `sub` in the string `s`. Overlapping - ## occurences of `sub` do not count. + ## Count the occurences of a substring `sub` in the string `s`. + ## Overlapping occurences of `sub` only count when `overlapping` + ## is set to true. var i = 0 while true: i = s.find(sub, i) if i < 0: break - i += sub.len + if overlapping: + inc i + else: + i += sub.len inc result proc count*(s: string, sub: char): int {.noSideEffect, @@ -829,18 +833,6 @@ proc count*(s: string, subs: set[char]): int {.noSideEffect, if c in subs: inc result -proc countOverlapping*(s: string, sub: string): int {.noSideEffect, - rtl, extern: "nsuCountOverlapping".} = - ## Count the occurences of a substring `sub` in the string `s`. Overlapping - ## occurences of `sub` do count. - var i = 0 - while true: - i = s.find(sub, i) - if i < 0: - break - inc i - inc result - proc quoteIfContainsWhite*(s: string): string {.deprecated.} = ## Returns ``'"' & s & '"'`` if `s` contains a space and does not ## start with a quote, else returns `s`. @@ -1394,6 +1386,6 @@ when isMainModule: doAssert parseEnum("invalid enum value", enC) == enC doAssert count("foofoofoo", "foofoo") == 1 - doAssert countOverlapping("foofoofoo", "foofoo") == 2 + doAssert count("foofoofoo", "foofoo", overlapping = true) == 2 doAssert count("foofoofoo", 'f') == 3 doAssert count("foofoofoobar", {'f','b'}) == 4 From d9b5ae13be7c7f9e92a5af4fa4274eae8c57397f Mon Sep 17 00:00:00 2001 From: def Date: Mon, 28 Jul 2014 17:41:00 +0200 Subject: [PATCH 073/234] Allow arguments for "nimrod run" --- compiler/nimrod.nim | 2 +- compiler/service.nim | 2 +- compiler/tccgen.nim | 8 +++----- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/compiler/nimrod.nim b/compiler/nimrod.nim index efe3d83bfe..ea7621b095 100644 --- a/compiler/nimrod.nim +++ b/compiler/nimrod.nim @@ -58,7 +58,7 @@ proc handleCmdLine() = if msgs.gErrorCounter == 0: when hasTinyCBackend: if gCmd == cmdRun: - tccgen.run() + tccgen.run(service.arguments) if optRun in gGlobalOptions: if gCmd == cmdCompileToJS: var ex: string diff --git a/compiler/service.nim b/compiler/service.nim index 2b861e1c76..eab9952764 100644 --- a/compiler/service.nim +++ b/compiler/service.nim @@ -59,7 +59,7 @@ proc processCmdLine*(pass: TCmdLinePass, cmd: string) = inc argsCount if pass == passCmd2: - if optRun notin gGlobalOptions and arguments != "": + if optRun notin gGlobalOptions and arguments != "" and options.command != "run": rawMessage(errArgsNeedRunOption, []) proc serve*(action: proc (){.nimcall.}) = diff --git a/compiler/tccgen.nim b/compiler/tccgen.nim index 9ed6db8a18..a571d416ef 100644 --- a/compiler/tccgen.nim +++ b/compiler/tccgen.nim @@ -68,11 +68,9 @@ proc compileCCode*(ccode: string) = setupEnvironment() discard compileString(gTinyC, ccode) -proc run*() = - var a: array[0..1, cstring] - a[0] = "" - a[1] = "" - var err = tinyc.run(gTinyC, 0'i32, cast[cstringArray](addr(a))) != 0'i32 +proc run*(args: string) = + var s = @[cstring(gProjectName)] & map(split(args), proc(x: string): cstring = cstring(x)) + var err = tinyc.run(gTinyC, cint(len(s)), cast[cstringArray](addr(s[0]))) != 0'i32 closeCCState(gTinyC) if err: rawMessage(errExecutionOfProgramFailed, "") From 69949c07b72ceacc18f2cb6ba66c580b006484dc Mon Sep 17 00:00:00 2001 From: Grzegorz Adam Hankiewicz Date: Mon, 28 Jul 2014 23:22:39 +0200 Subject: [PATCH 074/234] Escapes properly code blocks without highlite support. --- lib/packages/docutils/rstgen.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/packages/docutils/rstgen.nim b/lib/packages/docutils/rstgen.nim index fdbca4ca84..e9bae69b55 100644 --- a/lib/packages/docutils/rstgen.nim +++ b/lib/packages/docutils/rstgen.nim @@ -775,7 +775,7 @@ proc renderCodeBlock(d: PDoc, n: PRstNode, result: var string) = dispA(d.target, result, "
", "\\begin{rstpre}\n", [])
   if lang == langNone:
     d.msgHandler(d.filename, 1, 0, mwUnsupportedLanguage, langstr)
-    result.add(m.text)
+    for letter in m.text: escChar(d.target, result, letter)
   else:
     var g: TGeneralTokenizer
     initGeneralTokenizer(g, m.text)

From 1274953507deb1c1210a1e0f152950d5ffe5ad45 Mon Sep 17 00:00:00 2001
From: def 
Date: Tue, 29 Jul 2014 02:16:57 +0200
Subject: [PATCH 075/234] normalize "run" command

---
 compiler/service.nim | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/compiler/service.nim b/compiler/service.nim
index eab9952764..22f5c6e333 100644
--- a/compiler/service.nim
+++ b/compiler/service.nim
@@ -59,7 +59,7 @@ proc processCmdLine*(pass: TCmdLinePass, cmd: string) =
       inc argsCount
           
   if pass == passCmd2:
-    if optRun notin gGlobalOptions and arguments != "" and options.command != "run":
+    if optRun notin gGlobalOptions and arguments != "" and options.command.normalize != "run":
       rawMessage(errArgsNeedRunOption, [])
 
 proc serve*(action: proc (){.nimcall.}) =

From 06bbd6e7d720c05550d3ee9a71691a28a84a9e79 Mon Sep 17 00:00:00 2001
From: def 
Date: Tue, 29 Jul 2014 19:52:41 +0200
Subject: [PATCH 076/234] flush -> flushFile in doc

---
 lib/system.nim | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/system.nim b/lib/system.nim
index 753205777e..d77b4fdee4 100644
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -2031,7 +2031,7 @@ proc echo*[T](x: varargs[T, `$`]) {.magic: "Echo", tags: [FWriteIO], gcsafe.}
   ## Special built-in that takes a variable number of arguments. Each argument
   ## is converted to a string via ``$``, so it works for user-defined
   ## types that have an overloaded ``$`` operator.
-  ## It is roughly equivalent to ``writeln(stdout, x); flush(stdout)``, but
+  ## It is roughly equivalent to ``writeln(stdout, x); flushFile(stdout)``, but
   ## available for the JavaScript target too.
   ##
   ## Unlike other IO operations this is guaranteed to be thread-safe as

From 779f2b37aa5d99f07747a6c2dac9c56633a0f431 Mon Sep 17 00:00:00 2001
From: Dominik Picheta 
Date: Tue, 29 Jul 2014 21:29:39 +0100
Subject: [PATCH 077/234] Fixes typeinfo after PR #1408 broke it.

---
 lib/core/typeinfo.nim | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/lib/core/typeinfo.nim b/lib/core/typeinfo.nim
index 93b90e120a..57e11664b5 100644
--- a/lib/core/typeinfo.nim
+++ b/lib/core/typeinfo.nim
@@ -454,11 +454,11 @@ proc getBiggestUint*(x: TAny): uint64 =
   ## represent an unsigned integer.
   var t = skipRange(x.rawtype)
   case t.kind
-  of akUInt: result = uint64(cast[ptr uint](x.value)[])
-  of akUInt8: result = uint64(cast[ptr uint8](x.value)[])
-  of akUInt16: result = uint64(cast[ptr uint16](x.value)[])
-  of akUInt32: result = uint64(cast[ptr uint32](x.value)[])
-  of akUInt64: result = uint64(cast[ptr uint64](x.value)[])
+  of tyUInt: result = uint64(cast[ptr uint](x.value)[])
+  of tyUInt8: result = uint64(cast[ptr uint8](x.value)[])
+  of tyUInt16: result = uint64(cast[ptr uint16](x.value)[])
+  of tyUInt32: result = uint64(cast[ptr uint32](x.value)[])
+  of tyUInt64: result = uint64(cast[ptr uint64](x.value)[])
   else: assert false
 
 proc setBiggestUint*(x: TAny; y: uint64) =
@@ -466,11 +466,11 @@ proc setBiggestUint*(x: TAny; y: uint64) =
   ## unsigned integer.
   var t = skipRange(x.rawtype)
   case t.kind:
-  of akUInt: result = cast[ptr uint](x.value)[] = uint(y)
-  of akUInt8: result = cast[ptr uint8](x.value)[] = uint8(y)
-  of akUInt16: result = cast[ptr uint16](x.value)[] = uint16(y)
-  of akUInt32: result = cast[ptr uint32](x.value)[] = uint32(y)
-  of akUInt64: result = cast[ptr uint64](x.value)[] = uint64(y)
+  of tyUInt: cast[ptr uint](x.value)[] = uint(y)
+  of tyUInt8: cast[ptr uint8](x.value)[] = uint8(y)
+  of tyUInt16: cast[ptr uint16](x.value)[] = uint16(y)
+  of tyUInt32: cast[ptr uint32](x.value)[] = uint32(y)
+  of tyUInt64: cast[ptr uint64](x.value)[] = uint64(y)
   else: assert false
 
 proc getChar*(x: TAny): char =

From 1b6abccba2c220ba153e29b8a6ae4ad3038a00c3 Mon Sep 17 00:00:00 2001
From: Clay Sweetser 
Date: Tue, 29 Jul 2014 21:13:21 -0400
Subject: [PATCH 078/234] Fix #813

Also add a notice that the linked list stuff in the compiler should be (one day) removed.
---
 compiler/commands.nim | 12 +++++++++---
 compiler/lists.nim    |  8 +++++---
 2 files changed, 14 insertions(+), 6 deletions(-)

diff --git a/compiler/commands.nim b/compiler/commands.nim
index 38c8dd2949..6edbbd61a2 100644
--- a/compiler/commands.nim
+++ b/compiler/commands.nim
@@ -290,9 +290,15 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) =
     options.gNoBabelPath = true
   of "excludepath":
     expectArg(switch, arg, pass, info)
-    let path = processPath(arg)
-    lists.excludeStr(options.searchPaths, path)
-    lists.excludeStr(options.lazyPaths, path)
+    let
+      path = processPath(arg)
+      strippedPath = removeTrailingDirSep(path)
+    echo repr(options.searchPaths)
+    lists.excludePath(options.searchPaths, path)
+    lists.excludePath(options.lazyPaths, path)
+    lists.excludePath(options.searchPaths, strippedPath)
+    lists.excludePath(options.lazyPaths, strippedPath)
+    echo repr(options.searchPaths)
   of "nimcache":
     expectArg(switch, arg, pass, info)
     options.nimcacheDir = processPath(arg)
diff --git a/compiler/lists.nim b/compiler/lists.nim
index dd4f5d6be5..efffe60fe3 100644
--- a/compiler/lists.nim
+++ b/compiler/lists.nim
@@ -8,7 +8,8 @@
 #
 
 # This module implements a generic doubled linked list.
-
+# TODO Remove this and replace it with something sensible
+import os
 type 
   PListEntry* = ref TListEntry
   TListEntry* = object of TObject
@@ -103,11 +104,12 @@ proc bringToFront*(list: var TLinkedList, entry: PListEntry) =
     entry.next = list.head
     list.head = entry
 
-proc excludeStr*(list: var TLinkedList, data: string) =
+proc excludePath*(list: var TLinkedList, data: string) =
   var it = list.head
   while it != nil:
     let nxt = it.next
-    if PStrEntry(it).data == data: remove(list, it)
+    if cmpPaths(PStrEntry(it).data, data) == 0:
+      remove(list, it)
     it = nxt
 
 proc find*(list: TLinkedList, fn: TCompareProc, closure: pointer): PListEntry = 

From 6a09fc358e5e799fdf5c0f79774d475d2fb02e6f Mon Sep 17 00:00:00 2001
From: Clay Sweetser 
Date: Tue, 29 Jul 2014 21:23:18 -0400
Subject: [PATCH 079/234] Clean up a bit.

---
 compiler/commands.nim | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/compiler/commands.nim b/compiler/commands.nim
index 6edbbd61a2..ee2f2a7f7b 100644
--- a/compiler/commands.nim
+++ b/compiler/commands.nim
@@ -290,14 +290,14 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) =
     options.gNoBabelPath = true
   of "excludepath":
     expectArg(switch, arg, pass, info)
-    let
-      path = processPath(arg)
-      strippedPath = removeTrailingDirSep(path)
+    let path = processPath(arg)
     echo repr(options.searchPaths)
     lists.excludePath(options.searchPaths, path)
     lists.excludePath(options.lazyPaths, path)
-    lists.excludePath(options.searchPaths, strippedPath)
-    lists.excludePath(options.lazyPaths, strippedPath)
+    if (len(path) > 0) and (path[len(path) - 1] == DirSep)::
+      let strippedPath = removeTrailingDirSep(path)
+      lists.excludePath(options.searchPaths, strippedPath)
+      lists.excludePath(options.lazyPaths, strippedPath)
     echo repr(options.searchPaths)
   of "nimcache":
     expectArg(switch, arg, pass, info)

From 9b4b4bcbc5b6464da31b75ab6bf529066bf8315d Mon Sep 17 00:00:00 2001
From: Clay Sweetser 
Date: Tue, 29 Jul 2014 21:31:46 -0400
Subject: [PATCH 080/234] Clean up more

---
 compiler/commands.nim | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/compiler/commands.nim b/compiler/commands.nim
index ee2f2a7f7b..4fec420f77 100644
--- a/compiler/commands.nim
+++ b/compiler/commands.nim
@@ -294,8 +294,8 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) =
     echo repr(options.searchPaths)
     lists.excludePath(options.searchPaths, path)
     lists.excludePath(options.lazyPaths, path)
-    if (len(path) > 0) and (path[len(path) - 1] == DirSep)::
-      let strippedPath = removeTrailingDirSep(path)
+    if (len(path) > 0) and (path[len(path) - 1] == DirSep):
+      let strippedPath = path[0 .. (len(path) - 2)]
       lists.excludePath(options.searchPaths, strippedPath)
       lists.excludePath(options.lazyPaths, strippedPath)
     echo repr(options.searchPaths)

From 2c6406703c47467289c5a53387f6fd64a9f516ce Mon Sep 17 00:00:00 2001
From: def 
Date: Wed, 30 Jul 2014 23:23:02 +0200
Subject: [PATCH 081/234] Add some nil checks for xmldom (and clean up a bit)

---
 lib/pure/xmldom.nim | 419 +++++++++++++++++++++++---------------------
 1 file changed, 223 insertions(+), 196 deletions(-)

diff --git a/lib/pure/xmldom.nim b/lib/pure/xmldom.nim
index 47e94243eb..98e4104e43 100644
--- a/lib/pure/xmldom.nim
+++ b/lib/pure/xmldom.nim
@@ -45,7 +45,7 @@ const
   DocumentFragmentNode* = 11
 
   # Nodes which are childless - Not sure about AttributeNode
-  childlessObjects = {DocumentNode, AttributeNode, TextNode, 
+  childlessObjects = {DocumentNode, AttributeNode, TextNode,
     CDataSectionNode, ProcessingInstructionNode, CommentNode}
   # Illegal characters
   illegalChars = {'>', '<', '&', '"'}
@@ -69,21 +69,21 @@ type
     FOwnerDocument: PDocument # Read-Only
     FParentNode: PNode # Read-Only
     prefix*: string # Setting this should change some values... TODO!
-  
+
   PElement* = ref Element
   Element = object of Node
     FTagName: string # Read-only
-  
+
   PCharacterData* = ref CharacterData
   CharacterData = object of Node
     data*: string
-    
+
   PDocument* = ref Document
   Document = object of Node
     FImplementation: PDOMImplementation # Read-only
     FDocumentElement: PElement # Read-only
-    
-  PAttr* = ref Attr  
+
+  PAttr* = ref Attr
   Attr = object of Node
     FName: string # Read-only
     FSpecified: bool # Read-only
@@ -95,13 +95,13 @@ type
 
   PText* = ref Text
   Text = object of CharacterData
-  
+
   PComment* = ref comment
   Comment = object of CharacterData
-  
+
   PCDataSection* = ref CDataSection
   CDataSection = object of Text
-    
+
   PProcessingInstruction* = ref ProcessingInstruction
   ProcessingInstruction = object of Node
     data*: string
@@ -111,8 +111,8 @@ type
 proc getDOM*(): PDOMImplementation =
   ## Returns a DOMImplementation
   new(result)
-  result.Features = @[(name: "core", version: "2.0"), 
-                      (name: "core", version: "1.0"), 
+  result.Features = @[(name: "core", version: "2.0"),
+                      (name: "core", version: "1.0"),
                       (name: "XML", version: "2.0")]
 
 proc createDocument*(dom: PDOMImplementation, namespaceURI: string, qualifiedName: string): PDocument =
@@ -121,28 +121,28 @@ proc createDocument*(dom: PDOMImplementation, namespaceURI: string, qualifiedNam
   new(doc)
   doc.FNamespaceURI = namespaceURI
   doc.FImplementation = dom
-  
+
   var elTag: PElement
   new(elTag)
   elTag.FTagName = qualifiedName
   elTag.FNodeName = qualifiedName
   doc.FDocumentElement = elTag
   doc.FNodeType = DocumentNode
-  
+
   return doc
-  
+
 proc createDocument*(dom: PDOMImplementation, n: PElement): PDocument =
   ## Creates an XML Document object of the specified type with its document element.
-  
+
   # This procedure is not in the specification, it's provided for the parser.
   var doc: PDocument
   new(doc)
   doc.FDocumentElement = n
   doc.FImplementation = dom
   doc.FNodeType = DocumentNode
-  
+
   return doc
-  
+
 proc hasFeature*(dom: PDOMImplementation, feature: string, version: string = ""): bool =
   ## Returns ``true`` if this ``version`` of the DomImplementation implements ``feature``, otherwise ``false``
   for iName, iVersion in items(dom.Features):
@@ -157,58 +157,58 @@ proc hasFeature*(dom: PDOMImplementation, feature: string, version: string = "")
 
 # Document
 # Attributes
-  
+
 proc implementation*(doc: PDocument): PDOMImplementation =
   return doc.FImplementation
-  
-proc documentElement*(doc: PDocument): PElement = 
+
+proc documentElement*(doc: PDocument): PElement =
   return doc.FDocumentElement
 
 # Internal procedures
 proc findNodes(nl: PNode, name: string): seq[PNode] =
   # Made for getElementsByTagName
   var r: seq[PNode] = @[]
-  if isNil(nl.childNodes): return @[]
+  if nl.childNodes == nil: return @[]
   if nl.childNodes.len() == 0: return @[]
 
   for i in items(nl.childNodes):
     if i.FNodeType == ElementNode:
       if i.FNodeName == name or name == "*":
         r.add(i)
-        
-      if not isNil(i.childNodes):
+
+      if i.childNodes != nil:
         if i.childNodes.len() != 0:
           r.add(findNodes(i, name))
-    
+
   return r
-  
+
 proc findNodesNS(nl: PNode, namespaceURI: string, localName: string): seq[PNode] =
   # Made for getElementsByTagNameNS
   var r: seq[PNode] = @[]
-  if isNil(nl.childNodes): return @[]
+  if nl.childNodes == nil: return @[]
   if nl.childNodes.len() == 0: return @[]
 
   for i in items(nl.childNodes):
     if i.FNodeType == ElementNode:
       if (i.FNamespaceURI == namespaceURI or namespaceURI == "*") and (i.FLocalName == localName or localName == "*"):
         r.add(i)
-        
-      if not isNil(i.childNodes):
+
+      if i.childNodes != nil:
         if i.childNodes.len() != 0:
           r.add(findNodesNS(i, namespaceURI, localName))
-    
+
   return r
-    
+
 
 #Procedures
 proc createAttribute*(doc: PDocument, name: string): PAttr =
   ## Creates an Attr of the given name. Note that the Attr instance can then be set on an Element using the setAttributeNode method.
-  ## To create an attribute with a qualified name and namespace URI, use the createAttributeNS method. 
-  
+  ## To create an attribute with a qualified name and namespace URI, use the createAttributeNS method.
+
   # Check if name contains illegal characters
   if illegalChars in name:
     raise newException(EInvalidCharacterErr, "Invalid character")
-  
+
   var AttrNode: PAttr
   new(AttrNode)
   AttrNode.FName = name
@@ -222,7 +222,7 @@ proc createAttribute*(doc: PDocument, name: string): PAttr =
 
 proc createAttributeNS*(doc: PDocument, namespaceURI: string, qualifiedName: string): PAttr =
   ## Creates an attribute of the given qualified name and namespace URI
-  
+
   # Check if name contains illegal characters
   if illegalChars in namespaceURI or illegalChars in qualifiedName:
     raise newException(EInvalidCharacterErr, "Invalid character")
@@ -231,12 +231,12 @@ proc createAttributeNS*(doc: PDocument, namespaceURI: string, qualifiedName: str
     if namespaceURI == nil:
       raise newException(ENamespaceErr, "When qualifiedName contains a prefix namespaceURI cannot be nil")
     elif qualifiedName.split(':')[0].toLower() == "xml" and namespaceURI != "http://www.w3.org/XML/1998/namespace":
-      raise newException(ENamespaceErr, 
+      raise newException(ENamespaceErr,
         "When the namespace prefix is \"xml\" namespaceURI has to be \"http://www.w3.org/XML/1998/namespace\"")
     elif qualifiedName.split(':')[1].toLower() == "xmlns" and namespaceURI != "http://www.w3.org/2000/xmlns/":
-      raise newException(ENamespaceErr, 
+      raise newException(ENamespaceErr,
         "When the namespace prefix is \"xmlns\" namespaceURI has to be \"http://www.w3.org/2000/xmlns/\"")
-  
+
   var AttrNode: PAttr
   new(AttrNode)
   AttrNode.FName = qualifiedName
@@ -250,7 +250,7 @@ proc createAttributeNS*(doc: PDocument, namespaceURI: string, qualifiedName: str
     AttrNode.prefix = nil
     AttrNode.FLocalName = qualifiedName
   AttrNode.value = ""
-  
+
   AttrNode.FNodeType = AttributeNode
   return AttrNode
 
@@ -265,12 +265,12 @@ proc createCDATASection*(doc: PDocument, data: string): PCDATASection =
   return CData
 
 proc createComment*(doc: PDocument, data: string): PComment =
-  ## Creates a Comment node given the specified string. 
+  ## Creates a Comment node given the specified string.
   var Comm: PComment
   new(Comm)
   Comm.data = data
   Comm.nodeValue = data
-  
+
   Comm.FNodeType = CommentNode
   return Comm
 
@@ -282,11 +282,11 @@ proc createDocumentFragment*(doc: PDocument): PDocumentFragment =
 
 proc createElement*(doc: PDocument, tagName: string): PElement =
   ## Creates an element of the type specified.
-  
+
   # Check if name contains illegal characters
   if illegalChars in tagName:
     raise newException(EInvalidCharacterErr, "Invalid character")
-    
+
   var elNode: PElement
   new(elNode)
   elNode.FTagName = tagName
@@ -296,9 +296,9 @@ proc createElement*(doc: PDocument, tagName: string): PElement =
   elNode.FNamespaceURI = nil
   elNode.childNodes = @[]
   elNode.attributes = @[]
-  
+
   elNode.FNodeType = ElementNode
-  
+
   return elNode
 
 proc createElementNS*(doc: PDocument, namespaceURI: string, qualifiedName: string): PElement =
@@ -307,13 +307,13 @@ proc createElementNS*(doc: PDocument, namespaceURI: string, qualifiedName: strin
     if namespaceURI == nil:
       raise newException(ENamespaceErr, "When qualifiedName contains a prefix namespaceURI cannot be nil")
     elif qualifiedName.split(':')[0].toLower() == "xml" and namespaceURI != "http://www.w3.org/XML/1998/namespace":
-      raise newException(ENamespaceErr, 
+      raise newException(ENamespaceErr,
         "When the namespace prefix is \"xml\" namespaceURI has to be \"http://www.w3.org/XML/1998/namespace\"")
-        
+
   # Check if name contains illegal characters
   if illegalChars in namespaceURI or illegalChars in qualifiedName:
     raise newException(EInvalidCharacterErr, "Invalid character")
-    
+
   var elNode: PElement
   new(elNode)
   elNode.FTagName = qualifiedName
@@ -327,18 +327,18 @@ proc createElementNS*(doc: PDocument, namespaceURI: string, qualifiedName: strin
   elNode.FNamespaceURI = namespaceURI
   elNode.childNodes = @[]
   elNode.attributes = @[]
-  
+
   elNode.FNodeType = ElementNode
-  
+
   return elNode
 
-proc createProcessingInstruction*(doc: PDocument, target: string, data: string): PProcessingInstruction = 
-  ## Creates a ProcessingInstruction node given the specified name and data strings. 
-  
+proc createProcessingInstruction*(doc: PDocument, target: string, data: string): PProcessingInstruction =
+  ## Creates a ProcessingInstruction node given the specified name and data strings.
+
   #Check if name contains illegal characters
   if illegalChars in target:
     raise newException(EInvalidCharacterErr, "Invalid character")
-    
+
   var PI: PProcessingInstruction
   new(PI)
   PI.FTarget = target
@@ -347,13 +347,13 @@ proc createProcessingInstruction*(doc: PDocument, target: string, data: string):
   return PI
 
 proc createTextNode*(doc: PDocument, data: string): PText = #Propably TextNode
-  ## Creates a Text node given the specified string. 
+  ## Creates a Text node given the specified string.
   var txtNode: PText
   new(txtNode)
   txtNode.data = data
   txtNode.nodeValue = data
   txtNode.FNodeName = "#text"
-  
+
   txtNode.FNodeType = TextNode
   return txtNode
 
@@ -363,22 +363,22 @@ discard """proc getElementById*(doc: PDocument, elementId: string): PElement =
 
 proc getElementsByTagName*(doc: PDocument, tagName: string): seq[PNode] =
   ## Returns a NodeList of all the Elements with a given tag name in
-  ## the order in which they are encountered in a preorder traversal of the Document tree. 
+  ## the order in which they are encountered in a preorder traversal of the Document tree.
   var result: seq[PNode] = @[]
   if doc.FDocumentElement.FNodeName == tagName or tagName == "*":
     result.add(doc.FDocumentElement)
-  
+
   result.add(doc.FDocumentElement.findNodes(tagName))
   return result
-  
+
 proc getElementsByTagNameNS*(doc: PDocument, namespaceURI: string, localName: string): seq[PNode] =
   ## Returns a NodeList of all the Elements with a given localName and namespaceURI
-  ## in the order in which they are encountered in a preorder traversal of the Document tree. 
+  ## in the order in which they are encountered in a preorder traversal of the Document tree.
   var result: seq[PNode] = @[]
   if doc.FDocumentElement.FLocalName == localName or localName == "*":
     if doc.FDocumentElement.FNamespaceURI == namespaceURI or namespaceURI == "*":
       result.add(doc.FDocumentElement)
-      
+
   result.add(doc.FDocumentElement.findNodesNS(namespaceURI, localName))
   return result
 
@@ -406,7 +406,7 @@ proc importNode*(doc: PDocument, importedNode: PNode, deep: bool): PNode =
     if deep:
       for i in low(tmp.len())..high(tmp.len()):
         n.childNodes.add(importNode(doc, tmp[i], deep))
-        
+
     return n
   of ElementNode:
     var n: PNode
@@ -414,7 +414,7 @@ proc importNode*(doc: PDocument, importedNode: PNode, deep: bool): PNode =
     n = importedNode
     n.FOwnerDocument = doc
     n.FParentNode = nil
-    
+
     var tmpA: seq[PAttr] = n.attributes
     n.attributes = @[]
     # Import the Element node's attributes
@@ -426,7 +426,7 @@ proc importNode*(doc: PDocument, importedNode: PNode, deep: bool): PNode =
     if deep:
       for i in low(tmp.len())..high(tmp.len()):
         n.childNodes.add(importNode(doc, tmp[i], deep))
-        
+
     return n
   of ProcessingInstructionNode, TextNode, CDataSectionNode, CommentNode:
     var n: PNode
@@ -437,27 +437,27 @@ proc importNode*(doc: PDocument, importedNode: PNode, deep: bool): PNode =
     return n
   else:
     raise newException(ENotSupportedErr, "The type of node being imported is not supported")
-  
+
 
 # Node
 # Attributes
-  
+
 proc firstChild*(n: PNode): PNode =
   ## Returns this node's first child
 
-  if n.childNodes.len() > 0:
+  if n.childNodes != nil and n.childNodes.len() > 0:
     return n.childNodes[0]
   else:
     return nil
-  
+
 proc lastChild*(n: PNode): PNode =
   ## Returns this node's last child
 
-  if n.childNodes.len() > 0:
+  if n.childNodes != nil and n.childNodes.len() > 0:
     return n.childNodes[n.childNodes.len() - 1]
   else:
     return nil
-  
+
 proc localName*(n: PNode): string =
   ## Returns this nodes local name
 
@@ -465,15 +465,17 @@ proc localName*(n: PNode): string =
 
 proc namespaceURI*(n: PNode): string =
   ## Returns this nodes namespace URI
-  
+
   return n.FNamespaceURI
-  
-proc `namespaceURI=`*(n: PNode, value: string) = 
+
+proc `namespaceURI=`*(n: PNode, value: string) =
   n.FNamespaceURI = value
 
 proc nextSibling*(n: PNode): PNode =
   ## Returns the next sibling of this node
 
+  if n.FParentNode == nil or n.FParentNode.childNodes == nil:
+    return nil
   var nLow: int = low(n.FParentNode.childNodes)
   var nHigh: int = high(n.FParentNode.childNodes)
   for i in nLow..nHigh:
@@ -500,17 +502,19 @@ proc parentNode*(n: PNode): PNode =
   ## Returns the parent node of this node
 
   return n.FParentNode
-  
+
 proc previousSibling*(n: PNode): PNode =
   ## Returns the previous sibling of this node
 
+  if n.FParentNode == nil or n.FParentNode.childNodes == nil:
+    return nil
   var nLow: int = low(n.FParentNode.childNodes)
   var nHigh: int = high(n.FParentNode.childNodes)
   for i in nLow..nHigh:
     if n.FParentNode.childNodes[i] == n:
       return n.FParentNode.childNodes[i - 1]
   return nil
-  
+
 proc `prefix=`*(n: PNode, value: string) =
   ## Modifies the prefix of this node
 
@@ -522,10 +526,10 @@ proc `prefix=`*(n: PNode, value: string) =
   if n.FNamespaceURI == nil:
     raise newException(ENamespaceErr, "namespaceURI cannot be nil")
   elif value.toLower() == "xml" and n.FNamespaceURI != "http://www.w3.org/XML/1998/namespace":
-    raise newException(ENamespaceErr, 
+    raise newException(ENamespaceErr,
       "When the namespace prefix is \"xml\" namespaceURI has to be \"http://www.w3.org/XML/1998/namespace\"")
   elif value.toLower() == "xmlns" and n.FNamespaceURI != "http://www.w3.org/2000/xmlns/":
-    raise newException(ENamespaceErr, 
+    raise newException(ENamespaceErr,
       "When the namespace prefix is \"xmlns\" namespaceURI has to be \"http://www.w3.org/2000/xmlns/\"")
   elif value.toLower() == "xmlns" and n.FNodeType == AttributeNode:
     raise newException(ENamespaceErr, "An AttributeNode cannot have a prefix of \"xmlns\"")
@@ -543,33 +547,33 @@ proc `prefix=`*(n: PNode, value: string) =
 proc appendChild*(n: PNode, newChild: PNode) =
   ## Adds the node newChild to the end of the list of children of this node.
   ## If the newChild is already in the tree, it is first removed.
-  
+
   # Check if n contains newChild
-  if not IsNil(n.childNodes):
+  if n.childNodes != nil:
     for i in low(n.childNodes)..high(n.childNodes):
       if n.childNodes[i] == newChild:
         raise newException(EHierarchyRequestErr, "The node to append is already in this nodes children.")
-  
+
   # Check if newChild is from this nodes document
   if n.FOwnerDocument != newChild.FOwnerDocument:
     raise newException(EWrongDocumentErr, "This node belongs to a different document, use importNode.")
-  
+
   if n == newChild:
     raise newException(EHierarchyRequestErr, "You can't add a node into itself")
-  
+
   if n.nodeType in childlessObjects:
     raise newException(ENoModificationAllowedErr, "Cannot append children to a childless node")
-  
-  if isNil(n.childNodes): n.childNodes = @[]
-    
+
+  if n.childNodes == nil: n.childNodes = @[]
+
   newChild.FParentNode = n
   for i in low(n.childNodes)..high(n.childNodes):
     if n.childNodes[i] == newChild:
       n.childNodes[i] = newChild
-    
+
   n.childNodes.add(newChild)
 
-proc cloneNode*(n: PNode, deep: bool): PNode = 
+proc cloneNode*(n: PNode, deep: bool): PNode =
   ## Returns a duplicate of this node, if ``deep`` is `true`, Element node's children are copied
   case n.FNodeType
   of AttributeNode:
@@ -586,7 +590,7 @@ proc cloneNode*(n: PNode, deep: bool): PNode =
     # Import the childNodes
     var tmp: seq[PNode] = n.childNodes
     n.childNodes = @[]
-    if deep:
+    if deep and tmp != nil:
       for i in low(tmp.len())..high(tmp.len()):
         n.childNodes.add(cloneNode(tmp[i], deep))
     return newNode
@@ -597,29 +601,34 @@ proc cloneNode*(n: PNode, deep: bool): PNode =
     return newNode
 
 proc hasAttributes*(n: PNode): bool =
-  ## Returns whether this node (if it is an element) has any attributes. 
-  return n.attributes.len() > 0
+  ## Returns whether this node (if it is an element) has any attributes.
+  return n.attributes != nil and n.attributes.len() > 0
 
-proc hasChildNodes*(n: PNode): bool = 
+proc hasChildNodes*(n: PNode): bool =
   ## Returns whether this node has any children.
-  return n.childNodes.len() > 0
+  return n.childNodes != nil and n.childNodes.len() > 0
 
 proc insertBefore*(n: PNode, newChild: PNode, refChild: PNode): PNode =
   ## Inserts the node ``newChild`` before the existing child node ``refChild``.
   ## If ``refChild`` is nil, insert ``newChild`` at the end of the list of children.
-  
+
   # Check if newChild is from this nodes document
   if n.FOwnerDocument != newChild.FOwnerDocument:
     raise newException(EWrongDocumentErr, "This node belongs to a different document, use importNode.")
-    
+
+  if n.childNodes == nil:
+    n.ChildNodes = @[]
+
   for i in low(n.childNodes)..high(n.childNodes):
     if n.childNodes[i] == refChild:
       n.childNodes.insert(newChild, i - 1)
-    return
+      return
+
+  n.ChildNodes.add(newChild)
 
 proc isSupported*(n: PNode, feature: string, version: string): bool =
-  ## Tests whether the DOM implementation implements a specific 
-  ## feature and that feature is supported by this node. 
+  ## Tests whether the DOM implementation implements a specific
+  ## feature and that feature is supported by this node.
   return n.FOwnerDocument.FImplementation.hasFeature(feature, version)
 
 proc isEmpty(s: string): bool =
@@ -635,17 +644,17 @@ proc normalize*(n: PNode) =
   ## Merges all seperated TextNodes together, and removes any empty TextNodes
   var curTextNode: PNode = nil
   var i: int = 0
-  
+
   var newChildNodes: seq[PNode] = @[]
   while True:
-    if i >= n.childNodes.len:
+    if n.childNodes == nil or i >= n.childNodes.len:
       break
     if n.childNodes[i].nodeType == TextNode:
-      
+
       #If the TextNode is empty, remove it
       if PText(n.childNodes[i]).data.isEmpty():
         inc(i)
-      
+
       if curTextNode == nil:
         curTextNode = n.childNodes[i]
       else:
@@ -656,35 +665,37 @@ proc normalize*(n: PNode) =
       newChildNodes.add(curTextNode)
       newChildNodes.add(n.childNodes[i])
       curTextNode = nil
-    
+
     inc(i)
   n.childNodes = newChildNodes
 
 proc removeChild*(n: PNode, oldChild: PNode): PNode =
   ## Removes the child node indicated by ``oldChild`` from the list of children, and returns it.
-  for i in low(n.childNodes)..high(n.childNodes):
-    if n.childNodes[i] == oldChild:
-      result = n.childNodes[i]
-      n.childNodes.delete(i)
-      return result
-      
+  if n.childNodes != nil:
+    for i in low(n.childNodes)..high(n.childNodes):
+      if n.childNodes[i] == oldChild:
+        result = n.childNodes[i]
+        n.childNodes.delete(i)
+        return result
+
   raise newException(ENotFoundErr, "Node not found")
-    
+
 proc replaceChild*(n: PNode, newChild: PNode, oldChild: PNode): PNode =
   ## Replaces the child node ``oldChild`` with ``newChild`` in the list of children, and returns the ``oldChild`` node.
-  
+
   # Check if newChild is from this nodes document
   if n.FOwnerDocument != newChild.FOwnerDocument:
     raise newException(EWrongDocumentErr, "This node belongs to a different document, use importNode.")
-  
-  for i in low(n.childNodes)..high(n.childNodes):
-    if n.childNodes[i] == oldChild:
-      result = n.childNodes[i]
-      n.childNodes[i] = newChild
-      return result
-  
+
+  if n.childNodes != nil:
+    for i in low(n.childNodes)..high(n.childNodes):
+      if n.childNodes[i] == oldChild:
+        result = n.childNodes[i]
+        n.childNodes[i] = newChild
+        return result
+
   raise newException(ENotFoundErr, "Node not found")
-  
+
 # NamedNodeMap
 
 proc getNamedItem*(NList: seq[PNode], name: string): PNode =
@@ -693,22 +704,22 @@ proc getNamedItem*(NList: seq[PNode], name: string): PNode =
     if i.nodeName() == name:
       return i
   return nil
-  
+
 proc getNamedItem*(NList: seq[PAttr], name: string): PAttr =
   ## Retrieves a node specified by ``name``. If this node cannot be found returns ``nil``
   for i in items(NList):
     if i.nodeName() == name:
       return i
   return nil
-      
+
 proc getNamedItemNS*(NList: seq[PNode], namespaceURI: string, localName: string): PNode =
   ## Retrieves a node specified by ``localName`` and ``namespaceURI``. If this node cannot be found returns ``nil``
   for i in items(NList):
     if i.namespaceURI() == namespaceURI and i.localName() == localName:
       return i
   return nil
-  
-proc getNamedItemNS*(NList: seq[PAttr], namespaceURI: string, localName: string): PAttr = 
+
+proc getNamedItemNS*(NList: seq[PAttr], namespaceURI: string, localName: string): PAttr =
   ## Retrieves a node specified by ``localName`` and ``namespaceURI``. If this node cannot be found returns ``nil``
   for i in items(NList):
     if i.NamespaceURI() == namespaceURI and i.LocalName() == localName:
@@ -716,7 +727,7 @@ proc getNamedItemNS*(NList: seq[PAttr], namespaceURI: string, localName: string)
   return nil
 
 proc item*(NList: seq[PNode], index: int): PNode =
-  ## Returns the ``index`` th item in the map. 
+  ## Returns the ``index`` th item in the map.
   ## If ``index`` is greater than or equal to the number of nodes in this map, this returns ``nil``.
   if index >= NList.len(): return nil
   else: return NList[index]
@@ -729,9 +740,9 @@ proc removeNamedItem*(NList: var seq[PNode], name: string): PNode =
       result = NList[i]
       NList.delete(i)
       return result
-  
+
   raise newException(ENotFoundErr, "Node not found")
-  
+
 proc removeNamedItemNS*(NList: var seq[PNode], namespaceURI: string, localName: string): PNode =
   ## Removes a node specified by local name and namespace URI
   for i in low(NList)..high(NList):
@@ -739,19 +750,19 @@ proc removeNamedItemNS*(NList: var seq[PNode], namespaceURI: string, localName:
       result = NList[i]
       NList.delete(i)
       return result
-  
+
   raise newException(ENotFoundErr, "Node not found")
 
 proc setNamedItem*(NList: var seq[PNode], arg: PNode): PNode =
   ## Adds ``arg`` as a ``Node`` to the ``NList``
   ## If a node with the same name is already present in this map, it is replaced by the new one.
-  if not isNil(NList):
+  if NList != nil:
     if NList.len() > 0:
       #Check if newChild is from this nodes document
       if NList[0].FOwnerDocument != arg.FOwnerDocument:
         raise newException(EWrongDocumentErr, "This node belongs to a different document, use importNode.")
   #Exceptions End
-  
+
   var item: PNode = NList.getNamedItem(arg.NodeName())
   if item == nil:
     NList.add(arg)
@@ -765,19 +776,19 @@ proc setNamedItem*(NList: var seq[PNode], arg: PNode): PNode =
         break
     NList[index] = arg
     return item # Return the replaced node
-    
+
 proc setNamedItem*(NList: var seq[PAttr], arg: PAttr): PAttr =
   ## Adds ``arg`` as a ``Node`` to the ``NList``
   ## If a node with the same name is already present in this map, it is replaced by the new one.
-  if not IsNil(NList):
+  if NList != nil:
     if NList.len() > 0:
       # Check if newChild is from this nodes document
       if NList[0].FOwnerDocument != arg.FOwnerDocument:
         raise newException(EWrongDocumentErr, "This node belongs to a different document, use importNode.")
-        
+
   if arg.FOwnerElement != nil:
     raise newException(EInuseAttributeErr, "This attribute is in use by another element, use cloneNode")
-        
+
   # Exceptions end
   var item: PAttr = NList.getNamedItem(arg.nodeName())
   if item == nil:
@@ -792,16 +803,16 @@ proc setNamedItem*(NList: var seq[PAttr], arg: PAttr): PAttr =
         break
     NList[index] = arg
     return item # Return the replaced node
-    
+
 proc setNamedItemNS*(NList: var seq[PNode], arg: PNode): PNode =
   ## Adds a node using its ``namespaceURI`` and ``localName``
-  if not IsNil(NList):
+  if NList != nil:
     if NList.len() > 0:
       # Check if newChild is from this nodes document
       if NList[0].FOwnerDocument != arg.FOwnerDocument:
         raise newException(EWrongDocumentErr, "This node belongs to a different document, use importNode.")
   #Exceptions end
-        
+
   var item: PNode = NList.getNamedItemNS(arg.namespaceURI(), arg.localName())
   if item == nil:
     NList.add(arg)
@@ -815,18 +826,18 @@ proc setNamedItemNS*(NList: var seq[PNode], arg: PNode): PNode =
         break
     NList[index] = arg
     return item # Return the replaced node
-    
+
 proc setNamedItemNS*(NList: var seq[PAttr], arg: PAttr): PAttr =
   ## Adds a node using its ``namespaceURI`` and ``localName``
-  if not isNil(NList):
+  if NList != nil:
     if NList.len() > 0:
       # Check if newChild is from this nodes document
       if NList[0].FOwnerDocument != arg.FOwnerDocument:
         raise newException(EWrongDocumentErr, "This node belongs to a different document, use importNode.")
-        
+
   if arg.FOwnerElement != nil:
     raise newException(EInuseAttributeErr, "This attribute is in use by another element, use cloneNode")
-        
+
   # Exceptions end
   var item: PAttr = NList.getNamedItemNS(arg.namespaceURI(), arg.localName())
   if item == nil:
@@ -841,8 +852,8 @@ proc setNamedItemNS*(NList: var seq[PAttr], arg: PAttr): PAttr =
         break
     NList[index] = arg
     return item # Return the replaced node
-    
-# CharacterData - Decided to implement this, 
+
+# CharacterData - Decided to implement this,
 # Didn't add the procedures, because you can just edit .data
 
 # Attr
@@ -851,13 +862,13 @@ proc name*(a: PAttr): string =
   ## Returns the name of the Attribute
 
   return a.FName
-  
+
 proc specified*(a: PAttr): bool =
   ## Specifies whether this attribute was specified in the original document
 
   return a.FSpecified
-  
-proc ownerElement*(a: PAttr): PElement = 
+
+proc ownerElement*(a: PAttr): PElement =
   ## Returns this Attributes owner element
 
   return a.FOwnerElement
@@ -873,6 +884,8 @@ proc tagName*(el: PElement): string =
 # Procedures
 proc getAttribute*(el: PElement, name: string): string =
   ## Retrieves an attribute value by ``name``
+  if el.attributes == nil:
+    return nil
   var attribute = el.attributes.getNamedItem(name)
   if attribute != nil:
     return attribute.value
@@ -881,19 +894,25 @@ proc getAttribute*(el: PElement, name: string): string =
 
 proc getAttributeNS*(el: PElement, namespaceURI: string, localName: string): string =
   ## Retrieves an attribute value by ``localName`` and ``namespaceURI``
+  if el.attributes == nil:
+    return nil
   var attribute = el.attributes.getNamedItemNS(namespaceURI, localName)
   if attribute != nil:
     return attribute.value
   else:
     return nil
-    
+
 proc getAttributeNode*(el: PElement, name: string): PAttr =
   ## Retrieves an attribute node by ``name``
   ## To retrieve an attribute node by qualified name and namespace URI, use the `getAttributeNodeNS` method
+  if el.attributes == nil:
+    return nil
   return el.attributes.getNamedItem(name)
 
 proc getAttributeNodeNS*(el: PElement, namespaceURI: string, localName: string): PAttr =
   ## Retrieves an `Attr` node by ``localName`` and ``namespaceURI``
+  if el.attributes == nil:
+    return nil
   return el.attributes.getNamedItemNS(namespaceURI, localName)
 
 proc getElementsByTagName*(el: PElement, name: string): seq[PNode] =
@@ -909,103 +928,110 @@ proc getElementsByTagNameNS*(el: PElement, namespaceURI: string, localName: stri
   result = el.findNodesNS(namespaceURI, localName)
 
 proc hasAttribute*(el: PElement, name: string): bool =
-  ## Returns ``true`` when an attribute with a given ``name`` is specified 
-  ## on this element , ``false`` otherwise. 
+  ## Returns ``true`` when an attribute with a given ``name`` is specified
+  ## on this element , ``false`` otherwise.
+  if el.attributes == nil:
+    return false
   return el.attributes.getNamedItem(name) != nil
 
 proc hasAttributeNS*(el: PElement, namespaceURI: string, localName: string): bool =
   ## Returns ``true`` when an attribute with a given ``localName`` and
-  ## ``namespaceURI`` is specified on this element , ``false`` otherwise 
+  ## ``namespaceURI`` is specified on this element , ``false`` otherwise
+  if el.attributes == nil:
+    return false
   return el.attributes.getNamedItemNS(namespaceURI, localName) != nil
 
 proc removeAttribute*(el: PElement, name: string) =
   ## Removes an attribute by ``name``
-  for i in low(el.attributes)..high(el.attributes):
-    if el.attributes[i].FName == name:
-      el.attributes.delete(i)
-      
+  if el.attributes != nil:
+    for i in low(el.attributes)..high(el.attributes):
+      if el.attributes[i].FName == name:
+        el.attributes.delete(i)
+
 proc removeAttributeNS*(el: PElement, namespaceURI: string, localName: string) =
   ## Removes an attribute by ``localName`` and ``namespaceURI``
-  for i in low(el.attributes)..high(el.attributes):
-    if el.attributes[i].FNamespaceURI == namespaceURI and 
-        el.attributes[i].FLocalName == localName:
-      el.attributes.delete(i)
-  
+  if el.attributes != nil:
+    for i in low(el.attributes)..high(el.attributes):
+      if el.attributes[i].FNamespaceURI == namespaceURI and
+          el.attributes[i].FLocalName == localName:
+        el.attributes.delete(i)
+
 proc removeAttributeNode*(el: PElement, oldAttr: PAttr): PAttr =
   ## Removes the specified attribute node
   ## If the attribute node cannot be found raises ``ENotFoundErr``
-  for i in low(el.attributes)..high(el.attributes):
-    if el.attributes[i] == oldAttr:
-      result = el.attributes[i]
-      el.attributes.delete(i)
-      return result
-  
+  if el.attributes != nil:
+    for i in low(el.attributes)..high(el.attributes):
+      if el.attributes[i] == oldAttr:
+        result = el.attributes[i]
+        el.attributes.delete(i)
+        return result
+
   raise newException(ENotFoundErr, "oldAttr is not a member of el's Attributes")
 
 proc setAttributeNode*(el: PElement, newAttr: PAttr): PAttr =
   ## Adds a new attribute node, if an attribute with the same `nodeName` is
   ## present, it is replaced by the new one and the replaced attribute is
   ## returned, otherwise ``nil`` is returned.
-  
+
   # Check if newAttr is from this nodes document
   if el.FOwnerDocument != newAttr.FOwnerDocument:
-    raise newException(EWrongDocumentErr, 
+    raise newException(EWrongDocumentErr,
       "This node belongs to a different document, use importNode.")
-        
+
   if newAttr.FOwnerElement != nil:
-    raise newException(EInuseAttributeErr, 
+    raise newException(EInuseAttributeErr,
       "This attribute is in use by another element, use cloneNode")
   # Exceptions end
-  
-  if isNil(el.attributes): el.attributes = @[]
+
+  if el.attributes == nil: el.attributes = @[]
   return el.attributes.setNamedItem(newAttr)
-  
+
 proc setAttributeNodeNS*(el: PElement, newAttr: PAttr): PAttr =
-  ## Adds a new attribute node, if an attribute with the localName and 
+  ## Adds a new attribute node, if an attribute with the localName and
   ## namespaceURI of ``newAttr`` is present, it is replaced by the new one
   ## and the replaced attribute is returned, otherwise ``nil`` is returned.
-  
+
   # Check if newAttr is from this nodes document
   if el.FOwnerDocument != newAttr.FOwnerDocument:
-    raise newException(EWrongDocumentErr, 
+    raise newException(EWrongDocumentErr,
       "This node belongs to a different document, use importNode.")
-        
+
   if newAttr.FOwnerElement != nil:
-    raise newException(EInuseAttributeErr, 
+    raise newException(EInuseAttributeErr,
       "This attribute is in use by another element, use cloneNode")
   # Exceptions end
-  
-  if isNil(el.attributes): el.attributes = @[]
+
+  if el.attributes == nil: el.attributes = @[]
   return el.attributes.setNamedItemNS(newAttr)
 
 proc setAttribute*(el: PElement, name: string, value: string) =
   ## Adds a new attribute, as specified by ``name`` and ``value``
-  ## If an attribute with that name is already present in the element, its 
+  ## If an attribute with that name is already present in the element, its
   ## value is changed to be that of the value parameter
-  ## Raises the EInvalidCharacterErr if the specified ``name`` contains 
+  ## Raises the EInvalidCharacterErr if the specified ``name`` contains
   ## illegal characters
   var AttrNode = el.FOwnerDocument.createAttribute(name)
   # Check if name contains illegal characters
   if illegalChars in name:
     raise newException(EInvalidCharacterErr, "Invalid character")
-    
+
   discard el.setAttributeNode(AttrNode)
   # Set the info later, the setAttributeNode checks
   # if FOwnerElement is nil, and if it isn't it raises an exception
   AttrNode.FOwnerElement = el
   AttrNode.FSpecified = True
   AttrNode.value = value
-  
+
 proc setAttributeNS*(el: PElement, namespaceURI, localName, value: string) =
-  ## Adds a new attribute, as specified by ``namespaceURI``, ``localName`` 
+  ## Adds a new attribute, as specified by ``namespaceURI``, ``localName``
   ## and ``value``.
-  
+
   # Check if name contains illegal characters
   if illegalChars in namespaceURI or illegalChars in localName:
     raise newException(EInvalidCharacterErr, "Invalid character")
-    
+
   var AttrNode = el.FOwnerDocument.createAttributeNS(namespaceURI, localName)
-    
+
   discard el.setAttributeNodeNS(AttrNode)
   # Set the info later, the setAttributeNode checks
   # if FOwnerElement is nil, and if it isn't it raises an exception
@@ -1013,19 +1039,19 @@ proc setAttributeNS*(el: PElement, namespaceURI, localName, value: string) =
   AttrNode.FSpecified = True
   AttrNode.value = value
 
-# Text  
+# Text
 proc splitData*(TextNode: PText, offset: int): PText =
-  ## Breaks this node into two nodes at the specified offset, 
+  ## Breaks this node into two nodes at the specified offset,
   ## keeping both in the tree as siblings.
-  
+
   if offset > TextNode.data.len():
     raise newException(EIndexSizeErr, "Index out of bounds")
-  
+
   var left: string = TextNode.data.substr(0, offset)
   TextNode.data = left
   var right: string = TextNode.data.substr(offset, TextNode.data.len())
-  
-  if TextNode.FParentNode != nil:
+
+  if TextNode.FParentNode != nil and TextNode.FParentNode.childNodes != nil:
     for i in low(TextNode.FParentNode.childNodes)..high(TextNode.FParentNode.childNodes):
       if TextNode.FParentNode.childNodes[i] == TextNode:
         var newNode: PText = TextNode.FOwnerDocument.createTextNode(right)
@@ -1042,10 +1068,10 @@ proc target*(PI: PProcessingInstruction): string =
 
   return PI.FTarget
 
-    
+
 # --Other stuff--
 # Writer
-proc addEscaped(s: string): string = 
+proc addEscaped(s: string): string =
   result = ""
   for c in items(s):
     case c
@@ -1057,10 +1083,11 @@ proc addEscaped(s: string): string =
 
 proc nodeToXml(n: PNode, indent: int = 0): string =
   result = repeatChar(indent, ' ') & "<" & n.nodeName
-  for i in items(n.Attributes):
-    result.add(" " & i.name & "=\"" & addEscaped(i.value) & "\"")
-  
-  if n.childNodes.len() == 0:
+  if n.attributes != nil:
+    for i in items(n.attributes):
+      result.add(" " & i.name & "=\"" & addEscaped(i.value) & "\"")
+
+  if n.childNodes == nil or n.childNodes.len() == 0:
     result.add("/>") # No idea why this doesn't need a \n :O
   else:
     # End the beginning of this tag

From 7b9e2881d8eab90007a83fce88c12dae5d5193f9 Mon Sep 17 00:00:00 2001
From: def 
Date: Thu, 31 Jul 2014 11:28:26 +0200
Subject: [PATCH 082/234] Add "struct" to POSIX flock

---
 lib/posix/posix.nim | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/posix/posix.nim b/lib/posix/posix.nim
index 8e66336c2e..a5ee05abbd 100644
--- a/lib/posix/posix.nim
+++ b/lib/posix/posix.nim
@@ -90,7 +90,7 @@ type
     d_ino*: Tino  ## File serial number.
     d_name*: array [0..255, char] ## Name of entry.
 
-  Tflock* {.importc: "flock", final, pure,
+  Tflock* {.importc: "struct flock", final, pure,
             header: "".} = object ## flock type
     l_type*: cshort   ## Type of lock; F_RDLCK, F_WRLCK, F_UNLCK.
     l_whence*: cshort ## Flag for starting offset.

From d47971b9caa928b954203633fad2ef31628bf35f Mon Sep 17 00:00:00 2001
From: Grzegorz Adam Hankiewicz 
Date: Thu, 31 Jul 2014 14:38:35 +0200
Subject: [PATCH 083/234] Corrects description of nimcache file naming. Refs
 #852.

---
 doc/backends.txt | 54 +++++++++++++++++++++++-------------------------
 1 file changed, 26 insertions(+), 28 deletions(-)

diff --git a/doc/backends.txt b/doc/backends.txt
index adcd741490..c2dbb0af66 100644
--- a/doc/backends.txt
+++ b/doc/backends.txt
@@ -334,42 +334,40 @@ Nimcache and C like targets
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 The C like backends will place their temporary ``.c``, ``.cpp`` or ``.m`` files
-in the ``nimcache`` directory. The name of this files follows this logic:
+in the ``nimcache`` directory. The naming of these files follows the pattern
+``babelPackageName_`` + ``nimrodSource``:
 
-* Filenames for your project will be renamed from ``.nim`` to have the
-  extension of your target backend (from now on ``.c`` for these examples), but
-  otherwise nothing else will change. This will quickly break if your project
-  consists of a main ``proj.nim`` file which includes a ``utils/proj.nim``
-  file: both ``proj.nim`` files will generate the same name ``proj.c`` output
-  in the ``nimcache`` directory overwriting themselves!
+* Filenames for modules imported from `Babel packages
+  `_ will end up with
+  ``babelPackageName_module.c``. For example, if you import the
+  ``argument_parser`` module from the same name Babel package you
+  will end up with a ``argument_parser_argument_parser.c`` file
+  under ``nimcache``.  The name of the Babel package comes from the
+  ``proj.babel`` file, the actual contents are not read by the
+  compiler.
+
+* Filenames for non babel packages (like your project) will be
+  renamed from ``.nim`` to have the extension of your target backend
+  (from now on ``.c`` for these examples), but otherwise nothing
+  else will change. This will quickly break if your project consists
+  of a main ``proj.nim`` file which includes a ``utils/proj.nim``
+  file: both ``proj.nim`` files will generate the same name ``proj.c``
+  output in the ``nimcache`` directory overwriting themselves!
 
 * Filenames for modules found in the standard library will be named
   ``stdlib_module.c``. Unless you are doing something special, you
   will end up with at least ``stdlib_system.c``, since the `system
   module `_ is always imported automatically. Same for
   the `hashes module `_ which will be named
-  ``stdlib_hashes.c``
+  ``stdlib_hashes.c``. The ``stdlib_`` prefix comes from the *fake*
+  ``lib/stdlib.babel`` file.
 
-* Filenames for modules not part of the standard library and found
-  through additional paths specified with the ``--path`` compiler
-  switch will use as prefix their parent directory. For example,
-  the `rstgen module `_ will generate ``docutils_rstgen.c``
-  because the `lib/packages/docutils directory
-  `_ is
-  not included in the standard library and you need to either write
-  ``import packages/docutils/rstgen`` or add
-  ``--path:"$lib/pkages/docutils`` to the compiler switches to be
-  able to use it.
-
-* Filenames for modules imported from `babel packages
-  `_ will end up with
-  ``babelPackageName_module.c``. For example, if you import the
-  ``argument_parser`` module from the same name babel package you will end up
-  with a ``argument_parser_argument_parser.c`` file under ``nimcache``.
-
-To find out about what paths are part of the default standard library, create a
-dummy ``hello.nim`` file and run ``nimrod dump hello.nim``. This will display
-the defined simbols and the list of paths for the standard library.
+To find the name of a Babel package the compiler searches for a ``*.babel``
+file in the parent directory hierarchy of whatever module you are compiling.
+Even if you are in a subdirectory of your project, a parent ``*.babel`` file
+will influence the naming of the nimcache name. This means that on Unix systems
+creating the file ``~/foo.babel`` will automatically prefix all nimcache files
+not part of another package with the string ``foo_``.
 
 
 Nimcache and the Javascript target

From 0dd46ee8451115d0485a76cfc3f80ce893310159 Mon Sep 17 00:00:00 2001
From: def 
Date: Fri, 1 Aug 2014 01:45:58 +0200
Subject: [PATCH 084/234] Set kind of literal nodes as resExpr

---
 compiler/jsgen.nim | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim
index 6687e2e8ec..8fa9838ee4 100644
--- a/compiler/jsgen.nim
+++ b/compiler/jsgen.nim
@@ -1532,6 +1532,7 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) =
     genSym(p, n, r)
   of nkCharLit..nkInt64Lit:
     r.res = toRope(n.intVal)
+    r.kind = resExpr
   of nkNilLit:
     if isEmptyType(n.typ):
       discard
@@ -1539,8 +1540,10 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) =
       r.typ = etyBaseIndex
       r.address = toRope"null" | toRope"nil"
       r.res = toRope"0"
+      r.kind = resExpr
     else:
       r.res = toRope"null" | toRope"nil"
+      r.kind = resExpr
   of nkStrLit..nkTripleStrLit:
     if skipTypes(n.typ, abstractVarRange).kind == tyString: 
       useMagic(p, "cstrToNimstr")
@@ -1556,6 +1559,7 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) =
       if f > 0.0: r.res = toRope"Infinity"
       else: r.res = toRope"-Infinity"
     else: r.res = toRope(f.toStrMaxPrecision)
+    r.kind = resExpr
   of nkCallKinds:
     if (n.sons[0].kind == nkSym) and (n.sons[0].sym.magic != mNone): 
       genMagic(p, n, r)

From f17de0b13ac0e683e3a100eb0c3ea5ff23ff7ce2 Mon Sep 17 00:00:00 2001
From: def 
Date: Fri, 1 Aug 2014 02:06:07 +0200
Subject: [PATCH 085/234] Fix typo in mHigh

---
 compiler/jsgen.nim | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim
index 6687e2e8ec..662ee837b6 100644
--- a/compiler/jsgen.nim
+++ b/compiler/jsgen.nim
@@ -1321,7 +1321,7 @@ proc genMagic(p: PProc, n: PNode, r: var TCompRes) =
   of mLengthSeq, mLengthOpenArray, mLengthArray:
     unaryExpr(p, n, r, "", "$1.length")
   of mHigh:
-    if skipTypes(n.sons[0].typ, abstractVar).kind == tyString:
+    if skipTypes(n.sons[1].typ, abstractVar).kind == tyString:
       unaryExpr(p, n, r, "", "($1.length-2)")
     else:
       unaryExpr(p, n, r, "", "($1.length-1)")

From dc756a76187aa94c9eca18d070a9710ac4193218 Mon Sep 17 00:00:00 2001
From: def 
Date: Fri, 1 Aug 2014 02:23:13 +0200
Subject: [PATCH 086/234] replace nil comparisons with calls to isNil

---
 lib/pure/xmldom.nim | 104 ++++++++++++++++++++++----------------------
 1 file changed, 52 insertions(+), 52 deletions(-)

diff --git a/lib/pure/xmldom.nim b/lib/pure/xmldom.nim
index 98e4104e43..d63b6c5dd3 100644
--- a/lib/pure/xmldom.nim
+++ b/lib/pure/xmldom.nim
@@ -168,7 +168,7 @@ proc documentElement*(doc: PDocument): PElement =
 proc findNodes(nl: PNode, name: string): seq[PNode] =
   # Made for getElementsByTagName
   var r: seq[PNode] = @[]
-  if nl.childNodes == nil: return @[]
+  if isNil(nl.childNodes): return @[]
   if nl.childNodes.len() == 0: return @[]
 
   for i in items(nl.childNodes):
@@ -176,7 +176,7 @@ proc findNodes(nl: PNode, name: string): seq[PNode] =
       if i.FNodeName == name or name == "*":
         r.add(i)
 
-      if i.childNodes != nil:
+      if not isNil(i.childNodes):
         if i.childNodes.len() != 0:
           r.add(findNodes(i, name))
 
@@ -185,7 +185,7 @@ proc findNodes(nl: PNode, name: string): seq[PNode] =
 proc findNodesNS(nl: PNode, namespaceURI: string, localName: string): seq[PNode] =
   # Made for getElementsByTagNameNS
   var r: seq[PNode] = @[]
-  if nl.childNodes == nil: return @[]
+  if isNil(nl.childNodes): return @[]
   if nl.childNodes.len() == 0: return @[]
 
   for i in items(nl.childNodes):
@@ -193,7 +193,7 @@ proc findNodesNS(nl: PNode, namespaceURI: string, localName: string): seq[PNode]
       if (i.FNamespaceURI == namespaceURI or namespaceURI == "*") and (i.FLocalName == localName or localName == "*"):
         r.add(i)
 
-      if i.childNodes != nil:
+      if not isNil(i.childNodes):
         if i.childNodes.len() != 0:
           r.add(findNodesNS(i, namespaceURI, localName))
 
@@ -228,7 +228,7 @@ proc createAttributeNS*(doc: PDocument, namespaceURI: string, qualifiedName: str
     raise newException(EInvalidCharacterErr, "Invalid character")
   # Exceptions
   if qualifiedName.contains(':'):
-    if namespaceURI == nil:
+    if isNil(namespaceURI):
       raise newException(ENamespaceErr, "When qualifiedName contains a prefix namespaceURI cannot be nil")
     elif qualifiedName.split(':')[0].toLower() == "xml" and namespaceURI != "http://www.w3.org/XML/1998/namespace":
       raise newException(ENamespaceErr,
@@ -304,7 +304,7 @@ proc createElement*(doc: PDocument, tagName: string): PElement =
 proc createElementNS*(doc: PDocument, namespaceURI: string, qualifiedName: string): PElement =
   ## Creates an element of the given qualified name and namespace URI.
   if qualifiedName.contains(':'):
-    if namespaceURI == nil:
+    if isNIl(namespaceURI):
       raise newException(ENamespaceErr, "When qualifiedName contains a prefix namespaceURI cannot be nil")
     elif qualifiedName.split(':')[0].toLower() == "xml" and namespaceURI != "http://www.w3.org/XML/1998/namespace":
       raise newException(ENamespaceErr,
@@ -445,7 +445,7 @@ proc importNode*(doc: PDocument, importedNode: PNode, deep: bool): PNode =
 proc firstChild*(n: PNode): PNode =
   ## Returns this node's first child
 
-  if n.childNodes != nil and n.childNodes.len() > 0:
+  if not isNil(n.childNodes) and n.childNodes.len() > 0:
     return n.childNodes[0]
   else:
     return nil
@@ -453,7 +453,7 @@ proc firstChild*(n: PNode): PNode =
 proc lastChild*(n: PNode): PNode =
   ## Returns this node's last child
 
-  if n.childNodes != nil and n.childNodes.len() > 0:
+  if not isNil(n.childNodes) and n.childNodes.len() > 0:
     return n.childNodes[n.childNodes.len() - 1]
   else:
     return nil
@@ -474,7 +474,7 @@ proc `namespaceURI=`*(n: PNode, value: string) =
 proc nextSibling*(n: PNode): PNode =
   ## Returns the next sibling of this node
 
-  if n.FParentNode == nil or n.FParentNode.childNodes == nil:
+  if isNil(n.FParentNode) or isNil(n.FParentNode.childNodes):
     return nil
   var nLow: int = low(n.FParentNode.childNodes)
   var nHigh: int = high(n.FParentNode.childNodes)
@@ -506,7 +506,7 @@ proc parentNode*(n: PNode): PNode =
 proc previousSibling*(n: PNode): PNode =
   ## Returns the previous sibling of this node
 
-  if n.FParentNode == nil or n.FParentNode.childNodes == nil:
+  if isNil(n.FParentNode) or isNil(n.FParentNode.childNodes):
     return nil
   var nLow: int = low(n.FParentNode.childNodes)
   var nHigh: int = high(n.FParentNode.childNodes)
@@ -523,7 +523,7 @@ proc `prefix=`*(n: PNode, value: string) =
   if illegalChars in value:
     raise newException(EInvalidCharacterErr, "Invalid character")
 
-  if n.FNamespaceURI == nil:
+  if isNil(n.FNamespaceURI):
     raise newException(ENamespaceErr, "namespaceURI cannot be nil")
   elif value.toLower() == "xml" and n.FNamespaceURI != "http://www.w3.org/XML/1998/namespace":
     raise newException(ENamespaceErr,
@@ -549,7 +549,7 @@ proc appendChild*(n: PNode, newChild: PNode) =
   ## If the newChild is already in the tree, it is first removed.
 
   # Check if n contains newChild
-  if n.childNodes != nil:
+  if not isNil(n.childNodes):
     for i in low(n.childNodes)..high(n.childNodes):
       if n.childNodes[i] == newChild:
         raise newException(EHierarchyRequestErr, "The node to append is already in this nodes children.")
@@ -564,7 +564,7 @@ proc appendChild*(n: PNode, newChild: PNode) =
   if n.nodeType in childlessObjects:
     raise newException(ENoModificationAllowedErr, "Cannot append children to a childless node")
 
-  if n.childNodes == nil: n.childNodes = @[]
+  if isNil(n.childNodes): n.childNodes = @[]
 
   newChild.FParentNode = n
   for i in low(n.childNodes)..high(n.childNodes):
@@ -590,7 +590,7 @@ proc cloneNode*(n: PNode, deep: bool): PNode =
     # Import the childNodes
     var tmp: seq[PNode] = n.childNodes
     n.childNodes = @[]
-    if deep and tmp != nil:
+    if deep and not isNil(tmp):
       for i in low(tmp.len())..high(tmp.len()):
         n.childNodes.add(cloneNode(tmp[i], deep))
     return newNode
@@ -602,11 +602,11 @@ proc cloneNode*(n: PNode, deep: bool): PNode =
 
 proc hasAttributes*(n: PNode): bool =
   ## Returns whether this node (if it is an element) has any attributes.
-  return n.attributes != nil and n.attributes.len() > 0
+  return not isNil(n.attributes) and n.attributes.len() > 0
 
 proc hasChildNodes*(n: PNode): bool =
   ## Returns whether this node has any children.
-  return n.childNodes != nil and n.childNodes.len() > 0
+  return not isNil(n.childNodes) and n.childNodes.len() > 0
 
 proc insertBefore*(n: PNode, newChild: PNode, refChild: PNode): PNode =
   ## Inserts the node ``newChild`` before the existing child node ``refChild``.
@@ -616,7 +616,7 @@ proc insertBefore*(n: PNode, newChild: PNode, refChild: PNode): PNode =
   if n.FOwnerDocument != newChild.FOwnerDocument:
     raise newException(EWrongDocumentErr, "This node belongs to a different document, use importNode.")
 
-  if n.childNodes == nil:
+  if isNil(n.childNodes):
     n.ChildNodes = @[]
 
   for i in low(n.childNodes)..high(n.childNodes):
@@ -633,7 +633,7 @@ proc isSupported*(n: PNode, feature: string, version: string): bool =
 
 proc isEmpty(s: string): bool =
 
-  if s == "" or s == nil:
+  if isNil(s) or s == "":
     return True
   for i in items(s):
     if i != ' ':
@@ -647,7 +647,7 @@ proc normalize*(n: PNode) =
 
   var newChildNodes: seq[PNode] = @[]
   while True:
-    if n.childNodes == nil or i >= n.childNodes.len:
+    if isNil(n.childNodes) or i >= n.childNodes.len:
       break
     if n.childNodes[i].nodeType == TextNode:
 
@@ -655,7 +655,7 @@ proc normalize*(n: PNode) =
       if PText(n.childNodes[i]).data.isEmpty():
         inc(i)
 
-      if curTextNode == nil:
+      if isNil(curTextNode):
         curTextNode = n.childNodes[i]
       else:
         PText(curTextNode).data.add(PText(n.childNodes[i]).data)
@@ -671,7 +671,7 @@ proc normalize*(n: PNode) =
 
 proc removeChild*(n: PNode, oldChild: PNode): PNode =
   ## Removes the child node indicated by ``oldChild`` from the list of children, and returns it.
-  if n.childNodes != nil:
+  if not isNil(n.childNodes):
     for i in low(n.childNodes)..high(n.childNodes):
       if n.childNodes[i] == oldChild:
         result = n.childNodes[i]
@@ -687,7 +687,7 @@ proc replaceChild*(n: PNode, newChild: PNode, oldChild: PNode): PNode =
   if n.FOwnerDocument != newChild.FOwnerDocument:
     raise newException(EWrongDocumentErr, "This node belongs to a different document, use importNode.")
 
-  if n.childNodes != nil:
+  if not isNil(n.childNodes):
     for i in low(n.childNodes)..high(n.childNodes):
       if n.childNodes[i] == oldChild:
         result = n.childNodes[i]
@@ -756,7 +756,7 @@ proc removeNamedItemNS*(NList: var seq[PNode], namespaceURI: string, localName:
 proc setNamedItem*(NList: var seq[PNode], arg: PNode): PNode =
   ## Adds ``arg`` as a ``Node`` to the ``NList``
   ## If a node with the same name is already present in this map, it is replaced by the new one.
-  if NList != nil:
+  if not isNil(NList):
     if NList.len() > 0:
       #Check if newChild is from this nodes document
       if NList[0].FOwnerDocument != arg.FOwnerDocument:
@@ -764,7 +764,7 @@ proc setNamedItem*(NList: var seq[PNode], arg: PNode): PNode =
   #Exceptions End
 
   var item: PNode = NList.getNamedItem(arg.NodeName())
-  if item == nil:
+  if isNil(item):
     NList.add(arg)
     return nil
   else:
@@ -780,18 +780,18 @@ proc setNamedItem*(NList: var seq[PNode], arg: PNode): PNode =
 proc setNamedItem*(NList: var seq[PAttr], arg: PAttr): PAttr =
   ## Adds ``arg`` as a ``Node`` to the ``NList``
   ## If a node with the same name is already present in this map, it is replaced by the new one.
-  if NList != nil:
+  if not isNil(NList):
     if NList.len() > 0:
       # Check if newChild is from this nodes document
       if NList[0].FOwnerDocument != arg.FOwnerDocument:
         raise newException(EWrongDocumentErr, "This node belongs to a different document, use importNode.")
 
-  if arg.FOwnerElement != nil:
+  if not isNil(arg.FOwnerElement):
     raise newException(EInuseAttributeErr, "This attribute is in use by another element, use cloneNode")
 
   # Exceptions end
   var item: PAttr = NList.getNamedItem(arg.nodeName())
-  if item == nil:
+  if isNil(item):
     NList.add(arg)
     return nil
   else:
@@ -806,7 +806,7 @@ proc setNamedItem*(NList: var seq[PAttr], arg: PAttr): PAttr =
 
 proc setNamedItemNS*(NList: var seq[PNode], arg: PNode): PNode =
   ## Adds a node using its ``namespaceURI`` and ``localName``
-  if NList != nil:
+  if not isNil(NList):
     if NList.len() > 0:
       # Check if newChild is from this nodes document
       if NList[0].FOwnerDocument != arg.FOwnerDocument:
@@ -814,7 +814,7 @@ proc setNamedItemNS*(NList: var seq[PNode], arg: PNode): PNode =
   #Exceptions end
 
   var item: PNode = NList.getNamedItemNS(arg.namespaceURI(), arg.localName())
-  if item == nil:
+  if isNil(item):
     NList.add(arg)
     return nil
   else:
@@ -829,18 +829,18 @@ proc setNamedItemNS*(NList: var seq[PNode], arg: PNode): PNode =
 
 proc setNamedItemNS*(NList: var seq[PAttr], arg: PAttr): PAttr =
   ## Adds a node using its ``namespaceURI`` and ``localName``
-  if NList != nil:
+  if not isNil(NList):
     if NList.len() > 0:
       # Check if newChild is from this nodes document
       if NList[0].FOwnerDocument != arg.FOwnerDocument:
         raise newException(EWrongDocumentErr, "This node belongs to a different document, use importNode.")
 
-  if arg.FOwnerElement != nil:
+  if not isNil(arg.FOwnerElement):
     raise newException(EInuseAttributeErr, "This attribute is in use by another element, use cloneNode")
 
   # Exceptions end
   var item: PAttr = NList.getNamedItemNS(arg.namespaceURI(), arg.localName())
-  if item == nil:
+  if isNil(item):
     NList.add(arg)
     return nil
   else:
@@ -884,20 +884,20 @@ proc tagName*(el: PElement): string =
 # Procedures
 proc getAttribute*(el: PElement, name: string): string =
   ## Retrieves an attribute value by ``name``
-  if el.attributes == nil:
+  if isNil(el.attributes):
     return nil
   var attribute = el.attributes.getNamedItem(name)
-  if attribute != nil:
+  if not isNil(attribute):
     return attribute.value
   else:
     return nil
 
 proc getAttributeNS*(el: PElement, namespaceURI: string, localName: string): string =
   ## Retrieves an attribute value by ``localName`` and ``namespaceURI``
-  if el.attributes == nil:
+  if isNil(el.attributes):
     return nil
   var attribute = el.attributes.getNamedItemNS(namespaceURI, localName)
-  if attribute != nil:
+  if not isNil(attribute):
     return attribute.value
   else:
     return nil
@@ -905,13 +905,13 @@ proc getAttributeNS*(el: PElement, namespaceURI: string, localName: string): str
 proc getAttributeNode*(el: PElement, name: string): PAttr =
   ## Retrieves an attribute node by ``name``
   ## To retrieve an attribute node by qualified name and namespace URI, use the `getAttributeNodeNS` method
-  if el.attributes == nil:
+  if isNil(el.attributes):
     return nil
   return el.attributes.getNamedItem(name)
 
 proc getAttributeNodeNS*(el: PElement, namespaceURI: string, localName: string): PAttr =
   ## Retrieves an `Attr` node by ``localName`` and ``namespaceURI``
-  if el.attributes == nil:
+  if isNil(el.attributes):
     return nil
   return el.attributes.getNamedItemNS(namespaceURI, localName)
 
@@ -930,27 +930,27 @@ proc getElementsByTagNameNS*(el: PElement, namespaceURI: string, localName: stri
 proc hasAttribute*(el: PElement, name: string): bool =
   ## Returns ``true`` when an attribute with a given ``name`` is specified
   ## on this element , ``false`` otherwise.
-  if el.attributes == nil:
+  if isNil(el.attributes):
     return false
-  return el.attributes.getNamedItem(name) != nil
+  return not isNil(el.attributes.getNamedItem(name))
 
 proc hasAttributeNS*(el: PElement, namespaceURI: string, localName: string): bool =
   ## Returns ``true`` when an attribute with a given ``localName`` and
   ## ``namespaceURI`` is specified on this element , ``false`` otherwise
-  if el.attributes == nil:
+  if isNil(el.attributes):
     return false
-  return el.attributes.getNamedItemNS(namespaceURI, localName) != nil
+  return not isNil(el.attributes.getNamedItemNS(namespaceURI, localName))
 
 proc removeAttribute*(el: PElement, name: string) =
   ## Removes an attribute by ``name``
-  if el.attributes != nil:
+  if not isNil(el.attributes):
     for i in low(el.attributes)..high(el.attributes):
       if el.attributes[i].FName == name:
         el.attributes.delete(i)
 
 proc removeAttributeNS*(el: PElement, namespaceURI: string, localName: string) =
   ## Removes an attribute by ``localName`` and ``namespaceURI``
-  if el.attributes != nil:
+  if not isNil(el.attributes):
     for i in low(el.attributes)..high(el.attributes):
       if el.attributes[i].FNamespaceURI == namespaceURI and
           el.attributes[i].FLocalName == localName:
@@ -959,7 +959,7 @@ proc removeAttributeNS*(el: PElement, namespaceURI: string, localName: string) =
 proc removeAttributeNode*(el: PElement, oldAttr: PAttr): PAttr =
   ## Removes the specified attribute node
   ## If the attribute node cannot be found raises ``ENotFoundErr``
-  if el.attributes != nil:
+  if not isNil(el.attributes):
     for i in low(el.attributes)..high(el.attributes):
       if el.attributes[i] == oldAttr:
         result = el.attributes[i]
@@ -978,12 +978,12 @@ proc setAttributeNode*(el: PElement, newAttr: PAttr): PAttr =
     raise newException(EWrongDocumentErr,
       "This node belongs to a different document, use importNode.")
 
-  if newAttr.FOwnerElement != nil:
+  if not isNil(newAttr.FOwnerElement):
     raise newException(EInuseAttributeErr,
       "This attribute is in use by another element, use cloneNode")
   # Exceptions end
 
-  if el.attributes == nil: el.attributes = @[]
+  if isNil(el.attributes): el.attributes = @[]
   return el.attributes.setNamedItem(newAttr)
 
 proc setAttributeNodeNS*(el: PElement, newAttr: PAttr): PAttr =
@@ -996,12 +996,12 @@ proc setAttributeNodeNS*(el: PElement, newAttr: PAttr): PAttr =
     raise newException(EWrongDocumentErr,
       "This node belongs to a different document, use importNode.")
 
-  if newAttr.FOwnerElement != nil:
+  if not isNil(newAttr.FOwnerElement):
     raise newException(EInuseAttributeErr,
       "This attribute is in use by another element, use cloneNode")
   # Exceptions end
 
-  if el.attributes == nil: el.attributes = @[]
+  if isNil(el.attributes): el.attributes = @[]
   return el.attributes.setNamedItemNS(newAttr)
 
 proc setAttribute*(el: PElement, name: string, value: string) =
@@ -1051,7 +1051,7 @@ proc splitData*(TextNode: PText, offset: int): PText =
   TextNode.data = left
   var right: string = TextNode.data.substr(offset, TextNode.data.len())
 
-  if TextNode.FParentNode != nil and TextNode.FParentNode.childNodes != nil:
+  if not isNil(TextNode.FParentNode) and not isNil(TextNode.FParentNode.childNodes):
     for i in low(TextNode.FParentNode.childNodes)..high(TextNode.FParentNode.childNodes):
       if TextNode.FParentNode.childNodes[i] == TextNode:
         var newNode: PText = TextNode.FOwnerDocument.createTextNode(right)
@@ -1083,11 +1083,11 @@ proc addEscaped(s: string): string =
 
 proc nodeToXml(n: PNode, indent: int = 0): string =
   result = repeatChar(indent, ' ') & "<" & n.nodeName
-  if n.attributes != nil:
+  if not isNil(n.attributes):
     for i in items(n.attributes):
       result.add(" " & i.name & "=\"" & addEscaped(i.value) & "\"")
 
-  if n.childNodes == nil or n.childNodes.len() == 0:
+  if isNil(n.childNodes) or n.childNodes.len() == 0:
     result.add("/>") # No idea why this doesn't need a \n :O
   else:
     # End the beginning of this tag

From eada55fc78fbe43aa8eb756c992d4b40473f1c23 Mon Sep 17 00:00:00 2001
From: def 
Date: Fri, 1 Aug 2014 22:48:55 +0200
Subject: [PATCH 087/234] Make nimrepl and trimcc tools compile

---
 tools/nimrepl.nim | 2 +-
 tools/trimcc.nim  | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/tools/nimrepl.nim b/tools/nimrepl.nim
index 8e43b4431d..4b6379bd59 100644
--- a/tools/nimrepl.nim
+++ b/tools/nimrepl.nim
@@ -24,7 +24,7 @@ proc execCode(code: string): string =
     f.close()
     result = osproc.execProcess(
       "$# $# --verbosity:0 --hint[Conf]:off temp.nim" % [nimExe, runCmd],
-      {poStdErrToStdOut})
+      options = {poStdErrToStdOut})
   else:
     result = "cannot open file 'temp.nim'"
 
diff --git a/tools/trimcc.nim b/tools/trimcc.nim
index 6271d2b9a6..4d96861953 100644
--- a/tools/trimcc.nim
+++ b/tools/trimcc.nim
@@ -18,7 +18,7 @@ proc walker(dir: string) =
       else:
         echo "Required: ", path
         # copy back:
-        moveFile(dest=path, sourc=newName(path))
+        moveFile(dest=path, source=newName(path))
     of pcDir:
       walker(path)
     else: discard

From 9673e4f2df941bfeeb3e1fe8e66d89fddea1145b Mon Sep 17 00:00:00 2001
From: Araq 
Date: Fri, 1 Aug 2014 23:40:48 +0200
Subject: [PATCH 088/234] progress on deepCopy

---
 compiler/ast.nim                  |  10 +-
 compiler/ccgexprs.nim             |  46 ++++++--
 compiler/ccgtypes.nim             |  17 ++-
 compiler/ccgutils.nim             |   6 +-
 compiler/cgen.nim                 |   2 +-
 compiler/lowerings.nim            |  66 +++++++----
 compiler/pragmas.nim              |  14 ++-
 compiler/semdestruct.nim          |   3 +-
 compiler/semstmts.nim             |  24 +++-
 compiler/semtypinst.nim           |   2 +-
 compiler/wordrecg.nim             |   4 +-
 doc/manual.txt                    | 189 ++++++++++++++++++++----------
 lib/system.nim                    |  11 +-
 lib/system/deepcopy.nim           | 121 +++++++++++++++++++
 lib/system/hti.nim                |   1 +
 tests/destructor/tdestructor.nim  |   6 +-
 tests/destructor/tdestructor2.nim |   2 +-
 todo.txt                          |  22 ++--
 web/news.txt                      |   8 ++
 19 files changed, 419 insertions(+), 135 deletions(-)
 create mode 100644 lib/system/deepcopy.nim

diff --git a/compiler/ast.nim b/compiler/ast.nim
index bdb8d1c23e..51319127c5 100644
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -263,7 +263,7 @@ type
     sfNamedParamCall, # symbol needs named parameter call syntax in target
                       # language; for interfacing with Objective C
     sfDiscardable,    # returned value may be discarded implicitly
-    sfDestructor,     # proc is destructor
+    sfOverriden,      # proc is overriden
     sfGenSym          # symbol is 'gensym'ed; do not add to symbol table
 
   TSymFlags* = set[TSymFlag]
@@ -785,12 +785,13 @@ type
                               # the body of the user-defined type class
                               # formal param list
                               # else: unused
-    destructor*: PSym         # destructor. warning: nil here may not necessary
-                              # mean that there is no destructor.
-                              # see instantiateDestructor in types.nim
     owner*: PSym              # the 'owner' of the type
     sym*: PSym                # types have the sym associated with them
                               # it is used for converting types to strings
+    destructor*: PSym         # destructor. warning: nil here may not necessary
+                              # mean that there is no destructor.
+                              # see instantiateDestructor in semdestruct.nim
+    deepCopy*: PSym           # overriden 'deepCopy' operation
     size*: BiggestInt         # the size of the type in bytes
                               # -1 means that the size is unkwown
     align*: int               # the type's alignment requirements
@@ -1190,6 +1191,7 @@ proc assignType(dest, src: PType) =
   dest.size = src.size
   dest.align = src.align
   dest.destructor = src.destructor
+  dest.deepCopy = src.deepCopy
   # this fixes 'type TLock = TSysLock':
   if src.sym != nil:
     if dest.sym != nil:
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index 95167e1576..d5b2ad33d5 100644
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -359,6 +359,32 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
     linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(dest), rdLoc(src))
   else: internalError("genAssignment: " & $ty.kind)
 
+proc genDeepCopy(p: BProc; dest, src: TLoc) =
+  var ty = skipTypes(dest.t, abstractRange)
+  case ty.kind
+  of tyPtr, tyRef, tyString, tyProc, tyTuple, tyObject, tyArray, tyArrayConstr:
+    # XXX optimize this
+    linefmt(p, cpsStmts, "#genericDeepCopy((void*)$1, (void*)$2, $3);$n",
+            addrLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t))
+  of tySequence:
+    linefmt(p, cpsStmts, "#genericSeqDeepCopy($1, $2, $3);$n",
+            addrLoc(dest), rdLoc(src), genTypeInfo(p.module, dest.t))
+  of tyOpenArray, tyVarargs:
+    linefmt(p, cpsStmts,
+         "#genericDeepCopyOpenArray((void*)$1, (void*)$2, $1Len0, $3);$n",
+         addrLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t))
+  of tySet:
+    if mapType(ty) == ctArray:
+      useStringh(p.module)
+      linefmt(p, cpsStmts, "memcpy((void*)$1, (NIM_CONST void*)$2, $3);$n",
+              rdLoc(dest), rdLoc(src), toRope(getSize(dest.t)))
+    else:
+      linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(dest), rdLoc(src))
+  of tyPointer, tyChar, tyBool, tyEnum, tyCString,
+     tyInt..tyUInt64, tyRange, tyVar:
+    linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(dest), rdLoc(src))
+  else: internalError("genDeepCopy: " & $ty.kind)
+
 proc getDestLoc(p: BProc, d: var TLoc, typ: PType) =
   if d.k == locNone: getTemp(p, typ, d)
 
@@ -1578,25 +1604,25 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
   of mGetTypeInfo: genGetTypeInfo(p, e, d)
   of mSwap: genSwap(p, e, d)
   of mUnaryLt: 
-    if not (optOverflowCheck in p.options): unaryExpr(p, e, d, "$1 - 1")
+    if optOverflowCheck notin p.options: unaryExpr(p, e, d, "$1 - 1")
     else: unaryExpr(p, e, d, "#subInt($1, 1)")
   of mPred:
     # XXX: range checking?
-    if not (optOverflowCheck in p.options): binaryExpr(p, e, d, "$1 - $2")
+    if optOverflowCheck notin p.options: binaryExpr(p, e, d, "$1 - $2")
     else: binaryExpr(p, e, d, "#subInt($1, $2)")
   of mSucc:
     # XXX: range checking?
-    if not (optOverflowCheck in p.options): binaryExpr(p, e, d, "$1 + $2")
+    if optOverflowCheck notin p.options: binaryExpr(p, e, d, "$1 + $2")
     else: binaryExpr(p, e, d, "#addInt($1, $2)")
   of mInc:
-    if not (optOverflowCheck in p.options):
+    if optOverflowCheck notin p.options:
       binaryStmt(p, e, d, "$1 += $2;$n")
     elif skipTypes(e.sons[1].typ, abstractVar).kind == tyInt64:
       binaryStmt(p, e, d, "$1 = #addInt64($1, $2);$n")
     else:
       binaryStmt(p, e, d, "$1 = #addInt($1, $2);$n")
   of ast.mDec:
-    if not (optOverflowCheck in p.options):
+    if optOverflowCheck notin p.options:
       binaryStmt(p, e, d, "$1 -= $2;$n")
     elif skipTypes(e.sons[1].typ, abstractVar).kind == tyInt64:
       binaryStmt(p, e, d, "$1 = #subInt64($1, $2);$n")
@@ -1659,6 +1685,11 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
   of mParallel:
     let n = semparallel.liftParallel(p.module.module, e)
     expr(p, n, d)
+  of mDeepCopy:
+    var a, b: TLoc
+    initLocExpr(p, e.sons[1], a)
+    initLocExpr(p, e.sons[2], b)
+    genDeepCopy(p, a, b) 
   else: internalError(e.info, "genMagicExpr: " & $op)
 
 proc genConstExpr(p: BProc, n: PNode): PRope
@@ -1878,7 +1909,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
     of skVar, skForVar, skResult, skLet:
       if sfGlobal in sym.flags: genVarPrototype(p.module, sym)
       if sym.loc.r == nil or sym.loc.t == nil:
-        internalError(n.info, "expr: var not init " & sym.name.s)
+        internalError n.info, "expr: var not init " & sym.name.s & "_" & $sym.id
       if sfThread in sym.flags:
         accessThreadLocalVar(p, sym)
         if emulatedThreadVars(): 
@@ -1893,7 +1924,8 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
       putLocIntoDest(p, d, sym.loc)
     of skParam:
       if sym.loc.r == nil or sym.loc.t == nil:
-        internalError(n.info, "expr: param not init " & sym.name.s)
+        #echo "FAILED FOR PRCO ", p.prc.name.s
+        internalError(n.info, "expr: param not init " & sym.name.s & "_" & $sym.id)
       putLocIntoDest(p, d, sym.loc)
     else: internalError(n.info, "expr(" & $sym.kind & "); unknown symbol")
   of nkNilLit:
diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim
index 8e762ce279..4c71c6ff79 100644
--- a/compiler/ccgtypes.nim
+++ b/compiler/ccgtypes.nim
@@ -453,7 +453,7 @@ proc getRecordDesc(m: BModule, typ: PType, name: PRope,
     appf(result, " {$n", [name])
 
   var desc = getRecordFields(m, typ, check)
-  if (desc == nil) and not hasField: 
+  if desc == nil and not hasField: 
     appf(result, "char dummy;$n", [])
   else: 
     app(result, desc)
@@ -895,11 +895,20 @@ type
 
 include ccgtrav
 
-proc genTypeInfo(m: BModule, t: PType): PRope = 
+proc genDeepCopyProc(m: BModule; s: PSym; result: PRope) =
+  genProc(m, s)
+  appf(m.s[cfsTypeInit3], "$1.deepcopy = (N_NIMCALL_PTR(void*, void*)) $2;$n",
+     [result, s.loc.r])
+
+proc genTypeInfo(m: BModule, t: PType): PRope =
+  let origType = t
   var t = getUniqueType(t)
   result = ropef("NTI$1", [toRope(t.id)])
   if containsOrIncl(m.typeInfoMarker, t.id):
     return con("(&".toRope, result, ")".toRope)
+  
+  # getUniqueType doesn't skip tyDistinct when that has an overriden operation:
+  while t.kind == tyDistinct: t = t.lastSon
   let owner = t.skipTypes(typedescPtrs).owner.getModule
   if owner != m.module:
     # make sure the type info is created in the owner module
@@ -936,6 +945,10 @@ proc genTypeInfo(m: BModule, t: PType): PRope =
     # results are not deterministic!
     genTupleInfo(m, t, result)
   else: internalError("genTypeInfo(" & $t.kind & ')')
+  if t.deepCopy != nil:
+    genDeepCopyProc(m, t.deepCopy, result)
+  elif origType.deepCopy != nil:
+    genDeepCopyProc(m, origType.deepCopy, result)  
   result = con("(&".toRope, result, ")".toRope)
 
 proc genTypeSection(m: BModule, n: PNode) = 
diff --git a/compiler/ccgutils.nim b/compiler/ccgutils.nim
index 04983d6a4f..6af6a857c6 100644
--- a/compiler/ccgutils.nim
+++ b/compiler/ccgutils.nim
@@ -89,8 +89,10 @@ proc getUniqueType*(key: PType): PType =
   of tyTypeDesc, tyTypeClasses, tyGenericParam,
      tyFromExpr, tyFieldAccessor:
     internalError("GetUniqueType")
-  of tyGenericInst, tyDistinct, tyOrdinal, tyMutable,
-     tyConst, tyIter, tyStatic:
+  of tyDistinct:
+    if key.deepCopy != nil: result = key
+    else: result = getUniqueType(lastSon(key))
+  of tyGenericInst, tyOrdinal, tyMutable, tyConst, tyIter, tyStatic:
     result = getUniqueType(lastSon(key))
   of tyArrayConstr, tyGenericInvokation, tyGenericBody,
      tyOpenArray, tyArray, tySet, tyRange, tyTuple,
diff --git a/compiler/cgen.nim b/compiler/cgen.nim
index e2f3b5ab0a..b930bea8d4 100644
--- a/compiler/cgen.nim
+++ b/compiler/cgen.nim
@@ -295,6 +295,7 @@ proc postStmtActions(p: BProc) {.inline.} =
 
 proc accessThreadLocalVar(p: BProc, s: PSym)
 proc emulatedThreadVars(): bool {.inline.}
+proc genProc(m: BModule, prc: PSym)
 
 include "ccgtypes.nim"
 
@@ -574,7 +575,6 @@ proc fixLabel(p: BProc, labl: TLabel) =
 
 proc genVarPrototype(m: BModule, sym: PSym)
 proc requestConstImpl(p: BProc, sym: PSym)
-proc genProc(m: BModule, prc: PSym)
 proc genStmts(p: BProc, t: PNode)
 proc expr(p: BProc, n: PNode, d: var TLoc)
 proc genProcPrototype(m: BModule, sym: PSym)
diff --git a/compiler/lowerings.nim b/compiler/lowerings.nim
index 5b61a9cae9..1f1a7647b4 100644
--- a/compiler/lowerings.nim
+++ b/compiler/lowerings.nim
@@ -122,8 +122,8 @@ proc indirectAccess*(a: PNode, b: string, info: TLineInfo): PNode =
     if t == nil: break
     t = t.skipTypes(abstractInst)
   #if field == nil:
+  #  echo "FIELD ", b
   #  debug deref.typ
-  #  echo deref.typ.id
   internalAssert field != nil
   addSon(deref, a)
   result = newNodeI(nkDotExpr, info)
@@ -202,7 +202,8 @@ proc flowVarKind(t: PType): TFlowVarKind =
   elif containsGarbageCollectedRef(t): fvInvalid
   else: fvBlob
 
-proc addLocalVar(varSection: PNode; owner: PSym; typ: PType; v: PNode): PSym =
+proc addLocalVar(varSection, varInit: PNode; owner: PSym; typ: PType;
+                 v: PNode): PSym =
   result = newSym(skTemp, getIdent(genPrefix), owner, varSection.info)
   result.typ = typ
   incl(result.flags, sfFromGeneric)
@@ -210,8 +211,15 @@ proc addLocalVar(varSection: PNode; owner: PSym; typ: PType; v: PNode): PSym =
   var vpart = newNodeI(nkIdentDefs, varSection.info, 3)
   vpart.sons[0] = newSymNode(result)
   vpart.sons[1] = ast.emptyNode
-  vpart.sons[2] = v
+  vpart.sons[2] = if varInit.isNil: v else: ast.emptyNode
   varSection.add vpart
+  if varInit != nil:
+    let deepCopyCall = newNodeI(nkCall, varInit.info, 3)
+    deepCopyCall.sons[0] = newSymNode(createMagic("deepCopy", mDeepCopy))
+    deepCopyCall.sons[1] = newSymNode(result)
+    deepCopyCall.sons[2] = v
+    deepCopyCall.typ = typ
+    varInit.add deepCopyCall
 
 discard """
 We generate roughly this:
@@ -244,24 +252,25 @@ stmtList:
 """
 
 proc createWrapperProc(f: PNode; threadParam, argsParam: PSym;
-                       varSection, call, barrier, fv: PNode;
+                       varSection, varInit, call, barrier, fv: PNode;
                        spawnKind: TSpawnResult): PSym =
   var body = newNodeI(nkStmtList, f.info)
   var threadLocalBarrier: PSym
   if barrier != nil:
     var varSection = newNodeI(nkVarSection, barrier.info)
-    threadLocalBarrier = addLocalVar(varSection, argsParam.owner, 
+    threadLocalBarrier = addLocalVar(varSection, nil, argsParam.owner, 
                                      barrier.typ, barrier)
     body.add varSection
     body.add callCodeGenProc("barrierEnter", threadLocalBarrier.newSymNode)
   var threadLocalProm: PSym
   if spawnKind == srByVar:
-    threadLocalProm = addLocalVar(varSection, argsParam.owner, fv.typ, fv)
+    threadLocalProm = addLocalVar(varSection, nil, argsParam.owner, fv.typ, fv)
   elif fv != nil:
     internalAssert fv.typ.kind == tyGenericInst
-    threadLocalProm = addLocalVar(varSection, argsParam.owner, fv.typ, fv)
-    
-  body.add varSection
+    threadLocalProm = addLocalVar(varSection, nil, argsParam.owner, fv.typ, fv)
+  if barrier == nil:
+    body.add varSection
+  body.add varInit
   if fv != nil and spawnKind != srByVar:
     # generate:
     #   fv.owner = threadParam
@@ -314,7 +323,8 @@ proc createCastExpr(argsParam: PSym; objType: PType): PNode =
   result.typ.rawAddSon(objType)
 
 proc setupArgsForConcurrency(n: PNode; objType: PType; scratchObj: PSym, 
-                             castExpr, call, varSection, result: PNode) =
+                             castExpr, call, 
+                             varSection, varInit, result: PNode) =
   let formals = n[0].typ.n
   let tmpName = getIdent(genPrefix)
   for i in 1 .. ", importc: "printf", varargs.}
 
 Note that this pragma is somewhat of a misnomer: Other backends will provide
-the same feature under the same name. Also, if you are interfacing with C++
-you can use the `ImportCpp pragma `_ and
+the same feature under the same name. Also, if one is interfacing with C++
+the `ImportCpp pragma `_ and
 interfacing with Objective-C the `ImportObjC pragma
-`_.
+`_ can be used.
 
 
 Exportc pragma
@@ -5781,12 +5842,14 @@ used instead. `spawn`:idx: is used to pass a task to the thread pool:
 
 Currently the expression that ``spawn`` takes is however quite restricted: 
 
-* It must be a call expresion ``f(a, ...)``.
+* It must be a call expression ``f(a, ...)``.
 * ``f`` must be ``gcsafe``.
 * ``f`` must not have the calling convention ``closure``.
-* ``f``'s parameters may not be of type ``var`` nor may they contain ``ref``.
-  This means you have to use raw ``ptr``'s for data passing reminding the
+* ``f``'s parameters may not be of type ``var``.
+  This means one has to use raw ``ptr``'s for data passing reminding the
   programmer to be careful.
+* ``ref`` parameters are deeply copied which is a subtle semantic change and
+  can cause performance problems but ensures memory safety.
 * For *safe* data exchange between ``f`` and the caller a global ``TChannel``
   needs to be used. Other means will be provided soon.
 
diff --git a/lib/system.nim b/lib/system.nim
index 753205777e..3e4d3fb9e7 100644
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -2997,10 +2997,13 @@ proc locals*(): TObject {.magic: "Locals", noSideEffect.} =
   ##   # -> B is 1
   discard
 
-proc deepCopy*[T](x: T): T {.magic: "DeepCopy", noSideEffect.} =
-  ## performs a deep copy of `x`. This is also used by the code generator
-  ## for the implementation of ``spawn``.
-  discard
+when hostOS != "standalone" and not defined(NimrodVM) and not defined(JS):
+  proc deepCopy*[T](x: var T, y: T) {.noSideEffect, magic: "DeepCopy".} =
+    ## performs a deep copy of `x`. This is also used by the code generator
+    ## for the implementation of ``spawn``.
+    discard
+
+  include "system/deepcopy"
 
 {.pop.} #{.push warning[GcMem]: off.}
 
diff --git a/lib/system/deepcopy.nim b/lib/system/deepcopy.nim
new file mode 100644
index 0000000000..d3f9c5d7c9
--- /dev/null
+++ b/lib/system/deepcopy.nim
@@ -0,0 +1,121 @@
+#
+#
+#            Nimrod's Runtime Library
+#        (c) Copyright 2014 Andreas Rumpf
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+proc genericDeepCopyAux(dest, src: pointer, mt: PNimType) {.gcsafe.}
+proc genericDeepCopyAux(dest, src: pointer, n: ptr TNimNode) {.gcsafe.} =
+  var
+    d = cast[TAddress](dest)
+    s = cast[TAddress](src)
+  case n.kind
+  of nkSlot:
+    genericDeepCopyAux(cast[pointer](d +% n.offset), 
+                       cast[pointer](s +% n.offset), n.typ)
+  of nkList:
+    for i in 0..n.len-1:
+      genericDeepCopyAux(dest, src, n.sons[i])
+  of nkCase:
+    var dd = selectBranch(dest, n)
+    var m = selectBranch(src, n)
+    # reset if different branches are in use; note different branches also
+    # imply that's not self-assignment (``x = x``)!
+    if m != dd and dd != nil: 
+      genericResetAux(dest, dd)
+    copyMem(cast[pointer](d +% n.offset), cast[pointer](s +% n.offset),
+            n.typ.size)
+    if m != nil:
+      genericDeepCopyAux(dest, src, m)
+  of nkNone: sysAssert(false, "genericDeepCopyAux")
+
+proc genericDeepCopyAux(dest, src: pointer, mt: PNimType) =
+  var
+    d = cast[TAddress](dest)
+    s = cast[TAddress](src)
+  sysAssert(mt != nil, "genericDeepCopyAux 2")
+  case mt.kind
+  of tyString:
+    var x = cast[PPointer](dest)
+    var s2 = cast[PPointer](s)[]
+    if s2 == nil:
+      unsureAsgnRef(x, s2)
+    else:
+      unsureAsgnRef(x, copyString(cast[NimString](s2)))
+  of tySequence:
+    var s2 = cast[PPointer](src)[]
+    var seq = cast[PGenericSeq](s2)      
+    var x = cast[PPointer](dest)
+    if s2 == nil:
+      unsureAsgnRef(x, s2)
+      return
+    sysAssert(dest != nil, "genericDeepCopyAux 3")
+    unsureAsgnRef(x, newSeq(mt, seq.len))
+    var dst = cast[TAddress](cast[PPointer](dest)[])
+    for i in 0..seq.len-1:
+      genericDeepCopyAux(
+        cast[pointer](dst +% i*% mt.base.size +% GenericSeqSize),
+        cast[pointer](cast[TAddress](s2) +% i *% mt.base.size +%
+                     GenericSeqSize),
+        mt.base)
+  of tyObject:
+    # we need to copy m_type field for tyObject, as it could be empty for
+    # sequence reallocations:
+    var pint = cast[ptr PNimType](dest)
+    pint[] = cast[ptr PNimType](src)[]
+    if mt.base != nil:
+      genericDeepCopyAux(dest, src, mt.base)
+    genericDeepCopyAux(dest, src, mt.node)
+  of tyTuple:
+    genericDeepCopyAux(dest, src, mt.node)
+  of tyArray, tyArrayConstr:
+    for i in 0..(mt.size div mt.base.size)-1:
+      genericDeepCopyAux(cast[pointer](d +% i*% mt.base.size),
+                         cast[pointer](s +% i*% mt.base.size), mt.base)
+  of tyRef:
+    var z: pointer
+    if mt.base.deepCopy != nil:
+      z = mt.base.deepCopy(cast[PPointer](s)[])
+    else:
+      # we modify the header of the cell temporarily; instead of the type
+      # field we store a forwarding pointer. XXX This is bad when the cloning
+      # fails due to OOM etc.
+      let x = usrToCell(cast[PPointer](s)[])
+      let forw = cast[int](x.typ)
+      if (forw and 1) == 1:
+        # we stored a forwarding pointer, so let's use that:
+        z = cast[pointer](forw and not 1)
+      else:
+        let realType = x.typ
+        z = newObj(realType, realType.base.size)
+        x.typ = cast[PNimType](cast[int](z) or 1)
+        genericDeepCopyAux(dest, addr(z), realType)
+        x.typ = realType
+    unsureAsgnRef(cast[PPointer](dest), z)
+  of tyPtr:
+    # no cycle check here, but also not really required
+    if mt.base.deepCopy != nil:
+      cast[PPointer](dest)[] = mt.base.deepCopy(cast[PPointer](s)[])
+    else:
+      cast[PPointer](dest)[] = cast[PPointer](s)[]
+  else:
+    copyMem(dest, src, mt.size) # copy raw bits
+
+proc genericDeepCopy(dest, src: pointer, mt: PNimType) {.compilerProc.} =
+  genericDeepCopyAux(dest, src, mt)
+
+proc genericSeqDeepCopy(dest, src: pointer, mt: PNimType) {.compilerProc.} =
+  var src = src
+  genericDeepCopy(dest, addr(src), mt)
+
+proc genericDeepCopyOpenArray(dest, src: pointer, len: int,
+                            mt: PNimType) {.compilerproc.} =
+  var
+    d = cast[TAddress](dest)
+    s = cast[TAddress](src)
+  for i in 0..len-1:
+    genericDeepCopy(cast[pointer](d +% i*% mt.base.size),
+                    cast[pointer](s +% i*% mt.base.size), mt.base)
diff --git a/lib/system/hti.nim b/lib/system/hti.nim
index 64174e60f1..5689f92b36 100644
--- a/lib/system/hti.nim
+++ b/lib/system/hti.nim
@@ -86,6 +86,7 @@ type
     node: ptr TNimNode # valid for tyRecord, tyObject, tyTuple, tyEnum
     finalizer: pointer # the finalizer for the type
     marker: proc (p: pointer, op: int) {.nimcall, gcsafe.} # marker proc for GC
+    deepcopy: proc (p: pointer): pointer {.nimcall, gcsafe.}
   PNimType = ptr TNimType
   
 # node.len may be the ``first`` element of a set
diff --git a/tests/destructor/tdestructor.nim b/tests/destructor/tdestructor.nim
index e5236aaab3..f0ea3c5c67 100644
--- a/tests/destructor/tdestructor.nim
+++ b/tests/destructor/tdestructor.nim
@@ -55,14 +55,14 @@ type
         q: TMyGeneric3[TMyObj, int, int]
       r: string
 
-proc destruct(o: var TMyObj) {.destructor.} =
+proc destroy(o: var TMyObj) {.override.} =
   if o.p != nil: dealloc o.p
   echo "myobj destroyed"
 
-proc destroy(o: var TMyGeneric1) {.destructor.} =
+proc destroy(o: var TMyGeneric1) {.override.} =
   echo "mygeneric1 destroyed"
 
-proc destroy[A, B](o: var TMyGeneric2[A, B]) {.destructor.} =
+proc destroy[A, B](o: var TMyGeneric2[A, B]) {.override.} =
   echo "mygeneric2 destroyed"
 
 proc open: TMyObj =
diff --git a/tests/destructor/tdestructor2.nim b/tests/destructor/tdestructor2.nim
index da9192a3f9..a5b62860ca 100644
--- a/tests/destructor/tdestructor2.nim
+++ b/tests/destructor/tdestructor2.nim
@@ -8,7 +8,7 @@ type
     x, y: int
     p: pointer
     
-proc destruct(o: var TMyObj) {.destructor.} =
+proc destroy(o: var TMyObj) {.override.} =
   if o.p != nil: dealloc o.p
   
 proc open: TMyObj =
diff --git a/todo.txt b/todo.txt
index bd8f7f89e4..6ae5df509c 100644
--- a/todo.txt
+++ b/todo.txt
@@ -3,20 +3,26 @@ version 0.9.6
 
 - scopes are still broken for generic instantiation!
 - start experimental branch
-- overloading of '='; general lift mechanism
+- implicit deref for parameter matching
 
 Concurrency
 -----------
 
 - 'gcsafe' inferrence needs to be fixed
+- 'deepCopy' needs to be instantiated for
+  generics *when the type is constructed*
+- test 'deepCopy'
+- overloading of '='; general lift mechanism
+
 - the disjoint checker needs to deal with 'a = spawn f(); g = spawn f()'
-- implement 'deepCopy' builtin
 - implement 'foo[1..4] = spawn(f[4..7])'
-- support for exception propagation
-- Minor: The copying of the 'ref Promise' into the thead local storage only
+- document the new 'spawn' and 'parallel' statements
+
+Low priority:
+- support for exception propagation? (hard to implement)
+- the copying of the 'ref Promise' into the thead local storage only
   happens to work due to the write barrier's implementation
 - implement lock levels --> first without the more complex race avoidance
-- document the new 'spawn' and 'parallel' statements
 
 
 Misc
@@ -27,8 +33,6 @@ Misc
 - fix the tuple unpacking in lambda bug
 - make tuple unpacking work in a non-var/let context
 - special rule for ``[]=``
-- ``=`` should be overloadable; requires specialization for ``=``; general
-  lift mechanism in the compiler is already implemented for 'fields'
 - built-in 'getImpl'
 - type API for macros; make 'spawn' a macro
 - markAndSweepGC should expose an API for fibers
@@ -57,13 +61,9 @@ version 0.9.x
 - implement 'bits' pragmas
 - we need a magic thisModule symbol
 - provide --nilChecks:on|off
-- fix closures/lambdalifting
 - ensure (ref T)(a, b) works as a type conversion and type constructor
 - optimize 'genericReset'; 'newException' leads to code bloat
 - stack-less GC
-- implicit deref for parameter matching
-
-- VM: optimize opcAsgnStr
 
 
 version 0.9.X
diff --git a/web/news.txt b/web/news.txt
index 62a923dcd5..3aca10692c 100644
--- a/web/news.txt
+++ b/web/news.txt
@@ -20,6 +20,14 @@ News
     representation.
   - ``uri.TUrl`` as well as the ``parseurl`` module are now deprecated in favour
     of the new ``TUri`` type in the ``uri`` module.
+  - The ``destructor`` pragma has been deprecated. Use the ``override`` pragma
+    instead. The destructor's name has to be ``destroy`` now.
+
+  Language Additions
+  ------------------
+
+  - There is a new ``parallel`` statement for safe fork&join parallel computing.
+  
 
   Library Additions
   -----------------

From 23f64dd63d6c8f178f5fca1ec6e7706844808359 Mon Sep 17 00:00:00 2001
From: Varriount 
Date: Sat, 2 Aug 2014 00:16:10 -0400
Subject: [PATCH 089/234] Update commands.nim

---
 compiler/commands.nim | 2 --
 1 file changed, 2 deletions(-)

diff --git a/compiler/commands.nim b/compiler/commands.nim
index 4fec420f77..7219c168ad 100644
--- a/compiler/commands.nim
+++ b/compiler/commands.nim
@@ -291,14 +291,12 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) =
   of "excludepath":
     expectArg(switch, arg, pass, info)
     let path = processPath(arg)
-    echo repr(options.searchPaths)
     lists.excludePath(options.searchPaths, path)
     lists.excludePath(options.lazyPaths, path)
     if (len(path) > 0) and (path[len(path) - 1] == DirSep):
       let strippedPath = path[0 .. (len(path) - 2)]
       lists.excludePath(options.searchPaths, strippedPath)
       lists.excludePath(options.lazyPaths, strippedPath)
-    echo repr(options.searchPaths)
   of "nimcache":
     expectArg(switch, arg, pass, info)
     options.nimcacheDir = processPath(arg)

From 9fd6464a746187faad61b92bafcf98410f6f88d3 Mon Sep 17 00:00:00 2001
From: Grzegorz Adam Hankiewicz 
Date: Sat, 2 Aug 2014 20:44:37 +0200
Subject: [PATCH 090/234] Updates js.high usage for line ending dots. Refs
 #1291 and #1292.

---
 web/babelpkglist.nim | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/web/babelpkglist.nim b/web/babelpkglist.nim
index 8745c9f997..8de6047efc 100644
--- a/web/babelpkglist.nim
+++ b/web/babelpkglist.nim
@@ -38,8 +38,7 @@ proc processContent(content: string) =
       else: pkg["url"].str
     let
       desc = pkg["description"].str
-      # Review array index access when #1291 is solved.
-      dot = if desc.high > 0 and desc[ 0 and desc[desc.high] in endings: "" else: "."
       listItem = li(a(href=pkgWeb, pkg["name"].str), " ", desc & dot)
     if pkg["url"].str.startsWith("git://github.com/nimrod-code") or
        "official" in pkg["tags"].elems:

From bddfe007b6975687102e924cebab0497ea93584f Mon Sep 17 00:00:00 2001
From: Grzegorz Adam Hankiewicz 
Date: Sat, 2 Aug 2014 20:51:21 +0200
Subject: [PATCH 091/234] Adds placeholder text for js disabled browsers. Refs
 #1292.

---
 doc/lib.txt          | 6 ++++--
 web/babelpkglist.nim | 6 ++----
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/doc/lib.txt b/doc/lib.txt
index 2da753007b..5bacfcc4f9 100644
--- a/doc/lib.txt
+++ b/doc/lib.txt
@@ -594,7 +594,8 @@ compiler.
 
 .. raw:: html
 
-  
+
If you are reading this you are missing + babelpkglist.js or have javascript disabled in your browser.
Unofficial packages ------------------- @@ -605,7 +606,8 @@ Nimrod programming language. .. raw:: html -
+
If you are reading this you are missing + babelpkglist.js or have javascript disabled in your browser.
diff --git a/web/babelpkglist.nim b/web/babelpkglist.nim index 8de6047efc..e8f9efc1bd 100644 --- a/web/babelpkglist.nim +++ b/web/babelpkglist.nim @@ -50,19 +50,17 @@ proc processContent(content: string) = var officialPkgListDiv = document.getElementById("officialPkgList") - officialPkgListDiv.innerHTML.add( + officialPkgListDiv.innerHTML = p("There are currently " & $officialCount & " official packages in the Babel package repository.") & ul(officialList) - ) var unofficialPkgListDiv = document.getElementById("unofficialPkgList") - unofficialPkgListDiv.innerHTML.add( + unofficialPkgListDiv.innerHTML = p("There are currently " & $unofficialCount & " unofficial packages in the Babel package repository.") & ul(unofficialList) - ) proc gotPackageList(apiReply: TData) {.exportc.} = let decoded = decodeContent($apiReply.content) From ca937cdba8246eb21357e4147a568709c62a5463 Mon Sep 17 00:00:00 2001 From: Grzegorz Adam Hankiewicz Date: Sat, 2 Aug 2014 20:53:56 +0200 Subject: [PATCH 092/234] Uses case insensitive comparison for sorting. Refs #1292. --- web/babelpkglist.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/babelpkglist.nim b/web/babelpkglist.nim index e8f9efc1bd..5da7d60a9c 100644 --- a/web/babelpkglist.nim +++ b/web/babelpkglist.nim @@ -21,7 +21,7 @@ proc processContent(content: string) = var jsonArr = jsonDoc.elems jsonArr.sort do (x, y: PJsonNode) -> int: - system.cmp(x["name"].str, y["name"].str) + strutils.cmpIgnoreCase(x["name"].str, y["name"].str) var officialList = "" From 00f56b20d7e2edb903c7c486574ad793a078667a Mon Sep 17 00:00:00 2001 From: Grzegorz Adam Hankiewicz Date: Tue, 5 Aug 2014 11:25:54 +0200 Subject: [PATCH 093/234] Adds usage example to typetraits.name(). Credit goes to fowl (http://forum.nimrod-lang.org/t/430). --- lib/pure/typetraits.nim | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/lib/pure/typetraits.nim b/lib/pure/typetraits.nim index e7bd363cf9..3203ee6997 100644 --- a/lib/pure/typetraits.nim +++ b/lib/pure/typetraits.nim @@ -11,7 +11,26 @@ ## working with types proc name*(t: typedesc): string {.magic: "TypeTrait".} - ## Returns the name of the given type + ## Returns the name of the given type. + ## + ## Example: + ## + ## .. code-block:: + ## + ## import typetraits + ## + ## proc `$`*[T](some:typedesc[T]): string = name(T) + ## + ## template test(x): stmt = + ## echo "type: ", type(x), ", value: ", x + ## + ## test 42 + ## # --> type: int, value: 42 + ## test "Foo" + ## # --> type: string, value: Foo + ## test(@['A','B']) + ## # --> type: seq[char], value: @[A, B] + proc arity*(t: typedesc): int {.magic: "TypeTrait".} - ## Returns the arity of the given type \ No newline at end of file + ## Returns the arity of the given type From 5c9d6762e48f0f5e70fed848ba11e79c86427206 Mon Sep 17 00:00:00 2001 From: Grzegorz Adam Hankiewicz Date: Tue, 5 Aug 2014 11:43:22 +0200 Subject: [PATCH 094/234] Adds typetraits to library index and doc build. --- doc/lib.txt | 5 ++++- web/nimrod.ini | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/doc/lib.txt b/doc/lib.txt index 5bacfcc4f9..76e7354e01 100644 --- a/doc/lib.txt +++ b/doc/lib.txt @@ -56,7 +56,10 @@ Core * `typeinfo `_ Provides (unsafe) access to Nimrod's run time type information. - + +* `typetraits `_ + This module defines compile-time reflection procs for working with types. + * `actors `_ Actor support for Nimrod; implemented as a layer on top of the threads and channels modules. diff --git a/web/nimrod.ini b/web/nimrod.ini index 544446b11e..38a906ac57 100644 --- a/web/nimrod.ini +++ b/web/nimrod.ini @@ -41,7 +41,7 @@ doc: "tools;niminst;nimgrep;gc;estp;idetools;docgen;koch;backends.txt" pdf: "manual;lib;tut1;tut2;nimrodc;niminst;gc" srcdoc2: "system.nim;impure/graphics;wrappers/sdl" srcdoc2: "core/macros;pure/marshal;core/typeinfo;core/unsigned" -srcdoc2: "impure/re;pure/sockets" +srcdoc2: "impure/re;pure/sockets;pure/typetraits" srcdoc: "system/threads.nim;system/channels.nim;js/dom" srcdoc2: "pure/os;pure/strutils;pure/math;pure/matchers;pure/algorithm" srcdoc2: "pure/complex;pure/times;pure/osproc;pure/pegs;pure/dynlib" From 688db0f70a08960e4785cc3807a3b97f706f877d Mon Sep 17 00:00:00 2001 From: Grzegorz Adam Hankiewicz Date: Tue, 5 Aug 2014 14:49:56 +0200 Subject: [PATCH 095/234] Improves tut1.txt with more hyperlinks and minor fixes. --- doc/tut1.txt | 199 +++++++++++++++++++++++++++------------------------ 1 file changed, 106 insertions(+), 93 deletions(-) diff --git a/doc/tut1.txt b/doc/tut1.txt index 55eb0ebd74..ee642ce176 100644 --- a/doc/tut1.txt +++ b/doc/tut1.txt @@ -17,10 +17,9 @@ Introduction This document is a tutorial for the programming language *Nimrod*. -This tutorial assumes that you are familiar with basic programming concepts -like variables, types or statements but is kept very basic. The manual -contains many more examples of the advanced language features. - +This tutorial assumes that you are familiar with basic programming concepts +like variables, types or statements but is kept very basic. The `manual +`_ contains many more examples of the advanced language features. @@ -40,9 +39,9 @@ Save this code to the file "greetings.nim". Now compile and run it:: nimrod compile --run greetings.nim -With the ``--run`` switch Nimrod executes the file automatically -after compilation. You can give your program command line arguments by -appending them after the filename:: +With the ``--run`` `switch `_ Nimrod +executes the file automatically after compilation. You can give your program +command line arguments by appending them after the filename:: nimrod compile --run greetings.nim arg1 arg2 @@ -54,9 +53,10 @@ To compile a release version use:: nimrod c -d:release greetings.nim -By default the Nimrod compiler generates a large amount of runtime checks -aiming for your debugging pleasure. With ``-d:release`` these checks are -turned off and optimizations are turned on. +By default the Nimrod compiler generates a large amount of runtime checks +aiming for your debugging pleasure. With ``-d:release`` these checks are +`turned off and optimizations are turned on +`_. 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 @@ -65,9 +65,10 @@ done with spaces only, tabulators are not allowed. String literals are enclosed in double quotes. The ``var`` statement declares a new variable named ``name`` of type ``string`` with the value that is -returned by the ``readLine`` procedure. Since the compiler knows that -``readLine`` returns a string, you can leave out the type in the declaration -(this is called `local type inference`:idx:). So this will work too: +returned by the `readLine `_ procedure. Since the +compiler knows that `readLine `_ returns a string, +you can leave out the type in the declaration (this is called `local type +inference`:idx:). So this will work too: .. code-block:: Nimrod var name = readLine(stdin) @@ -75,10 +76,10 @@ returned by the ``readLine`` procedure. Since the compiler knows that Note that this is basically the only form of type inference that exists in Nimrod: it is a good compromise between brevity and readability. -The "hello world" program contains several identifiers that are already -known to the compiler: ``echo``, ``readLine``, etc. These built-ins are -declared in the system_ module which is implicitly imported by any other -module. +The "hello world" program contains several identifiers that are already known +to the compiler: ``echo``, `readLine `_, etc. +These built-ins are declared in the system_ module which is implicitly +imported by any other module. Lexical elements @@ -154,11 +155,11 @@ the syntax, watch their indentation: when false: brokenCode() -Another option is to use the `discard`_ statement together with -*long string literals* to create block comments: +Another option is to use the `discard statement`_ together with *long string +literals* to create block comments: .. code-block:: nimrod - discard """ You can have any nimrod code text commented + discard """ You can have any Nimrod code text commented out inside this with no indentation restrictions. yes("May I ask a pointless question?") """ @@ -257,10 +258,10 @@ that can not be re-assigned, ``const`` means "enforce compile time evaluation and put it into a data section": .. code-block:: - const input = readline(stdin) # Error: constant expression expected + const input = readLine(stdin) # Error: constant expression expected .. code-block:: - let input = readline(stdin) # works + let input = readLine(stdin) # works Control flow statements @@ -285,9 +286,10 @@ The if statement is one way to branch the control flow: else: echo("Hi, ", name, "!") -There can be zero or more elif parts, and the else part is optional. The -keyword ``elif`` is short for ``else if``, and is useful to avoid excessive -indentation. (The ``""`` is the empty string. It contains no characters.) +There can be zero or more ``elif`` parts, and the ``else`` part is optional. +The keyword ``elif`` is short for ``else if``, and is useful to avoid +excessive indentation. (The ``""`` is the empty string. It contains no +characters.) Case statement @@ -338,7 +340,7 @@ the compiler that for every other value nothing should be done: of 3, 8: echo("The number is 3 or 8") else: discard -The empty ``discard`` statement is a *do nothing* statement. The compiler knows +The empty `discard statement`_ is a *do nothing* statement. The compiler knows that a case statement with an else part cannot fail and thus the error disappears. Note that it is impossible to cover all possible string values: that is why there is no such check for string cases. @@ -370,7 +372,8 @@ For statement ------------- The ``for`` statement is a construct to loop over any element an *iterator* -provides. The example uses the built-in ``countup`` iterator: +provides. The example uses the built-in `countup `_ +iterator: .. code-block:: nimrod echo("Counting to ten: ") @@ -378,11 +381,11 @@ provides. The example uses the built-in ``countup`` iterator: echo($i) # --> Outputs 1 2 3 4 5 6 7 8 9 10 on different lines -The built-in ``$`` operator turns an integer (``int``) and many other types -into a string. The variable ``i`` is implicitly declared by the ``for`` loop -and has the type ``int``, because that is what ``countup`` returns. ``i`` runs -through the values 1, 2, .., 10. Each value is ``echo``-ed. This code does -the same: +The built-in `$ `_ operator turns an integer (``int``) and many +other types into a string. The variable ``i`` is implicitly declared by the +``for`` loop and has the type ``int``, because that is what `countup +`_ returns. ``i`` runs through the values 1, 2, .., 10. +Each value is ``echo``-ed. This code does the same: .. code-block:: nimrod echo("Counting to 10: ") @@ -400,8 +403,8 @@ Counting down can be achieved as easily (but is less often needed): echo($i) # --> Outputs 10 9 8 7 6 5 4 3 2 1 on different lines -Since counting up occurs so often in programs, Nimrod also has a ``..`` iterator -that does the same: +Since counting up occurs so often in programs, Nimrod also has a `.. +`_ iterator that does the same: .. code-block:: nimrod for i in 1..10: @@ -553,9 +556,10 @@ an expression is allowed: Procedures ========== -To define new commands like ``echo``, ``readline`` in the examples, the concept -of a `procedure` is needed. (Some languages call them *methods* or -*functions*.) In Nimrod new procedures are defined with the ``proc`` keyword: +To define new commands like `echo `_ and `readLine +`_ in the examples, the concept of a `procedure` +is needed. (Some languages call them *methods* or *functions*.) In Nimrod new +procedures are defined with the ``proc`` keyword: .. code-block:: nimrod proc yes(question: string): bool = @@ -649,7 +653,7 @@ a tuple as a return value instead of using var parameters. Discard statement ----------------- To call a procedure that returns a value just for its side effects and ignoring -its return value, a discard statement **has** to be used. Nimrod does not +its return value, a ``discard`` statement **has** to be used. Nimrod does not allow to silently throw away a return value: .. code-block:: nimrod @@ -665,8 +669,8 @@ been declared with the ``discardable`` pragma: p(3, 4) # now valid -The discard statement can also be used to create block comments as described -in the `Comments`_. +The ``discard`` statement can also be used to create block comments as +described in the `Comments`_ section. Named arguments @@ -730,12 +734,12 @@ Nimrod provides the ability to overload procedures similar to C++: echo(toString(13)) # calls the toString(x: int) proc echo(toString(true)) # calls the toString(x: bool) proc -(Note that ``toString`` is usually the ``$`` operator in Nimrod.) -The compiler chooses the most appropriate proc for the ``toString`` calls. How -this overloading resolution algorithm works exactly is not discussed here -(it will be specified in the manual soon). -However, it does not lead to nasty surprises and is based on a quite simple -unification algorithm. Ambiguous calls are reported as errors. +(Note that ``toString`` is usually the `$ `_ operator in +Nimrod.) The compiler chooses the most appropriate proc for the ``toString`` +calls. How this overloading resolution algorithm works exactly is not +discussed here (it will be specified in the manual soon). However, it does +not lead to nasty surprises and is based on a quite simple unification +algorithm. Ambiguous calls are reported as errors. Operators @@ -758,7 +762,7 @@ User defined operators are allowed. Nothing stops you from defining your own The operator's precedence is determined by its first character. The details can be found in the manual. -To define a new operator enclose the operator in "``": +To define a new operator enclose the operator in backticks "``": .. code-block:: nimrod proc `$` (x: myDataType): string = ... @@ -811,7 +815,8 @@ Let's return to the boring counting example: for i in countup(1, 10): echo($i) -Can a ``countup`` proc be written that supports this loop? Lets try: +Can a `countup `_ proc be written that supports this +loop? Lets try: .. code-block:: nimrod proc countup(a, b: int): int = @@ -976,24 +981,25 @@ type: The common operators ``+ - * / < <= == != > >=`` are defined for floats and follow the IEEE standard. -Automatic type conversion in expressions with different kinds -of floating point types is performed: the smaller type is -converted to the larger. Integer types are **not** converted to floating point -types automatically and vice versa. The ``toInt`` and ``toFloat`` procs can be -used for these conversions. +Automatic type conversion in expressions with different kinds of floating +point types is performed: the smaller type is converted to the larger. Integer +types are **not** converted to floating point types automatically and vice +versa. The `toInt `_ and `toFloat `_ +procs can be used for these conversions. Internal type representation ============================ -As mentioned earlier, the built-in ``$`` (stringify) operator turns any basic -type into a string, which you can then print to the screen with the ``echo`` -proc. However, advanced types, or types you may define yourself won't work with -the ``$`` operator until you define one for them. Sometimes you just want to -debug the current value of a complex type without having to write its ``$`` -operator. You can use then the ``repr`` proc which works with any type and -even complex data graphs with cycles. The following example shows that even for -basic types there is a difference between the ``$`` and ``repr`` outputs: +As mentioned earlier, the built-in `$ `_ (stringify) operator +turns any basic type into a string, which you can then print to the screen +with the ``echo`` proc. However, advanced types, or types you may define +yourself won't work with the ``$`` operator until you define one for them. +Sometimes you just want to debug the current value of a complex type without +having to write its ``$`` operator. You can use then the `repr +`_ proc which works with any type and even complex data +graphs with cycles. The following example shows that even for basic types +there is a difference between the ``$`` and ``repr`` outputs: .. code-block:: nimrod var @@ -1087,9 +1093,10 @@ Operation Comment ``pred(x, n)`` returns the `n`'th predecessor of `x` ----------------- -------------------------------------------------------- -The ``inc dec succ pred`` operations can fail by raising an `EOutOfRange` or -`EOverflow` exception. (If the code has been compiled with the proper runtime -checks turned on.) +The `inc `_, `dec `_, `succ +`_ and `pred `_ operations can fail by +raising an `EOutOfRange` or `EOverflow` exception. (If the code has been +compiled with the proper runtime checks turned on.) Subranges @@ -1107,12 +1114,12 @@ to 5. Assigning any other value to a variable of type ``TSubrange`` is a compile-time or runtime error. Assignments from the base type to one of its subrange types (and vice versa) are allowed. -The ``system`` module defines the important ``natural`` type as -``range[0..high(int)]`` (``high`` returns the maximal value). Other programming -languages mandate the usage of unsigned integers for natural numbers. This is -often **wrong**: you don't want unsigned arithmetic (which wraps around) just -because the numbers cannot be negative. Nimrod's ``natural`` type helps to -avoid this common programming error. +The ``system`` module defines the important `Natural `_ +type as ``range[0..high(int)]`` (`high `_ returns the +maximal value). Other programming languages mandate the usage of unsigned +integers for natural numbers. This is often **wrong**: you don't want unsigned +arithmetic (which wraps around) just because the numbers cannot be negative. +Nimrod's ``Natural`` type helps to avoid this common programming error. Sets @@ -1145,8 +1152,9 @@ checks can be disabled via pragmas or invoking the compiler with the Arrays are value types, like any other Nimrod type. The assignment operator copies the whole array contents. -The built-in ``len`` proc returns the array's length. ``low(a)`` returns the -lowest valid index for the array `a` and ``high(a)`` the highest valid index. +The built-in `len `_ proc returns the array's +length. `low(a) `_ returns the lowest valid index for the +array `a` and `high(a) `_ the highest valid index. .. code-block:: nimrod type @@ -1218,13 +1226,14 @@ Sequences are similar to arrays but of dynamic length which may change during runtime (like strings). Since sequences are resizable they are always allocated on the heap and garbage collected. -Sequences are always indexed with an ``int`` starting at position 0. -The ``len``, ``low`` and ``high`` operations are available for sequences too. -The notation ``x[i]`` can be used to access the i-th element of ``x``. +Sequences are always indexed with an ``int`` starting at position 0. The `len +`_, `low `_ and `high +`_ operations are available for sequences too. The notation +``x[i]`` can be used to access the i-th element of ``x``. Sequences can be constructed by the array constructor ``[]`` in conjunction with the array to sequence operator ``@``. Another way to allocate space for -a sequence is to call the built-in ``newSeq`` procedure. +a sequence is to call the built-in `newSeq `_ procedure. A sequence may be passed to an openarray parameter. @@ -1245,10 +1254,11 @@ object on the heap, so there is a trade-off to be made here. The ``for`` statement can be used with one or two variables when used with a sequence. When you use the one variable form, the variable will hold the value provided by the sequence. The ``for`` statement is looping over the results -from the ``items()`` iterator from the `system `_ module. But if -you use the two variable form, the first variable will hold the index position -and the second variable will hold the value. Here the ``for`` statement is -looping over the results from the ``pairs()`` iterator from the `system +from the `items() `_ iterator from the `system +`_ module. But if you use the two variable form, the first +variable will hold the index position and the second variable will hold the +value. Here the ``for`` statement is looping over the results from the +`pairs() `_ iterator from the `system `_ module. Examples: .. code-block:: nimrod @@ -1269,12 +1279,13 @@ Open arrays ----------- **Note**: Openarrays can only be used for parameters. -Often fixed size arrays turn out to be too inflexible; procedures should -be able to deal with arrays of different sizes. The `openarray`:idx: type -allows this. Openarrays are always indexed with an ``int`` starting at -position 0. The ``len``, ``low`` and ``high`` operations are available -for open arrays too. Any array with a compatible base type can be passed to -an openarray parameter, the index type does not matter. +Often fixed size arrays turn out to be too inflexible; procedures should be +able to deal with arrays of different sizes. The `openarray`:idx: type allows +this. Openarrays are always indexed with an ``int`` starting at position 0. +The `len `_, `low `_ and `high +`_ operations are available for open arrays too. Any array +with a compatible base type can be passed to an openarray parameter, the index +type does not matter. The openarray type cannot be nested: multidimensional openarrays are not supported because this is seldom needed and cannot be done efficiently. @@ -1312,8 +1323,9 @@ type conversions in this context: # is transformed by the compiler to: myWriteln(stdout, [$123, $"def", $4.0]) -In this example ``$`` is applied to any argument that is passed to the -parameter ``a``. Note that ``$`` applied to strings is a nop. +In this example `$ `_ is applied to any argument that is passed +to the parameter ``a``. Note that `$ `_ applied to strings is a +nop. Slices @@ -1392,11 +1404,12 @@ having the same field types. Tuples can be *unpacked* during variable assignment (and only then!). This can be handy to assign directly the fields of the tuples to individually named -variables. An example of this is the ``splitFile`` proc from the `os module -`_ which returns the directory, name and extension of a path at the -same time. For tuple unpacking to work you have to use parenthesis around the -values you want to assign the unpacking to, otherwise you will be assigning the -same value to all the individual variables! Example: +variables. An example of this is the `splitFile `_ proc +from the `os module `_ which returns the directory, name and +extension of a path at the same time. For tuple unpacking to work you have to +use parenthesis around the values you want to assign the unpacking to, +otherwise you will be assigning the same value to all the individual +variables! Example: .. code-block:: nimrod From 8aa0be82d471c3ec24b8e798ea65748c67b0c5ce Mon Sep 17 00:00:00 2001 From: Grzegorz Adam Hankiewicz Date: Tue, 5 Aug 2014 16:44:27 +0200 Subject: [PATCH 096/234] Improves tut2.txt with more hyperlinks. --- doc/tut2.txt | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/doc/tut2.txt b/doc/tut2.txt index 1e23618e08..295d2e046b 100644 --- a/doc/tut2.txt +++ b/doc/tut2.txt @@ -23,11 +23,13 @@ features.** Pragmas ======= + Pragmas are Nimrod's method to give the compiler additional information/ -commands without introducing a massive number of new keywords. Pragmas are -enclosed in the special ``{.`` and ``.}`` curly dot brackets. This tutorial -does not cover pragmas. See the `manual `_ -or `user guide `_ for a description of the available pragmas. +commands without introducing a massive number of new keywords. Pragmas are +enclosed in the special ``{.`` and ``.}`` curly dot brackets. This tutorial +does not cover pragmas. See the `manual `_ or `user guide +`_ for a description of the available +pragmas. Object Oriented Programming @@ -421,9 +423,10 @@ the rest of the procedure - that is not within a ``finally`` clause - is not executed (if an exception occurs). If you need to *access* the actual exception object or message inside an -``except`` branch you can use the getCurrentException() and -getCurrentExceptionMsg() procs from the `system `_ module. -Example: +``except`` branch you can use the `getCurrentException() +`_ and `getCurrentExceptionMsg() +`_ procs from the `system `_ +module. Example: .. code-block:: nimrod try: @@ -663,8 +666,8 @@ statement: declareInNewScope(b, int) b = 42 # does not work, `b` is unknown -(The manual explains why the ``immediate`` pragma is needed for these -templates.) +(The `manual explains `_ why the +``immediate`` pragma is needed for these templates.) If there is a ``stmt`` parameter it should be the last in the template declaration. The reason is that statements can be passed to a template From 1daa54e5a2abaa74d3c574fc9c451fb52a1ccaa2 Mon Sep 17 00:00:00 2001 From: Grzegorz Adam Hankiewicz Date: Tue, 5 Aug 2014 17:07:43 +0200 Subject: [PATCH 097/234] Downgrades public module comments to private level. This avoids the weird concatenation in the final system.html file which doesn't make any sense. --- lib/system/atomics.nim | 2 +- lib/system/widestrs.nim | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/system/atomics.nim b/lib/system/atomics.nim index 43b3f0438f..82ec5dbdeb 100644 --- a/lib/system/atomics.nim +++ b/lib/system/atomics.nim @@ -7,7 +7,7 @@ # distribution, for details about the copyright. # -## Atomic operations for Nimrod. +# Atomic operations for Nimrod. {.push stackTrace:off.} const someGcc = defined(gcc) or defined(llvm_gcc) or defined(clang) diff --git a/lib/system/widestrs.nim b/lib/system/widestrs.nim index e2a5d87e90..e9673888c2 100644 --- a/lib/system/widestrs.nim +++ b/lib/system/widestrs.nim @@ -7,8 +7,8 @@ # distribution, for details about the copyright. # -## Nimrod support for C/C++'s `wide strings`:idx:. This is part of the system -## module! Do not import it directly! +# Nimrod support for C/C++'s `wide strings`:idx:. This is part of the system +# module! Do not import it directly! when not defined(NimString): {.error: "You must not import this module explicitly".} From f3d785b5cf7e06c06b5d1bb1d6af29bb9591d132 Mon Sep 17 00:00:00 2001 From: Grzegorz Adam Hankiewicz Date: Tue, 5 Aug 2014 17:59:28 +0200 Subject: [PATCH 098/234] Factors exception hierarchy into reusable fragment. The fragment with hyperlinks is included now from the system module. --- doc/exception_hierarchy_fragment.txt | 31 ++++ doc/tut2.txt | 34 +--- lib/system.nim | 248 +++++++++++++++++---------- 3 files changed, 187 insertions(+), 126 deletions(-) create mode 100644 doc/exception_hierarchy_fragment.txt diff --git a/doc/exception_hierarchy_fragment.txt b/doc/exception_hierarchy_fragment.txt new file mode 100644 index 0000000000..6ca68921f1 --- /dev/null +++ b/doc/exception_hierarchy_fragment.txt @@ -0,0 +1,31 @@ +* `E_Base `_ + * `EAccessViolation `_ + * `EArithmetic `_ + * `EDivByZero `_ + * `EOverflow `_ + * `EAssertionFailed `_ + * `EAsynch `_ + * `EControlC `_ + * `EDeadThread `_ + * `EFloatingPoint `_ + * `EFloatDivByZero `_ + * `EFloatInexact `_ + * `EFloatInvalidOp `_ + * `EFloatOverflow `_ + * `EFloatUnderflow `_ + * `EInvalidField `_ + * `EInvalidIndex `_ + * `EInvalidObjectAssignment `_ + * `EInvalidObjectConversion `_ + * `EInvalidValue `_ + * `EInvalidKey `_ + * `ENoExceptionToReraise `_ + * `EOutOfRange `_ + * `ESynch `_ + * `EOutOfMemory `_ + * `EResourceExhausted `_ + * `EStackOverflow `_ + * `ESystem `_ + * `EIO `_ + * `EOS `_ + * `EInvalidLibrary `_ diff --git a/doc/tut2.txt b/doc/tut2.txt index 295d2e046b..2f42bcefc5 100644 --- a/doc/tut2.txt +++ b/doc/tut2.txt @@ -443,39 +443,9 @@ Exception hierarchy If you want to create your own exceptions you can inherit from E_Base, but you can also inherit from one of the existing exceptions if they fit your purpose. -The exception tree is:: +The exception tree is: - * E_Base - * EAsynch - * EControlC - * ESynch - * ESystem - * EIO - * EOS - * EInvalidLibrary - * EResourceExhausted - * EOutOfMemory - * EStackOverflow - * EArithmetic - * EDivByZero - * EOverflow - * EAccessViolation - * EAssertionFailed - * EInvalidValue - * EInvalidKey - * EInvalidIndex - * EInvalidField - * EOutOfRange - * ENoExceptionToReraise - * EInvalidObjectAssignment - * EInvalidObjectConversion - * EFloatingPoint - * EFloatInvalidOp - * EFloatDivByZero - * EFloatOverflow - * EFloatUnderflow - * EFloatInexact - * EDeadThread +.. include:: exception_hierarchy_fragment.txt See the `system `_ module for a description of each exception. diff --git a/lib/system.nim b/lib/system.nim index d77b4fdee4..1cfa06057e 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -13,6 +13,21 @@ ## Each module implicitly imports the System module; it must not be listed ## explicitly. Because of this there cannot be a user-defined module named ## ``system``. +## +## Exception hierarchy +## =================== +## +## For visual convenience here is the exception inheritance hierarchy +## represented as a tree: +## +## .. include:: ../doc/exception_hierarchy_fragment.txt +## +## Module system +## ============= +## + +# That lonesome header above is to prevent :idx: entries from being mentioned +# in the global index as part of the previous header (Exception hierarchy). type int* {.magic: Int.} ## default integer type; bitwidth depends on @@ -301,9 +316,11 @@ type FWriteIO* = object of FIO ## Effect describing a write IO operation. FExecIO* = object of FIO ## Effect describing an executing IO operation. - E_Base* {.compilerproc.} = object of TObject ## base exception class; - ## each exception has to - ## inherit from `E_Base`. + E_Base* {.compilerproc.} = object of TObject ## \ + ## Base exception class. + ## + ## Each exception has to inherit from `E_Base`. See the full `exception + ## hierarchy`_. parent: ref E_Base ## parent exception (can be used as a stack) name: cstring ## The exception's name is its Nimrod identifier. ## This field is filled automatically in the @@ -313,99 +330,142 @@ type ## is bad style. trace: string - EAsynch* = object of E_Base ## Abstract exception class for - ## *asynchronous exceptions* (interrupts). - ## This is rarely needed: Most - ## exception types inherit from `ESynch` - ESynch* = object of E_Base ## Abstract exception class for - ## *synchronous exceptions*. Most exceptions - ## should be inherited (directly or indirectly) - ## from ESynch. - ESystem* = object of ESynch ## Abstract class for exceptions that the runtime - ## system raises. - EIO* = object of ESystem ## raised if an IO error occured. - EOS* = object of ESystem ## raised if an operating system service failed. + EAsynch* = object of E_Base ## \ + ## Abstract exception class for *asynchronous exceptions* (interrupts). + ## + ## This is rarely needed: most exception types inherit from `ESynch + ## <#ESynch>`_. See the full `exception hierarchy`_. + EControlC* = object of EAsynch ## \ + ## Raised for Ctrl+C key presses in console applications. + ## + ## See the full `exception hierarchy`_. + ESynch* = object of E_Base ## \ + ## Abstract exception class for *synchronous exceptions*. + ## + ## Most exceptions should be inherited (directly or indirectly) from + ## `ESynch` instead of from `EAsynch <#EAsynch>`_. See the full `exception + ## hierarchy`_. + ESystem* = object of ESynch ## \ + ## Abstract class for exceptions that the runtime system raises. + ## + ## See the full `exception hierarchy`_. + EIO* = object of ESystem ## \ + ## Raised if an IO error occured. + ## + ## See the full `exception hierarchy`_. + EOS* = object of ESystem ## \ + ## Raised if an operating system service failed. + ## + ## See the full `exception hierarchy`_. errorCode*: int32 ## OS-defined error code describing this error. - EInvalidLibrary* = object of EOS ## raised if a dynamic library - ## could not be loaded. - EResourceExhausted* = object of ESystem ## raised if a resource request - ## could not be fullfilled. - EArithmetic* = object of ESynch ## raised if any kind of arithmetic - ## error occured. - 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. + EInvalidLibrary* = object of EOS ## \ + ## Raised if a dynamic library could not be loaded. + ## + ## See the full `exception hierarchy`_. + EResourceExhausted* = object of ESystem ## \ + ## Raised if a resource request could not be fullfilled. + ## + ## See the full `exception hierarchy`_. + EArithmetic* = object of ESynch ## \ + ## Raised if any kind of arithmetic error occured. + ## + ## See the full `exception hierarchy`_. + EDivByZero* {.compilerproc.} = object of EArithmetic ## \ + ## Raised for runtime integer divide-by-zero errors. + ## + ## See the full `exception hierarchy`_. + EOverflow* {.compilerproc.} = object of EArithmetic ## \ + ## Raised for runtime integer overflows. + ## + ## This happens for calculations whose results are too large to fit in the + ## provided bits. See the full `exception hierarchy`_. + EAccessViolation* {.compilerproc.} = object of ESynch ## \ + ## Raised for invalid memory access errors + ## + ## See the full `exception hierarchy`_. + EAssertionFailed* {.compilerproc.} = object of ESynch ## \ + ## Raised when assertion is proved wrong. + ## + ## Usually the result of using the `assert() template <#assert>`_. See the + ## full `exception hierarchy`_. + EInvalidValue* = object of ESynch ## \ + ## Raised for string and object conversion errors. + EInvalidKey* = object of EInvalidValue ## \ + ## Raised if a key cannot be found in a table. + ## + ## Mostly used by the `tables `_ module, it can also be raised + ## by other collection modules like `sets `_ or `strtabs + ## `_. See the full `exception hierarchy`_. + EOutOfMemory* = object of ESystem ## \ + ## Raised for unsuccessful attempts to allocate memory. + ## + ## See the full `exception hierarchy`_. + EInvalidIndex* = object of ESynch ## \ + ## Raised if an array index is out of bounds. + ## + ## See the full `exception hierarchy`_. + EInvalidField* = object of ESynch ## \ + ## Raised if a record field is not accessible because its dicriminant's + ## value does not fit. + ## + ## See the full `exception hierarchy`_. + EOutOfRange* = object of ESynch ## \ + ## Raised if a range check error occurred. + ## + ## See the full `exception hierarchy`_. + EStackOverflow* = object of ESystem ## \ + ## Raised if the hardware stack used for subroutine calls overflowed. + ## + ## See the full `exception hierarchy`_. + ENoExceptionToReraise* = object of ESynch ## \ + ## Raised if there is no exception to reraise. + ## + ## See the full `exception hierarchy`_. + EInvalidObjectAssignment* = object of ESynch ## \ + ## Raised if an object gets assigned to its parent's object. + ## + ## See the full `exception hierarchy`_. + EInvalidObjectConversion* = object of ESynch ## \ + ## Raised if an object is converted to an incompatible object type. + ## + ## See the full `exception hierarchy`_. + EFloatingPoint* = object of ESynch ## \ + ## Base class for floating point exceptions. + ## + ## See the full `exception hierarchy`_. + EFloatInvalidOp* {.compilerproc.} = object of EFloatingPoint ## \ + ## Raised by invalid operations according to IEEE. + ## + ## Raised by ``0.0/0.0``, for example. See the full `exception + ## hierarchy`_. + EFloatDivByZero* {.compilerproc.} = object of EFloatingPoint ## \ + ## Raised by division by zero. + ## + ## Divisor is zero and dividend is a finite nonzero number. See the full + ## `exception hierarchy`_. + EFloatOverflow* {.compilerproc.} = object of EFloatingPoint ## \ + ## Raised for overflows. + ## + ## The operation produced a result that exceeds the range of the exponent. + ## See the full `exception hierarchy`_. + EFloatUnderflow* {.compilerproc.} = object of EFloatingPoint ## \ + ## Raised for underflows. + ## + ## The operation produced a result that is too small to be represented as a + ## normal number. See the full `exception hierarchy`_. + EFloatInexact* {.compilerproc.} = object of EFloatingPoint ## \ + ## Raised for inexact results. + ## + ## The operation produced a result that cannot be represented with infinite + ## precision -- for example: ``2.0 / 3.0, log(1.1)`` + ## + ## **NOTE**: Nimrod currently does not detect these! See the full + ## `exception hierarchy`_. + EDeadThread* = object of ESynch ## \ + ## Raised if it is attempted to send a message to a dead thread. + ## + ## See the full `exception hierarchy`_. - EAccessViolation* {.compilerproc.} = - object of ESynch ## the exception class for invalid memory access errors - - 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. - - EInvalidValue* = object of ESynch ## is the exception class for string - ## and object conversion errors. - EInvalidKey* = object of EInvalidValue ## is the exception class if a key - ## cannot be found in a table. - - EOutOfMemory* = object of ESystem ## is the exception class for - ## unsuccessful attempts to allocate - ## memory. - - 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 - ## occurred. - - EStackOverflow* = object of ESystem ## is raised if the hardware stack - ## used for subroutine calls overflowed. - - 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 - ## parent's object. - - EInvalidObjectConversion* = - object of ESynch ## is raised if an object is converted to an incompatible - ## object type. - - EFloatingPoint* = object of ESynch ## base class for floating point exceptions - EFloatInvalidOp* {.compilerproc.} = - object of EFloatingPoint ## Invalid operation according to IEEE: Raised by - ## 0.0/0.0, for example. - EFloatDivByZero* {.compilerproc.} = - object of EFloatingPoint ## Division by zero. Divisor is zero and dividend - ## is a finite nonzero number. - EFloatOverflow* {.compilerproc.} = - object of EFloatingPoint ## Overflow. Operation produces a result - ## that exceeds the range of the exponent - EFloatUnderflow* {.compilerproc.} = - object of EFloatingPoint ## Underflow. Operation produces a result - ## that is too small to be represented as - ## a normal number - EFloatInexact* {.compilerproc.} = - object of EFloatingPoint ## Inexact. Operation produces a result - ## that cannot be represented with infinite - ## precision -- for example, 2.0 / 3.0, log(1.1) - ## NOTE: Nimrod currently does not detect these! - EDeadThread* = - object of ESynch ## is raised if it is attempted to send a message to a - ## dead thread. - TResult* = enum Failure, Success proc sizeof*[T](x: T): Natural {.magic: "SizeOf", noSideEffect.} From 053b34d91d5dd7d57cb3878a1286b351c67b217c Mon Sep 17 00:00:00 2001 From: Araq Date: Tue, 5 Aug 2014 21:38:27 +0200 Subject: [PATCH 099/234] fixes yet another LL bug --- compiler/lambdalifting.nim | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/compiler/lambdalifting.nim b/compiler/lambdalifting.nim index bdad0e4711..6c650eee3b 100644 --- a/compiler/lambdalifting.nim +++ b/compiler/lambdalifting.nim @@ -843,8 +843,15 @@ proc transformOuterProc(o: POuterContext, n: PNode; it: TIter): PNode = # every local goes through the closure: #if not containsOrIncl(o.capturedVars, local.id): # addField(it.obj, local) - addUniqueField(it.obj, local) - return indirectAccess(newSymNode(it.closureParam), local, n.info) + if contains(o.capturedVars, local.id): + # change 'local' to 'closure.local', unless it's a 'byCopy' variable: + # if sfByCopy notin local.flags: + result = idNodeTableGet(o.localsToAccess, local) + assert result != nil, "cannot find: " & local.name.s + return result + else: + addUniqueField(it.obj, local) + return indirectAccess(newSymNode(it.closureParam), local, n.info) var closure = PEnv(idTableGet(o.lambdasToEnv, local)) if local.kind == skClosureIterator: From 3df553ef25699d975320eb6815f0a1492261b5b2 Mon Sep 17 00:00:00 2001 From: Araq Date: Tue, 5 Aug 2014 21:38:49 +0200 Subject: [PATCH 100/234] check there is only one deepCopy per type --- compiler/semstmts.nim | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 1d913dc009..5831850487 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -1020,7 +1020,10 @@ proc semOverride(c: PContext, s: PSym, n: PNode) = # the problem that pointers are structural types: let t = s.typ.sons[1].skipTypes(abstractInst).lastSon.skipTypes(abstractInst) if t.kind in {tyObject, tyDistinct, tyEnum}: - t.deepCopy = s + if t.deepCopy.isNil: t.deepCopy = s + else: + localError(n.info, errGenerated, + "cannot bind another 'deepCopy' to: " & typeToString(t)) else: localError(n.info, errGenerated, "cannot bind 'deepCopy' to: " & typeToString(t)) From 55250b3f36f403d0a8baf49c8d30e2290105d2b1 Mon Sep 17 00:00:00 2001 From: Araq Date: Tue, 5 Aug 2014 21:40:17 +0200 Subject: [PATCH 101/234] added debug output (but not active) --- compiler/ccgexprs.nim | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index d5b2ad33d5..ff262f1a60 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -1909,6 +1909,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) = of skVar, skForVar, skResult, skLet: if sfGlobal in sym.flags: genVarPrototype(p.module, sym) if sym.loc.r == nil or sym.loc.t == nil: + #echo "FAILED FOR PRCO ", p.prc.name.s internalError n.info, "expr: var not init " & sym.name.s & "_" & $sym.id if sfThread in sym.flags: accessThreadLocalVar(p, sym) From ca8135f34b30b5c9da62f6d55f6bc5726206535b Mon Sep 17 00:00:00 2001 From: Araq Date: Tue, 5 Aug 2014 21:45:58 +0200 Subject: [PATCH 102/234] added test --- tests/closure/tforum.nim | 44 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 tests/closure/tforum.nim diff --git a/tests/closure/tforum.nim b/tests/closure/tforum.nim new file mode 100644 index 0000000000..4f6a16ff7f --- /dev/null +++ b/tests/closure/tforum.nim @@ -0,0 +1,44 @@ +discard """ + output: '''asdas +processClient end +false +''' +""" + +type + PAsyncHttpServer = ref object + value: string + PFutureBase = ref object + callback: proc () {.closure.} + value: string + failed: bool + +proc accept(server: PAsyncHttpServer): PFutureBase = + new(result) + result.callback = proc () = + discard + server.value = "hahaha" + +proc processClient(): PFutureBase = + new(result) + +proc serve(server: PAsyncHttpServer): PFutureBase = + iterator serveIter(): PFutureBase {.closure.} = + echo server.value + while true: + var acceptAddrFut = server.accept() + yield acceptAddrFut + var fut = acceptAddrFut.value + + var f = processClient() + f.callback = + proc () = + echo("processClient end") + echo(f.failed) + yield f + var x = serveIter + for i in 0 .. 1: + result = x() + result.callback() + +discard serve(PAsyncHttpServer(value: "asdas")) From 1e8a9aead060d27099bdd8634cbab6b89ecd9995 Mon Sep 17 00:00:00 2001 From: Araq Date: Tue, 5 Aug 2014 21:54:39 +0200 Subject: [PATCH 103/234] fixes typos --- doc/spawn.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/spawn.txt b/doc/spawn.txt index ed500f3a5c..c5c96ecf8b 100644 --- a/doc/spawn.txt +++ b/doc/spawn.txt @@ -53,13 +53,13 @@ restrictions / changes: * ``spawn`` within a ``parallel`` section has special semantics. * Every location of the form ``a[i]`` and ``a[i..j]`` and ``dest`` where ``dest`` is part of the pattern ``dest = spawn f(...)`` has to be - provable disjoint. This is called the *disjoint check*. + provably disjoint. This is called the *disjoint check*. * Every other complex location ``loc`` that is used in a spawned proc (``spawn f(loc)``) has to be immutable for the duration of the ``parallel`` section. This is called the *immutability check*. Currently it is not specified what exactly "complex location" means. We need to make this an optimization! -* Every array access has to be provable within bounds. This is called +* Every array access has to be provably within bounds. This is called the *bounds check*. * Slices are optimized so that no copy is performed. This optimization is not yet performed for ordinary slices outside of a ``parallel`` section. Slices From 530d210c910c768a314cdb47bdf60d74fcbb141a Mon Sep 17 00:00:00 2001 From: Dwight Schauer Date: Tue, 5 Aug 2014 18:57:45 -0500 Subject: [PATCH 104/234] Added carriage return and linefeed check to os::parseCmdLine ti delimiting whitespace eating. --- lib/pure/os.nim | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/pure/os.nim b/lib/pure/os.nim index a70bfa7f10..44673d3e0f 100644 --- a/lib/pure/os.nim +++ b/lib/pure/os.nim @@ -1457,7 +1457,8 @@ proc parseCmdLine*(c: string): seq[string] {. var a = "" while true: setLen(a, 0) - while c[i] == ' ' or c[i] == '\t': inc(i) + # eat all delimiting whitespace + while c[i] == ' ' or c[i] == '\t' or c [i] == '\l' or c [i] == '\r' : inc(i) when defined(windows): # parse a single argument according to the above rules: if c[i] == '\0': break From a64d733029b1f8c76575f5d117399d587346b9cc Mon Sep 17 00:00:00 2001 From: Araq Date: Wed, 6 Aug 2014 09:54:23 +0200 Subject: [PATCH 105/234] some bugfixes for 'deepCopy' --- compiler/ccgexprs.nim | 11 ++++++----- lib/system/deepcopy.nim | 33 +++++++++++++++++++++++---------- 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index b4beb5a7e9..d480373d46 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -360,13 +360,13 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) = else: internalError("genAssignment: " & $ty.kind) proc genDeepCopy(p: BProc; dest, src: TLoc) = - var ty = skipTypes(dest.t, abstractRange) + var ty = skipTypes(dest.t, abstractVarRange) case ty.kind - of tyPtr, tyRef, tyString, tyProc, tyTuple, tyObject, tyArray, tyArrayConstr: + of tyPtr, tyRef, tyProc, tyTuple, tyObject, tyArray, tyArrayConstr: # XXX optimize this linefmt(p, cpsStmts, "#genericDeepCopy((void*)$1, (void*)$2, $3);$n", addrLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t)) - of tySequence: + of tySequence, tyString: linefmt(p, cpsStmts, "#genericSeqDeepCopy($1, $2, $3);$n", addrLoc(dest), rdLoc(src), genTypeInfo(p.module, dest.t)) of tyOpenArray, tyVarargs: @@ -1687,9 +1687,10 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) = expr(p, n, d) of mDeepCopy: var a, b: TLoc - initLocExpr(p, e.sons[1], a) + let x = if e[1].kind in {nkAddr, nkHiddenAddr}: e[1][0] else: e[1] + initLocExpr(p, x, a) initLocExpr(p, e.sons[2], b) - genDeepCopy(p, a, b) + genDeepCopy(p, a, b) else: internalError(e.info, "genMagicExpr: " & $op) proc genConstExpr(p: BProc, n: PNode): PRope diff --git a/lib/system/deepcopy.nim b/lib/system/deepcopy.nim index d3f9c5d7c9..5c10ef9eda 100644 --- a/lib/system/deepcopy.nim +++ b/lib/system/deepcopy.nim @@ -32,6 +32,12 @@ proc genericDeepCopyAux(dest, src: pointer, n: ptr TNimNode) {.gcsafe.} = genericDeepCopyAux(dest, src, m) of nkNone: sysAssert(false, "genericDeepCopyAux") +proc copyDeepString(src: NimString): NimString {.inline.} = + if src != nil: + result = rawNewString(src.space) + result.len = src.len + c_memcpy(result.data, src.data, (src.len + 1) * sizeof(char)) + proc genericDeepCopyAux(dest, src: pointer, mt: PNimType) = var d = cast[TAddress](dest) @@ -44,10 +50,10 @@ proc genericDeepCopyAux(dest, src: pointer, mt: PNimType) = if s2 == nil: unsureAsgnRef(x, s2) else: - unsureAsgnRef(x, copyString(cast[NimString](s2))) + unsureAsgnRef(x, copyDeepString(cast[NimString](s2))) of tySequence: var s2 = cast[PPointer](src)[] - var seq = cast[PGenericSeq](s2) + var seq = cast[PGenericSeq](s2) var x = cast[PPointer](dest) if s2 == nil: unsureAsgnRef(x, s2) @@ -76,25 +82,31 @@ proc genericDeepCopyAux(dest, src: pointer, mt: PNimType) = genericDeepCopyAux(cast[pointer](d +% i*% mt.base.size), cast[pointer](s +% i*% mt.base.size), mt.base) of tyRef: - var z: pointer if mt.base.deepCopy != nil: - z = mt.base.deepCopy(cast[PPointer](s)[]) + let z = mt.base.deepCopy(cast[PPointer](src)[]) + unsureAsgnRef(cast[PPointer](dest), z) else: # we modify the header of the cell temporarily; instead of the type # field we store a forwarding pointer. XXX This is bad when the cloning # fails due to OOM etc. - let x = usrToCell(cast[PPointer](s)[]) + let s2 = cast[PPointer](src)[] + if s2 == nil: + unsureAsgnRef(cast[PPointer](dest), s2) + return + let x = usrToCell(s2) let forw = cast[int](x.typ) if (forw and 1) == 1: # we stored a forwarding pointer, so let's use that: - z = cast[pointer](forw and not 1) + let z = cast[pointer](forw and not 1) + unsureAsgnRef(cast[PPointer](dest), z) else: let realType = x.typ - z = newObj(realType, realType.base.size) + let z = newObj(realType, realType.base.size) + + unsureAsgnRef(cast[PPointer](dest), z) x.typ = cast[PNimType](cast[int](z) or 1) - genericDeepCopyAux(dest, addr(z), realType) + genericDeepCopyAux(z, s2, realType.base) x.typ = realType - unsureAsgnRef(cast[PPointer](dest), z) of tyPtr: # no cycle check here, but also not really required if mt.base.deepCopy != nil: @@ -102,12 +114,13 @@ proc genericDeepCopyAux(dest, src: pointer, mt: PNimType) = else: cast[PPointer](dest)[] = cast[PPointer](s)[] else: - copyMem(dest, src, mt.size) # copy raw bits + copyMem(dest, src, mt.size) proc genericDeepCopy(dest, src: pointer, mt: PNimType) {.compilerProc.} = genericDeepCopyAux(dest, src, mt) proc genericSeqDeepCopy(dest, src: pointer, mt: PNimType) {.compilerProc.} = + # also invoked for 'string' var src = src genericDeepCopy(dest, addr(src), mt) From 278c265c6fe1a3bc9f1fb3c4895d3108134b8294 Mon Sep 17 00:00:00 2001 From: Grzegorz Adam Hankiewicz Date: Wed, 6 Aug 2014 21:19:20 +0200 Subject: [PATCH 106/234] Parallelizes documentation building. --- tools/nimweb.nim | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/tools/nimweb.nim b/tools/nimweb.nim index 9a83a5ccaa..d3c6d3fcd3 100644 --- a/tools/nimweb.nim +++ b/tools/nimweb.nim @@ -215,6 +215,11 @@ proc exec(cmd: string) = echo(cmd) if os.execShellCmd(cmd) != 0: quit("external program failed") +proc mexec(cmds: openarray[string]) = + ## Multiprocessor version of exec + if 0 != execProcesses(cmds, {poStdErrToStdOut, poParentStreams, poEchoCmd}): + quit("external program failed") + proc buildDocSamples(c: var TConfigData, destPath: string) = ## Special case documentation sample proc. ## @@ -229,18 +234,26 @@ proc buildDocSamples(c: var TConfigData, destPath: string) = proc buildDoc(c: var TConfigData, destPath: string) = # call nim for the documentation: + var + commands = newSeq[string](len(c.doc) + len(c.srcdoc) + len(c.srcdoc2)) + i = 0 for d in items(c.doc): - exec("nimrod rst2html $# --docSeeSrcUrl:$# -o:$# --index:on $#" % + commands[i] = "nimrod rst2html $# --docSeeSrcUrl:$# -o:$# --index:on $#" % [c.nimrodArgs, c.gitCommit, - destPath / changeFileExt(splitFile(d).name, "html"), d]) + destPath / changeFileExt(splitFile(d).name, "html"), d] + i.inc for d in items(c.srcdoc): - exec("nimrod doc $# --docSeeSrcUrl:$# -o:$# --index:on $#" % + commands[i] = "nimrod doc $# --docSeeSrcUrl:$# -o:$# --index:on $#" % [c.nimrodArgs, c.gitCommit, - destPath / changeFileExt(splitFile(d).name, "html"), d]) + destPath / changeFileExt(splitFile(d).name, "html"), d] + i.inc for d in items(c.srcdoc2): - exec("nimrod doc2 $# --docSeeSrcUrl:$# -o:$# --index:on $#" % + commands[i] = "nimrod doc2 $# --docSeeSrcUrl:$# -o:$# --index:on $#" % [c.nimrodArgs, c.gitCommit, - destPath / changeFileExt(splitFile(d).name, "html"), d]) + destPath / changeFileExt(splitFile(d).name, "html"), d] + i.inc + + mexec(commands) exec("nimrod buildIndex -o:$1/theindex.html $1" % [destPath]) proc buildPdfDoc(c: var TConfigData, destPath: string) = @@ -264,10 +277,12 @@ proc buildPdfDoc(c: var TConfigData, destPath: string) = proc buildAddDoc(c: var TConfigData, destPath: string) = # build additional documentation (without the index): - for d in items(c.webdoc): - exec("nimrod doc $# --docSeeSrcUrl:$# -o:$# $#" % + var commands = newSeq[string](c.webdoc.len) + for i, doc in pairs(c.webdoc): + commands[i] = "nimrod doc $# --docSeeSrcUrl:$# -o:$# $#" % [c.nimrodArgs, c.gitCommit, - destPath / changeFileExt(splitFile(d).name, "html"), d]) + destPath / changeFileExt(splitFile(doc).name, "html"), doc] + mexec(commands) proc parseNewsTitles(inputFilename: string): seq[TRssItem] = # parses the file for titles and returns them as TRssItem blocks. From c4ac8edce9fc04e9898b12f9935850a9469e5340 Mon Sep 17 00:00:00 2001 From: Clay Sweetser Date: Wed, 6 Aug 2014 20:42:43 -0400 Subject: [PATCH 107/234] Make device and file ID's public. Added the isHidden() proc --- lib/pure/os.nim | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/lib/pure/os.nim b/lib/pure/os.nim index a70bfa7f10..37d3417873 100644 --- a/lib/pure/os.nim +++ b/lib/pure/os.nim @@ -1860,12 +1860,12 @@ proc expandTilde*(path: string): string = when defined(Windows): type - DeviceId = int32 - FileId = int64 + DeviceId* = int32 + FileId* = int64 else: type - DeviceId = TDev - FileId = TIno + DeviceId* = TDev + FileId* = TIno type FileInfo* = object @@ -1908,6 +1908,7 @@ template rawToFormalFileInfo(rawInfo, formalInfo): expr = if (rawInfo.dwFileAttributes and FILE_ATTRIBUTE_REPARSE_POINT) != 0'i32: formalInfo.kind = succ(result.kind) + else: template checkAndIncludeMode(rawMode, formalMode: expr) = if (rawInfo.st_mode and rawMode) != 0'i32: @@ -1994,4 +1995,21 @@ proc getFileInfo*(path: string, followSymlink = true): FileInfo = osError(osLastError()) rawToFormalFileInfo(rawInfo, result) +proc isHidden*(path: string): bool = + ## Determines whether a given path is hidden or not. Returns false if the + ## file doesn't exist. On Windows, a file is hidden if the file's 'hidden' + ## attribute is set. On Unix-like systems, a file is hidden if it starts + ## with a '.' ." + when defined(Windows): + wrapUnary(attributes, getFileAttributesW, path) + if attributes != -1'i32: + result = (attributes and FILE_ATTRIBUTE_HIDDEN) != 0'i32 + else: + result = false + else: + if fileExists(path): + result = (path[0] == '.') + else: + result = false + {.pop.} From a41be8021beb648726c4527a0cd5deec59b1f405 Mon Sep 17 00:00:00 2001 From: def Date: Thu, 7 Aug 2014 21:32:17 +0200 Subject: [PATCH 108/234] Include string.h for strlen with cpp backend --- compiler/ccgexprs.nim | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index d480373d46..de62bc1c31 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -1286,6 +1286,7 @@ proc genArrayLen(p: BProc, e: PNode, d: var TLoc, op: TMagic) = if op == mHigh: unaryExpr(p, e, d, "($1Len0-1)") else: unaryExpr(p, e, d, "$1Len0") of tyCString: + if gCmd == cmdCompileToCpp: useStringh(p.module) if op == mHigh: unaryExpr(p, e, d, "(strlen($1)-1)") else: unaryExpr(p, e, d, "strlen($1)") of tyString, tySequence: From 7c3a28ae8b258415918fa9c852cbcb7d9fbde2b7 Mon Sep 17 00:00:00 2001 From: Clay Sweetser Date: Thu, 7 Aug 2014 17:52:37 -0400 Subject: [PATCH 109/234] Fix #1424 --- compiler/semexprs.nim | 2 ++ 1 file changed, 2 insertions(+) diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 7deb46af9a..c8d95886d5 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -185,6 +185,8 @@ proc isCastable(dst, src: PType): bool = # castableTypeKinds = {tyInt, tyPtr, tyRef, tyCstring, tyString, # tySequence, tyPointer, tyNil, tyOpenArray, # tyProc, tySet, tyEnum, tyBool, tyChar} + if dst.kind == tyOpenArray: + return false var dstSize, srcSize: BiggestInt dstSize = computeSize(dst) From 9bb739332f6941316f8927ef7e44f0c295ff47ea Mon Sep 17 00:00:00 2001 From: def Date: Fri, 8 Aug 2014 01:02:44 +0200 Subject: [PATCH 110/234] Also include string.h for strlen for C backend --- compiler/ccgexprs.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index de62bc1c31..8c0a2af539 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -1286,7 +1286,7 @@ proc genArrayLen(p: BProc, e: PNode, d: var TLoc, op: TMagic) = if op == mHigh: unaryExpr(p, e, d, "($1Len0-1)") else: unaryExpr(p, e, d, "$1Len0") of tyCString: - if gCmd == cmdCompileToCpp: useStringh(p.module) + useStringh(p.module) if op == mHigh: unaryExpr(p, e, d, "(strlen($1)-1)") else: unaryExpr(p, e, d, "strlen($1)") of tyString, tySequence: From bab41babeafc69a14f757f55e9a876315089f1e7 Mon Sep 17 00:00:00 2001 From: Grzegorz Adam Hankiewicz Date: Fri, 8 Aug 2014 02:21:13 +0200 Subject: [PATCH 111/234] Adds --parallelBuild to koch web and automatic reruns. Refs #1455. --- doc/koch.txt | 7 +++++++ tools/nimweb.nim | 31 +++++++++++++++++++++++++++---- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/doc/koch.txt b/doc/koch.txt index 0321518081..7be2be6d46 100644 --- a/doc/koch.txt +++ b/doc/koch.txt @@ -138,6 +138,13 @@ from rst to HTML. It also repeats the same operation but places the result in the ``web/upload`` which can be used to update the website at http://nimrod-lang.org. +By default the documentation will be built in parallel using the number of +available CPU cores. If any documentation build sub commands fail, they will +be rerun in serial fashion so that meaninful error output can be gathered for +inspection. The ``--parallelBuild:n`` switch or configuration option can be +used to force a specific number of parallel jobs or run everything serially +from the start (``n == 1``). + zip command ----------- diff --git a/tools/nimweb.nim b/tools/nimweb.nim index d3c6d3fcd3..d76c5e354a 100644 --- a/tools/nimweb.nim +++ b/tools/nimweb.nim @@ -21,6 +21,7 @@ type nimrodArgs: string gitCommit: string quotations: TTable[string, tuple[quote, author: string]] + numProcessors: int # Set by parallelBuild:n, only works for values > 0. TRssItem = object year, month, day, title: string @@ -42,6 +43,7 @@ proc initConfigData(c: var TConfigData) = c.ticker = "" c.vars = newStringTable(modeStyleInsensitive) c.gitCommit = "master" + c.numProcessors = countProcessors() # Attempts to obtain the git current commit. let (output, code) = execCmdEx("git log -n 1 --format=%H") if code == 0 and output.strip.len == 40: @@ -121,6 +123,12 @@ proc parseCmdLine(c: var TConfigData) = stdout.write(Version & "\n") quit(0) of "o", "output": c.outdir = val + of "parallelbuild": + try: + let num = parseInt(val) + if num != 0: c.numProcessors = num + except EInvalidValue: + quit("invalid numeric value for --parallelBuild") of "var": var idx = val.find('=') if idx < 0: quit("invalid command line") @@ -187,6 +195,12 @@ proc parseIniFile(c: var TConfigData) = of "srcdoc": addFiles(c.srcdoc, "lib", ".nim", split(v, {';'})) of "srcdoc2": addFiles(c.srcdoc2, "lib", ".nim", split(v, {';'})) of "webdoc": addFiles(c.webdoc, "lib", ".nim", split(v, {';'})) + of "parallelbuild": + try: + let num = parseInt(v) + if num != 0: c.numProcessors = num + except EInvalidValue: + quit("invalid numeric value for --parallelBuild in config") else: quit(errorStr(p, "unknown variable: " & k.key)) of "quotations": let vSplit = v.split('-') @@ -215,10 +229,19 @@ proc exec(cmd: string) = echo(cmd) if os.execShellCmd(cmd) != 0: quit("external program failed") -proc mexec(cmds: openarray[string]) = +proc sexec(cmds: openarray[string]) = + ## Serial queue wrapper around exec. + for cmd in cmds: exec(cmd) + +proc mexec(cmds: openarray[string], processors: int) = ## Multiprocessor version of exec + if processors < 2: + sexec(cmds) + return + if 0 != execProcesses(cmds, {poStdErrToStdOut, poParentStreams, poEchoCmd}): - quit("external program failed") + echo "external program failed, retrying serial work queue for logs!" + sexec(cmds) proc buildDocSamples(c: var TConfigData, destPath: string) = ## Special case documentation sample proc. @@ -253,7 +276,7 @@ proc buildDoc(c: var TConfigData, destPath: string) = destPath / changeFileExt(splitFile(d).name, "html"), d] i.inc - mexec(commands) + mexec(commands, c.numProcessors) exec("nimrod buildIndex -o:$1/theindex.html $1" % [destPath]) proc buildPdfDoc(c: var TConfigData, destPath: string) = @@ -282,7 +305,7 @@ proc buildAddDoc(c: var TConfigData, destPath: string) = commands[i] = "nimrod doc $# --docSeeSrcUrl:$# -o:$# $#" % [c.nimrodArgs, c.gitCommit, destPath / changeFileExt(splitFile(doc).name, "html"), doc] - mexec(commands) + mexec(commands, c.numProcessors) proc parseNewsTitles(inputFilename: string): seq[TRssItem] = # parses the file for titles and returns them as TRssItem blocks. From 057b53e1394962f43afba8e3e0a73f91bca68fe0 Mon Sep 17 00:00:00 2001 From: Araq Date: Fri, 8 Aug 2014 02:24:19 +0200 Subject: [PATCH 112/234] 'lambda' is no keyword anymore --- compiler/lexer.nim | 4 ++-- compiler/renderer.nim | 2 +- compiler/wordrecg.nim | 4 ++-- doc/keywords.txt | 2 +- lib/packages/docutils/highlite.nim | 2 +- web/news.txt | 1 + 6 files changed, 8 insertions(+), 7 deletions(-) diff --git a/compiler/lexer.nim b/compiler/lexer.nim index 0e4dfc2ac9..ea51a13994 100644 --- a/compiler/lexer.nim +++ b/compiler/lexer.nim @@ -40,7 +40,7 @@ type tkFinally, tkFor, tkFrom, tkGeneric, tkIf, tkImport, tkIn, tkInclude, tkInterface, tkIs, tkIsnot, tkIterator, - tkLambda, tkLet, + tkLet, tkMacro, tkMethod, tkMixin, tkMod, tkNil, tkNot, tkNotin, tkObject, tkOf, tkOr, tkOut, tkProc, tkPtr, tkRaise, tkRef, tkReturn, tkShl, tkShr, tkStatic, @@ -75,7 +75,7 @@ const "elif", "else", "end", "enum", "except", "export", "finally", "for", "from", "generic", "if", "import", "in", "include", "interface", "is", "isnot", "iterator", - "lambda", "let", + "let", "macro", "method", "mixin", "mod", "nil", "not", "notin", "object", "of", "or", "out", "proc", "ptr", "raise", "ref", "return", diff --git a/compiler/renderer.nim b/compiler/renderer.nim index 0b1312ccc8..c97b2f3216 100644 --- a/compiler/renderer.nim +++ b/compiler/renderer.nim @@ -925,7 +925,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) = of nkCheckedFieldExpr, nkHiddenAddr, nkHiddenDeref: gsub(g, n.sons[0]) of nkLambda: - putWithSpace(g, tkLambda, "proc") + putWithSpace(g, tkProc, "proc") gsub(g, n.sons[paramsPos]) gsub(g, n.sons[pragmasPos]) put(g, tkSpaces, Space) diff --git a/compiler/wordrecg.nim b/compiler/wordrecg.nim index c0550f702b..96056eb6f3 100644 --- a/compiler/wordrecg.nim +++ b/compiler/wordrecg.nim @@ -27,7 +27,7 @@ type wContinue, wConverter, wDiscard, wDistinct, wDiv, wDo, wElif, wElse, wEnd, wEnum, wExcept, wExport, wFinally, wFor, wFrom, wGeneric, wIf, wImport, wIn, - wInclude, wInterface, wIs, wIsnot, wIterator, wLambda, wLet, + wInclude, wInterface, wIs, wIsnot, wIterator, wLet, wMacro, wMethod, wMixin, wMod, wNil, wNot, wNotin, wObject, wOf, wOr, wOut, wProc, wPtr, wRaise, wRef, wReturn, wShl, wShr, wStatic, wTemplate, wTry, wTuple, wType, wUsing, wVar, @@ -107,7 +107,7 @@ const "elif", "else", "end", "enum", "except", "export", "finally", "for", "from", "generic", "if", "import", "in", "include", "interface", "is", "isnot", "iterator", - "lambda", "let", + "let", "macro", "method", "mixin", "mod", "nil", "not", "notin", "object", "of", "or", "out", "proc", "ptr", "raise", "ref", "return", diff --git a/doc/keywords.txt b/doc/keywords.txt index 60b1003980..a43b35475b 100644 --- a/doc/keywords.txt +++ b/doc/keywords.txt @@ -6,7 +6,7 @@ elif else end enum except export finally for from generic if import in include interface is isnot iterator -lambda let +let macro method mixin mod nil not notin object of or out diff --git a/lib/packages/docutils/highlite.nim b/lib/packages/docutils/highlite.nim index 80fbf3a51b..ff371f4e17 100644 --- a/lib/packages/docutils/highlite.nim +++ b/lib/packages/docutils/highlite.nim @@ -50,7 +50,7 @@ const "break", "case", "cast", "const", "continue", "converter", "discard", "distinct", "div", "do", "elif", "else", "end", "enum", "except", "export", "finally", "for", "from", "generic", "if", "import", "in", "include", - "interface", "is", "isnot", "iterator", "lambda", "let", "macro", "method", + "interface", "is", "isnot", "iterator", "let", "macro", "method", "mixin", "mod", "nil", "not", "notin", "object", "of", "or", "out", "proc", "ptr", "raise", "ref", "return", "shl", "shr", "static", "template", "try", "tuple", "type", "using", "var", "when", "while", "with", diff --git a/web/news.txt b/web/news.txt index 3aca10692c..20e2412212 100644 --- a/web/news.txt +++ b/web/news.txt @@ -22,6 +22,7 @@ News of the new ``TUri`` type in the ``uri`` module. - The ``destructor`` pragma has been deprecated. Use the ``override`` pragma instead. The destructor's name has to be ``destroy`` now. + - ``lambda`` is not a keyword anymore. Language Additions ------------------ From 68accb53c4b7bd6740bad21c21bcc633a745874a Mon Sep 17 00:00:00 2001 From: Araq Date: Fri, 8 Aug 2014 02:25:07 +0200 Subject: [PATCH 113/234] setMaxPoolSize improvements --- lib/pure/concurrency/threadpool.nim | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/lib/pure/concurrency/threadpool.nim b/lib/pure/concurrency/threadpool.nim index fd1041918d..3c636d1ce7 100644 --- a/lib/pure/concurrency/threadpool.nim +++ b/lib/pure/concurrency/threadpool.nim @@ -134,7 +134,7 @@ proc await*(fv: FlowVarBase) = proc finished(fv: FlowVarBase) = doAssert fv.ai.isNil, "flowVar is still attached to an 'awaitAny'" # we have to protect against the rare cases where the owner of the flowVar - # simply disregards the flowVar and yet the "flowVarr" has not yet written + # simply disregards the flowVar and yet the "flowVar" has not yet written # anything to it: await(fv) if fv.data.isNil: return @@ -207,6 +207,7 @@ proc `^`*[T](fv: FlowVar[T]): T = ## blocks until the value is available and then returns this value. await(fv) when T is string or T is seq: + # XXX closures? deepCopy? result = cast[T](fv.data) else: result = fv.blob @@ -264,6 +265,10 @@ proc slave(w: ptr Worker) {.thread.} = w.shutdown = false atomicDec currentPoolSize +var + workers: array[MaxThreadPoolSize, TThread[ptr Worker]] + workersData: array[MaxThreadPoolSize, Worker] + proc setMinPoolSize*(size: range[1..MaxThreadPoolSize]) = ## sets the minimal thread pool size. The default value of this is 4. minPoolSize = size @@ -272,10 +277,10 @@ proc setMaxPoolSize*(size: range[1..MaxThreadPoolSize]) = ## sets the minimal thread pool size. The default value of this ## is ``MaxThreadPoolSize``. maxPoolSize = size - -var - workers: array[MaxThreadPoolSize, TThread[ptr Worker]] - workersData: array[MaxThreadPoolSize, Worker] + if currentPoolSize > maxPoolSize: + for i in maxPoolSize..currentPoolSize-1: + let w = addr(workersData[i]) + w.shutdown = true proc activateThread(i: int) {.noinline.} = workersData[i].taskArrived = createCondVar() From 32197b7a130a7abb188cd2b2d386272571396c65 Mon Sep 17 00:00:00 2001 From: Araq Date: Fri, 8 Aug 2014 02:26:56 +0200 Subject: [PATCH 114/234] fixes #1456 --- lib/system/deepcopy.nim | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/lib/system/deepcopy.nim b/lib/system/deepcopy.nim index 5c10ef9eda..36ceb9ef91 100644 --- a/lib/system/deepcopy.nim +++ b/lib/system/deepcopy.nim @@ -93,20 +93,27 @@ proc genericDeepCopyAux(dest, src: pointer, mt: PNimType) = if s2 == nil: unsureAsgnRef(cast[PPointer](dest), s2) return - let x = usrToCell(s2) - let forw = cast[int](x.typ) - if (forw and 1) == 1: - # we stored a forwarding pointer, so let's use that: - let z = cast[pointer](forw and not 1) - unsureAsgnRef(cast[PPointer](dest), z) + when defined(usrToCell): + # unfortunately we only have cycle detection for our native GCs. + let x = usrToCell(s2) + let forw = cast[int](x.typ) + if (forw and 1) == 1: + # we stored a forwarding pointer, so let's use that: + let z = cast[pointer](forw and not 1) + unsureAsgnRef(cast[PPointer](dest), z) + else: + let realType = x.typ + let z = newObj(realType, realType.base.size) + + unsureAsgnRef(cast[PPointer](dest), z) + x.typ = cast[PNimType](cast[int](z) or 1) + genericDeepCopyAux(z, s2, realType.base) + x.typ = realType else: let realType = x.typ - let z = newObj(realType, realType.base.size) - + let z = newObj(realType, realType.base.size) unsureAsgnRef(cast[PPointer](dest), z) - x.typ = cast[PNimType](cast[int](z) or 1) - genericDeepCopyAux(z, s2, realType.base) - x.typ = realType + genericDeepCopyAux(z, s2, realType.base) of tyPtr: # no cycle check here, but also not really required if mt.base.deepCopy != nil: From 0914b489b3a792b3cc482712b63cdb303b4210f0 Mon Sep 17 00:00:00 2001 From: Araq Date: Fri, 8 Aug 2014 02:28:26 +0200 Subject: [PATCH 115/234] 'parallel' statement works again --- compiler/ccgexprs.nim | 4 +++- compiler/lowerings.nim | 10 ++++------ compiler/semexprs.nim | 2 +- compiler/semparallel.nim | 1 - 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index d480373d46..a2fe9be418 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -1922,7 +1922,9 @@ proc expr(p: BProc, n: PNode, d: var TLoc) = putLocIntoDest(p, d, sym.loc) of skTemp: if sym.loc.r == nil or sym.loc.t == nil: - internalError(n.info, "expr: temp not init " & sym.name.s) + #echo "FAILED FOR PRCO ", p.prc.name.s + #echo renderTree(p.prc.ast, {renderIds}) + internalError(n.info, "expr: temp not init " & sym.name.s & "_" & $sym.id) putLocIntoDest(p, d, sym.loc) of skParam: if sym.loc.r == nil or sym.loc.t == nil: diff --git a/compiler/lowerings.nim b/compiler/lowerings.nim index 1f1a7647b4..4050bb9b44 100644 --- a/compiler/lowerings.nim +++ b/compiler/lowerings.nim @@ -218,7 +218,6 @@ proc addLocalVar(varSection, varInit: PNode; owner: PSym; typ: PType; deepCopyCall.sons[0] = newSymNode(createMagic("deepCopy", mDeepCopy)) deepCopyCall.sons[1] = newSymNode(result) deepCopyCall.sons[2] = v - deepCopyCall.typ = typ varInit.add deepCopyCall discard """ @@ -257,10 +256,10 @@ proc createWrapperProc(f: PNode; threadParam, argsParam: PSym; var body = newNodeI(nkStmtList, f.info) var threadLocalBarrier: PSym if barrier != nil: - var varSection = newNodeI(nkVarSection, barrier.info) - threadLocalBarrier = addLocalVar(varSection, nil, argsParam.owner, + var varSection2 = newNodeI(nkVarSection, barrier.info) + threadLocalBarrier = addLocalVar(varSection2, nil, argsParam.owner, barrier.typ, barrier) - body.add varSection + body.add varSection2 body.add callCodeGenProc("barrierEnter", threadLocalBarrier.newSymNode) var threadLocalProm: PSym if spawnKind == srByVar: @@ -268,8 +267,7 @@ proc createWrapperProc(f: PNode; threadParam, argsParam: PSym; elif fv != nil: internalAssert fv.typ.kind == tyGenericInst threadLocalProm = addLocalVar(varSection, nil, argsParam.owner, fv.typ, fv) - if barrier == nil: - body.add varSection + body.add varSection body.add varInit if fv != nil and spawnKind != srByVar: # generate: diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 7deb46af9a..d040675fa1 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -592,7 +592,7 @@ proc analyseIfAddressTakenInCall(c: PContext, n: PNode) = const FakeVarParams = {mNew, mNewFinalize, mInc, ast.mDec, mIncl, mExcl, mSetLengthStr, mSetLengthSeq, mAppendStrCh, mAppendStrStr, mSwap, - mAppendSeqElem, mNewSeq, mReset, mShallowCopy} + mAppendSeqElem, mNewSeq, mReset, mShallowCopy, mDeepCopy} # get the real type of the callee # it may be a proc var with a generic alias type, so we skip over them diff --git a/compiler/semparallel.nim b/compiler/semparallel.nim index c594a47883..2ad7ef3416 100644 --- a/compiler/semparallel.nim +++ b/compiler/semparallel.nim @@ -462,4 +462,3 @@ proc liftParallel*(owner: PSym; n: PNode): PNode = result.add callCodeGenProc("openBarrier", barrier) result.add transformSpawn(owner, body, barrier) result.add callCodeGenProc("closeBarrier", barrier) - From abf511245a4c69af5745ba99e6e69527a347dbf9 Mon Sep 17 00:00:00 2001 From: Araq Date: Fri, 8 Aug 2014 09:54:43 +0200 Subject: [PATCH 116/234] nice error message --- lib/pure/concurrency/threadpool.nim | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/pure/concurrency/threadpool.nim b/lib/pure/concurrency/threadpool.nim index 3c636d1ce7..e0a2ac6782 100644 --- a/lib/pure/concurrency/threadpool.nim +++ b/lib/pure/concurrency/threadpool.nim @@ -9,6 +9,9 @@ ## Implements Nimrod's 'spawn'. +when not compileOption("threads"): + {.error: "Threadpool requires --threads:on option.".} + import cpuinfo, cpuload, locks {.push stackTrace:off.} From fd086abb43d606188920c841bcd4abbed770e7d6 Mon Sep 17 00:00:00 2001 From: Araq Date: Fri, 8 Aug 2014 09:55:19 +0200 Subject: [PATCH 117/234] fixes #1456 --- lib/system/deepcopy.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/system/deepcopy.nim b/lib/system/deepcopy.nim index 36ceb9ef91..bd8d005275 100644 --- a/lib/system/deepcopy.nim +++ b/lib/system/deepcopy.nim @@ -110,7 +110,7 @@ proc genericDeepCopyAux(dest, src: pointer, mt: PNimType) = genericDeepCopyAux(z, s2, realType.base) x.typ = realType else: - let realType = x.typ + let realType = mt let z = newObj(realType, realType.base.size) unsureAsgnRef(cast[PPointer](dest), z) genericDeepCopyAux(z, s2, realType.base) From 7a09b3b57b6e715e4bca492904d26341d2f91ce9 Mon Sep 17 00:00:00 2001 From: Clay Sweetser Date: Fri, 8 Aug 2014 17:22:50 -0400 Subject: [PATCH 118/234] Fix #1424 some more --- compiler/semexprs.nim | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index c8d95886d5..14129332cc 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -185,19 +185,23 @@ proc isCastable(dst, src: PType): bool = # castableTypeKinds = {tyInt, tyPtr, tyRef, tyCstring, tyString, # tySequence, tyPointer, tyNil, tyOpenArray, # tyProc, tySet, tyEnum, tyBool, tyChar} - if dst.kind == tyOpenArray: + if skipTypes(dst, abstractInst-{tyOpenArray}).kind == tyOpenArray: return false var dstSize, srcSize: BiggestInt dstSize = computeSize(dst) srcSize = computeSize(src) if dstSize < 0: + echo 'a' result = false elif srcSize < 0: + echo 'b' result = false elif not typeAllowed(dst, skParam): + echo 'c' result = false else: + echo 'd' result = (dstSize >= srcSize) or (skipTypes(dst, abstractInst).kind in IntegralTypes) or (skipTypes(src, abstractInst-{tyTypeDesc}).kind in IntegralTypes) From 4f5f98f0b1693a221bd3a2087bddf7e6ac350387 Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Sat, 9 Aug 2014 17:13:22 +0100 Subject: [PATCH 119/234] Fixes incorrect async exception handling. Adds sleepAsync. The tasyncexceptions test has been added which tests for this incorrect exception handling behaviour. The problem was that the exception was raised inside a callback which was called from a previously finished async procedure. This caused a "Future already finished" error. The fix was to simply reraise the exception if the retFutureSym is already finished. sleepAsync was added to help with the reproduction of this test. It should also be useful for users however. Finally some debug information was added to futures to help with future bugs. --- lib/pure/asyncdispatch.nim | 147 +++++++++++++++++++++---------- lib/pure/asynchttpserver.nim | 2 + lib/pure/asyncnet.nim | 4 +- tests/async/tasyncexceptions.nim | 38 ++++++++ 4 files changed, 141 insertions(+), 50 deletions(-) create mode 100644 tests/async/tasyncexceptions.nim diff --git a/lib/pure/asyncdispatch.nim b/lib/pure/asyncdispatch.nim index d410f8ce16..6339232f8e 100644 --- a/lib/pure/asyncdispatch.nim +++ b/lib/pure/asyncdispatch.nim @@ -9,7 +9,7 @@ include "system/inclrtl" -import os, oids, tables, strutils, macros +import os, oids, tables, strutils, macros, times import rawsockets, net @@ -41,27 +41,40 @@ type cb: proc () {.closure,gcsafe.} finished: bool error*: ref EBase - stackTrace: string ## For debugging purposes only. + when defined(debug): + stackTrace: string ## For debugging purposes only. + id: int + fromProc: string PFuture*[T] = ref object of PFutureBase value: T -proc newFuture*[T](): PFuture[T] = +var currentID* = 0 +proc newFuture*[T](fromProc: string = "unspecified"): PFuture[T] = ## Creates a new future. + ## + ## Specifying ``fromProc``, which is a string specifying the name of the proc + ## that this future belongs to, is a good habit as it helps with debugging. new(result) result.finished = false - result.stackTrace = getStackTrace() + when defined(debug): + result.stackTrace = getStackTrace() + result.id = currentID + result.fromProc = fromProc + currentID.inc() proc checkFinished[T](future: PFuture[T]) = - if future.finished: - echo("<----->") - echo(future.stackTrace) - echo("-----") - when T is string: - echo("Contents: ", future.value.repr) - echo("<----->") - echo("Future already finished, cannot finish twice.") - assert false + when defined(debug): + if future.finished: + echo("<-----> ", future.id, " ", future.fromProc) + echo(future.stackTrace) + echo("-----") + when T is string: + echo("Contents: ", future.value.repr) + echo("<----->") + echo("Future already finished, cannot finish twice.") + echo getStackTrace() + assert false proc complete*[T](future: PFuture[T], val: T) = ## Completes ``future`` with value ``val``. @@ -121,7 +134,8 @@ proc read*[T](future: PFuture[T]): T = ## ## If the result of the future is an error then that error will be raised. if future.finished: - if future.error != nil: raise future.error + if future.error != nil: + raise future.error when T isnot void: return future.value else: @@ -150,7 +164,21 @@ proc asyncCheck*[T](future: PFuture[T]) = ## This should be used instead of ``discard`` to discard void futures. future.callback = proc () = - if future.failed: raise future.error + if future.failed: + raise future.error + +type + PDispatcherBase = ref object of PObject + timers: seq[tuple[finishAt: float, fut: PFuture[void]]] + +proc processTimers(p: PDispatcherBase) = + var oldTimers = p.timers + p.timers = @[] + for t in oldTimers: + if epochTime() >= t.finishAt: + t.fut.complete() + else: + p.timers.add(t) when defined(windows) or defined(nimdoc): import winlean, sets, hashes @@ -162,7 +190,7 @@ when defined(windows) or defined(nimdoc): cb: proc (sock: TAsyncFD, bytesTransferred: DWORD, errcode: TOSErrorCode) {.closure,gcsafe.} - PDispatcher* = ref object + PDispatcher* = ref object of PDispatcherBase ioPort: THandle handles: TSet[TAsyncFD] @@ -181,6 +209,7 @@ when defined(windows) or defined(nimdoc): new result result.ioPort = CreateIOCompletionPort(INVALID_HANDLE_VALUE, 0, 0, 1) result.handles = initSet[TAsyncFD]() + result.timers = @[] var gDisp{.threadvar.}: PDispatcher ## Global dispatcher proc getGlobalDispatcher*(): PDispatcher = @@ -207,8 +236,9 @@ when defined(windows) or defined(nimdoc): proc poll*(timeout = 500) = ## Waits for completion events and processes them. let p = getGlobalDispatcher() - if p.handles.len == 0: - raise newException(EInvalidValue, "No handles registered in dispatcher.") + if p.handles.len == 0 and p.timers.len == 0: + raise newException(EInvalidValue, + "No handles or timers registered in dispatcher.") let llTimeout = if timeout == -1: winlean.INFINITE @@ -242,6 +272,9 @@ when defined(windows) or defined(nimdoc): discard else: osError(errCode) + # Timer processing. + processTimers(p) + var connectExPtr: pointer = nil var acceptExPtr: pointer = nil var getAcceptExSockAddrsPtr: pointer = nil @@ -314,7 +347,7 @@ when defined(windows) or defined(nimdoc): ## Returns a ``PFuture`` which will complete when the connection succeeds ## or an error occurs. verifyPresence(socket) - var retFuture = newFuture[void]() + var retFuture = newFuture[void]("connect") # Apparently ``ConnectEx`` expects the socket to be initially bound: var saddr: Tsockaddr_in saddr.sin_family = int16(toInt(af)) @@ -384,7 +417,7 @@ when defined(windows) or defined(nimdoc): # '\0' in the message currently signifies a socket disconnect. Who # knows what will happen when someone sends that to our socket. verifyPresence(socket) - var retFuture = newFuture[string]() + var retFuture = newFuture[string]("recv") var dataBuf: TWSABuf dataBuf.buf = cast[cstring](alloc0(size)) dataBuf.len = size @@ -459,7 +492,7 @@ when defined(windows) or defined(nimdoc): ## Sends ``data`` to ``socket``. The returned future will complete once all ## data has been sent. verifyPresence(socket) - var retFuture = newFuture[void]() + var retFuture = newFuture[void]("send") var dataBuf: TWSABuf dataBuf.buf = data # since this is not used in a callback, this is fine @@ -502,7 +535,7 @@ when defined(windows) or defined(nimdoc): ## ## The resulting client socket is automatically registered to dispatcher. verifyPresence(socket) - var retFuture = newFuture[tuple[address: string, client: TAsyncFD]]() + var retFuture = newFuture[tuple[address: string, client: TAsyncFD]]("acceptAddr") var clientSock = newRawSocket() if clientSock == osInvalidSocket: osError(osLastError()) @@ -614,6 +647,7 @@ else: proc newDispatcher*(): PDispatcher = new result result.selector = newSelector() + result.timers = @[] var gDisp{.threadvar.}: PDispatcher ## Global dispatcher proc getGlobalDispatcher*(): PDispatcher = @@ -693,6 +727,8 @@ else: else: # FD no longer a part of the selector. Likely been closed # (e.g. socket disconnected). + + processTimers(p) proc connect*(socket: TAsyncFD, address: string, port: TPort, af = AF_INET): PFuture[void] = @@ -814,11 +850,19 @@ else: addRead(socket, cb) return retFuture +proc sleepAsync*(ms: int): PFuture[void] = + ## Suspends the execution of the current async procedure for the next + ## ``ms`` miliseconds. + var retFuture = newFuture[void]("sleepAsync") + let p = getGlobalDispatcher() + p.timers.add((epochTime() + (ms / 1000), retFuture)) + return retFuture + proc accept*(socket: TAsyncFD): PFuture[TAsyncFD] = ## Accepts a new connection. Returns a future containing the client socket ## corresponding to that connection. ## The future will complete when the connection is successfully accepted. - var retFut = newFuture[TAsyncFD]() + var retFut = newFuture[TAsyncFD]("accept") var fut = acceptAddr(socket) fut.callback = proc (future: PFuture[tuple[address: string, client: TAsyncFD]]) = @@ -845,11 +889,16 @@ template createCb*(retFutureSym, iteratorNameSym, else: next.callback = cb except: - retFutureSym.fail(getCurrentException()) + if retFutureSym.finished: + # Take a look at tasyncexceptions for the bug which this fixes. + # That test explains it better than I can here. + raise + else: + retFutureSym.fail(getCurrentException()) cb() #{.pop.} proc generateExceptionCheck(futSym, - exceptBranch, rootReceiver: PNimrodNode): PNimrodNode {.compileTime.} = + exceptBranch, rootReceiver, fromNode: PNimrodNode): PNimrodNode {.compileTime.} = if exceptBranch == nil: result = rootReceiver else: @@ -869,20 +918,21 @@ proc generateExceptionCheck(futSym, ) ) ) - let elseNode = newNimNode(nnkElse) - elseNode.add newNimNode(nnkStmtList) + let elseNode = newNimNode(nnkElse, fromNode) + elseNode.add newNimNode(nnkStmtList, fromNode) elseNode[0].add rootReceiver result.add elseNode template createVar(result: var PNimrodNode, futSymName: string, asyncProc: PNimrodNode, - valueReceiver, rootReceiver: expr) = - result = newNimNode(nnkStmtList) + valueReceiver, rootReceiver: expr, + fromNode: PNimrodNode) = + result = newNimNode(nnkStmtList, fromNode) var futSym = genSym(nskVar, "future") result.add newVarStmt(futSym, asyncProc) # -> var future = y - result.add newNimNode(nnkYieldStmt).add(futSym) # -> yield future + result.add newNimNode(nnkYieldStmt, fromNode).add(futSym) # -> yield future valueReceiver = newDotExpr(futSym, newIdentNode("read")) # -> future.read - result.add generateExceptionCheck(futSym, exceptBranch, rootReceiver) + result.add generateExceptionCheck(futSym, exceptBranch, rootReceiver, fromNode) proc processBody(node, retFutureSym: PNimrodNode, subTypeIsVoid: bool, @@ -891,7 +941,7 @@ proc processBody(node, retFutureSym: PNimrodNode, result = node case node.kind of nnkReturnStmt: - result = newNimNode(nnkStmtList) + result = newNimNode(nnkStmtList, node) if node[0].kind == nnkEmpty: if not subtypeIsVoid: result.add newCall(newIdentNode("complete"), retFutureSym, @@ -902,19 +952,19 @@ proc processBody(node, retFutureSym: PNimrodNode, result.add newCall(newIdentNode("complete"), retFutureSym, node[0].processBody(retFutureSym, subtypeIsVoid, exceptBranch)) - result.add newNimNode(nnkReturnStmt).add(newNilLit()) + result.add newNimNode(nnkReturnStmt, node).add(newNilLit()) return # Don't process the children of this return stmt of nnkCommand: if node[0].kind == nnkIdent and node[0].ident == !"await": case node[1].kind of nnkIdent: # await x - result = newNimNode(nnkYieldStmt).add(node[1]) # -> yield x + result = newNimNode(nnkYieldStmt, node).add(node[1]) # -> yield x of nnkCall: # await foo(p, x) var futureValue: PNimrodNode result.createVar("future" & $node[1][0].toStrLit, node[1], futureValue, - futureValue) + futureValue, node) else: error("Invalid node kind in 'await', got: " & $node[1].kind) elif node[1].kind == nnkCommand and node[1][0].kind == nnkIdent and @@ -922,7 +972,7 @@ proc processBody(node, retFutureSym: PNimrodNode, # foo await x var newCommand = node result.createVar("future" & $node[0].toStrLit, node[1][1], newCommand[1], - newCommand) + newCommand, node) of nnkVarSection, nnkLetSection: case node[0][2].kind @@ -931,7 +981,7 @@ proc processBody(node, retFutureSym: PNimrodNode, # var x = await y var newVarSection = node # TODO: Should this use copyNimNode? result.createVar("future" & $node[0][0].ident, node[0][2][1], - newVarSection[0][2], newVarSection) + newVarSection[0][2], newVarSection, node) else: discard of nnkAsgn: case node[1].kind @@ -939,7 +989,7 @@ proc processBody(node, retFutureSym: PNimrodNode, if node[1][0].ident == !"await": # x = await y var newAsgn = node - result.createVar("future" & $node[0].toStrLit, node[1][1], newAsgn[1], newAsgn) + result.createVar("future" & $node[0].toStrLit, node[1][1], newAsgn[1], newAsgn, node) else: discard of nnkDiscardStmt: # discard await x @@ -947,10 +997,10 @@ proc processBody(node, retFutureSym: PNimrodNode, node[0][0].ident == !"await": var newDiscard = node result.createVar("futureDiscard_" & $toStrLit(node[0][1]), node[0][1], - newDiscard[0], newDiscard) + newDiscard[0], newDiscard, node) of nnkTryStmt: # try: await x; except: ... - result = newNimNode(nnkStmtList) + result = newNimNode(nnkStmtList, node) proc processForTry(n: PNimrodNode, i: var int, res: PNimrodNode): bool {.compileTime.} = result = false @@ -1009,7 +1059,7 @@ macro async*(prc: stmt): stmt {.immediate.} = (returnType.kind == nnkBracketExpr and returnType[1].kind == nnkIdent and returnType[1].ident == !"void") - var outerProcBody = newNimNode(nnkStmtList) + var outerProcBody = newNimNode(nnkStmtList, prc[6]) # -> var retFuture = newFuture[T]() var retFutureSym = genSym(nskVar, "retFuture") @@ -1019,9 +1069,10 @@ macro async*(prc: stmt): stmt {.immediate.} = outerProcBody.add( newVarStmt(retFutureSym, newCall( - newNimNode(nnkBracketExpr).add( + newNimNode(nnkBracketExpr, prc[6]).add( newIdentNode(!"newFuture"), # TODO: Strange bug here? Remove the `!`. - subRetType)))) # Get type from return type of this proc + subRetType), + newLit(prc[0].getName)))) # Get type from return type of this proc # -> iterator nameIter(): PFutureBase {.closure.} = # -> var result: T @@ -1030,7 +1081,7 @@ macro async*(prc: stmt): stmt {.immediate.} = var iteratorNameSym = genSym(nskIterator, $prc[0].getName & "Iter") var procBody = prc[6].processBody(retFutureSym, subtypeIsVoid, nil) if not subtypeIsVoid: - procBody.insert(0, newNimNode(nnkVarSection).add( + procBody.insert(0, newNimNode(nnkVarSection, prc[6]).add( newIdentDefs(newIdentNode("result"), returnType[1]))) # -> var result: T procBody.add( newCall(newIdentNode("complete"), @@ -1041,7 +1092,7 @@ macro async*(prc: stmt): stmt {.immediate.} = var closureIterator = newProc(iteratorNameSym, [newIdentNode("PFutureBase")], procBody, nnkIteratorDef) - closureIterator[4] = newNimNode(nnkPragma).add(newIdentNode("closure")) + closureIterator[4] = newNimNode(nnkPragma, prc[6]).add(newIdentNode("closure")) outerProcBody.add(closureIterator) # -> createCb(retFuture) @@ -1051,7 +1102,7 @@ macro async*(prc: stmt): stmt {.immediate.} = outerProcBody.add procCb # -> return retFuture - outerProcBody.add newNimNode(nnkReturnStmt).add(retFutureSym) + outerProcBody.add newNimNode(nnkReturnStmt, prc[6][prc[6].len-1]).add(retFutureSym) result = prc @@ -1068,8 +1119,8 @@ macro async*(prc: stmt): stmt {.immediate.} = result[6] = outerProcBody #echo(treeRepr(result)) - #if prc[0].getName == "routeReq": - #echo(toStrLit(result)) + #if prc[0].getName == "processClient": + # echo(toStrLit(result)) proc recvLine*(socket: TAsyncFD): PFuture[string] {.async.} = ## Reads a line of data from ``socket``. Returned future will complete once diff --git a/lib/pure/asynchttpserver.nim b/lib/pure/asynchttpserver.nim index ee6658fd1f..e7abfb97cb 100644 --- a/lib/pure/asynchttpserver.nim +++ b/lib/pure/asynchttpserver.nim @@ -199,6 +199,8 @@ proc serve*(server: PAsyncHttpServer, port: TPort, #var (address, client) = await server.socket.acceptAddr() var fut = await server.socket.acceptAddr() asyncCheck processClient(fut.client, fut.address, callback) + #echo(f.isNil) + #echo(f.repr) proc close*(server: PAsyncHttpServer) = ## Terminates the async http server instance. diff --git a/lib/pure/asyncnet.nim b/lib/pure/asyncnet.nim index 374ac77e31..db6f80b06b 100644 --- a/lib/pure/asyncnet.nim +++ b/lib/pure/asyncnet.nim @@ -140,7 +140,7 @@ proc acceptAddr*(socket: PAsyncSocket): ## Accepts a new connection. Returns a future containing the client socket ## corresponding to that connection and the remote address of the client. ## The future will complete when the connection is successfully accepted. - var retFuture = newFuture[tuple[address: string, client: PAsyncSocket]]() + var retFuture = newFuture[tuple[address: string, client: PAsyncSocket]]("asyncnet.acceptAddr") var fut = acceptAddr(socket.fd.TAsyncFD) fut.callback = proc (future: PFuture[tuple[address: string, client: TAsyncFD]]) = @@ -157,7 +157,7 @@ proc accept*(socket: PAsyncSocket): PFuture[PAsyncSocket] = ## Accepts a new connection. Returns a future containing the client socket ## corresponding to that connection. ## The future will complete when the connection is successfully accepted. - var retFut = newFuture[PAsyncSocket]() + var retFut = newFuture[PAsyncSocket]("asyncnet.accept") var fut = acceptAddr(socket) fut.callback = proc (future: PFuture[tuple[address: string, client: PAsyncSocket]]) = diff --git a/tests/async/tasyncexceptions.nim b/tests/async/tasyncexceptions.nim new file mode 100644 index 0000000000..9474fbae8a --- /dev/null +++ b/tests/async/tasyncexceptions.nim @@ -0,0 +1,38 @@ +discard """ + file: "tasyncexceptions.nim" + exitcode: 1 + outputsub: "Error: unhandled exception: foobar [E_Base]" +""" +import asyncdispatch + +proc accept(): PFuture[int] {.async.} = + await sleepAsync(100) + result = 4 + +proc recvLine(fd: int): PFuture[string] {.async.} = + await sleepAsync(100) + return "get" + +proc processClient(fd: int) {.async.} = + # these finish synchronously, we need some async delay to emulate this bug. + var line = await recvLine(fd) + var foo = line[0] + if foo == 'g': + raise newException(EBase, "foobar") + + +proc serve() {.async.} = + + while true: + var fut = await accept() + await processClient(fut) + +when isMainModule: + var fut = serve() + fut.callback = + proc () = + if fut.failed: + # This test ensures that this exception crashes the application + # as it is not handled. + raise fut.error + runForever() From f8e714bd30809c7a1f606d64aa0ea1e41036f037 Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Sat, 9 Aug 2014 18:10:45 +0100 Subject: [PATCH 120/234] Fixes async on Linux. --- lib/pure/asyncdispatch.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pure/asyncdispatch.nim b/lib/pure/asyncdispatch.nim index 6339232f8e..752c19534c 100644 --- a/lib/pure/asyncdispatch.nim +++ b/lib/pure/asyncdispatch.nim @@ -639,7 +639,7 @@ else: readCBs: seq[TCallback] writeCBs: seq[TCallback] - PDispatcher* = ref object + PDispatcher* = ref object of PDispatcherBase selector: PSelector proc `==`*(x, y: TAsyncFD): bool {.borrow.} From 7358fc256f3cf4eec1b73e8c7d257e3d377772f7 Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Sat, 9 Aug 2014 20:50:06 +0100 Subject: [PATCH 121/234] More future debug info. Added new error code to SafeDisconn list. --- lib/pure/asyncdispatch.nim | 25 +++++++++++++++++++++---- lib/pure/net.nim | 2 +- lib/pure/rawsockets.nim | 2 +- lib/windows/winlean.nim | 1 + 4 files changed, 24 insertions(+), 6 deletions(-) diff --git a/lib/pure/asyncdispatch.nim b/lib/pure/asyncdispatch.nim index 752c19534c..dea17d1468 100644 --- a/lib/pure/asyncdispatch.nim +++ b/lib/pure/asyncdispatch.nim @@ -41,7 +41,8 @@ type cb: proc () {.closure,gcsafe.} finished: bool error*: ref EBase - when defined(debug): + errorStackTrace*: string + when not defined(release): stackTrace: string ## For debugging purposes only. id: int fromProc: string @@ -57,14 +58,14 @@ proc newFuture*[T](fromProc: string = "unspecified"): PFuture[T] = ## that this future belongs to, is a good habit as it helps with debugging. new(result) result.finished = false - when defined(debug): + when not defined(release): result.stackTrace = getStackTrace() result.id = currentID result.fromProc = fromProc currentID.inc() proc checkFinished[T](future: PFuture[T]) = - when defined(debug): + when not defined(release): if future.finished: echo("<-----> ", future.id, " ", future.fromProc) echo(future.stackTrace) @@ -101,6 +102,8 @@ proc fail*[T](future: PFuture[T], error: ref EBase) = checkFinished(future) future.finished = true future.error = error + future.errorStackTrace = + if getStackTrace(error) == "": getStackTrace() else: getStackTrace(error) if future.cb != nil: future.cb() else: @@ -128,6 +131,15 @@ proc `callback=`*[T](future: PFuture[T], ## If future has already completed then ``cb`` will be called immediately. future.callback = proc () = cb(future) +proc echoOriginalStackTrace[T](future: PFuture[T]) = + # TODO: Come up with something better. + when not defined(release): + echo("Original stack trace in ", future.fromProc, ":") + if not future.errorStackTrace.isNil() and future.errorStackTrace != "": + echo(future.errorStackTrace) + else: + echo("Empty or nil stack trace.") + proc read*[T](future: PFuture[T]): T = ## Retrieves the value of ``future``. Future must be finished otherwise ## this function will fail with a ``EInvalidValue`` exception. @@ -135,6 +147,7 @@ proc read*[T](future: PFuture[T]): T = ## If the result of the future is an error then that error will be raised. if future.finished: if future.error != nil: + echoOriginalStackTrace(future) raise future.error when T isnot void: return future.value @@ -165,6 +178,7 @@ proc asyncCheck*[T](future: PFuture[T]) = future.callback = proc () = if future.failed: + echoOriginalStackTrace(future) raise future.error type @@ -438,7 +452,10 @@ when defined(windows) or defined(nimdoc): copyMem(addr data[0], addr dataBuf.buf[0], bytesCount) retFuture.complete($data) else: - retFuture.fail(newException(EOS, osErrorMsg(errcode))) + if flags.isDisconnectionError(errcode): + retFuture.complete("") + else: + retFuture.fail(newException(EOS, osErrorMsg(errcode))) if dataBuf.buf != nil: dealloc dataBuf.buf dataBuf.buf = nil diff --git a/lib/pure/net.nim b/lib/pure/net.nim index ddc2bbe2dc..5f83b1dea4 100644 --- a/lib/pure/net.nim +++ b/lib/pure/net.nim @@ -361,7 +361,7 @@ proc isDisconnectionError*(flags: set[TSocketFlags], when useWinVersion: TSocketFlags.SafeDisconn in flags and lastError.int32 in {WSAECONNRESET, WSAECONNABORTED, WSAENETRESET, - WSAEDISCON} + WSAEDISCON, ERROR_NETNAME_DELETED} else: TSocketFlags.SafeDisconn in flags and lastError.int32 in {ECONNRESET, EPIPE, ENETRESET} diff --git a/lib/pure/rawsockets.nim b/lib/pure/rawsockets.nim index d96741846e..fea09dfa25 100644 --- a/lib/pure/rawsockets.nim +++ b/lib/pure/rawsockets.nim @@ -22,7 +22,7 @@ const useWinVersion = defined(Windows) or defined(nimdoc) when useWinVersion: import winlean export WSAEWOULDBLOCK, WSAECONNRESET, WSAECONNABORTED, WSAENETRESET, - WSAEDISCON + WSAEDISCON, ERROR_NETNAME_DELETED else: import posix export fcntl, F_GETFL, O_NONBLOCK, F_SETFL, EAGAIN, EWOULDBLOCK, MSG_NOSIGNAL, diff --git a/lib/windows/winlean.nim b/lib/windows/winlean.nim index dcae6ffaf2..09696b67fa 100644 --- a/lib/windows/winlean.nim +++ b/lib/windows/winlean.nim @@ -664,6 +664,7 @@ const WSAEDISCON* = 10101 WSAENETRESET* = 10052 WSAETIMEDOUT* = 10060 + ERROR_NETNAME_DELETED* = 64 proc CreateIoCompletionPort*(FileHandle: THANDLE, ExistingCompletionPort: THANDLE, CompletionKey: DWORD, From e46a735bb5a6720851fef4630cea1adeff9ae1fd Mon Sep 17 00:00:00 2001 From: Clay Sweetser Date: Sat, 9 Aug 2014 16:40:35 -0400 Subject: [PATCH 122/234] Fixes #1435 --- compiler/semexprs.nim | 2 ++ 1 file changed, 2 insertions(+) diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index d040675fa1..bf13727e59 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -199,6 +199,8 @@ proc isCastable(dst, src: PType): bool = result = (dstSize >= srcSize) or (skipTypes(dst, abstractInst).kind in IntegralTypes) or (skipTypes(src, abstractInst-{tyTypeDesc}).kind in IntegralTypes) + if result and src.kind == tyNil: + result = dst.size <= platform.ptrSize proc isSymChoice(n: PNode): bool {.inline.} = result = n.kind in nkSymChoices From f8ea5f1a37de1d86e494477a8ac95165a3c81310 Mon Sep 17 00:00:00 2001 From: Clay Sweetser Date: Sat, 9 Aug 2014 16:40:58 -0400 Subject: [PATCH 123/234] Adds documentation on skipTypes and mapType --- compiler/ast.nim | 4 ++++ compiler/ccgtypes.nim | 1 + 2 files changed, 5 insertions(+) diff --git a/compiler/ast.nim b/compiler/ast.nim index 51319127c5..7ad2946957 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -1313,6 +1313,10 @@ proc newSons(father: PNode, length: int) = setLen(father.sons, length) proc skipTypes*(t: PType, kinds: TTypeKinds): PType = + ## Used throughout the compiler code to test whether a type tree contains or + ## doesn't contain a specific type/types - it is often the case that only the + ## last child nodes of a type tree need to be searched. This is a really hot + ## path within the compiler! result = t while result.kind in kinds: result = lastSon(result) diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim index 4c71c6ff79..86142995cc 100644 --- a/compiler/ccgtypes.nim +++ b/compiler/ccgtypes.nim @@ -122,6 +122,7 @@ proc mapSetType(typ: PType): TCTypeKind = else: result = ctArray proc mapType(typ: PType): TCTypeKind = + ## Maps a nimrod type to a C type case typ.kind of tyNone, tyStmt: result = ctVoid of tyBool: result = ctBool From 76011e40ef37018fe5cf69171e55b5c321152fbd Mon Sep 17 00:00:00 2001 From: Araq Date: Sun, 10 Aug 2014 03:17:30 +0200 Subject: [PATCH 124/234] progress on 'spawn' --- compiler/lowerings.nim | 4 ++-- compiler/sem.nim | 2 +- compiler/semexprs.nim | 6 +++--- compiler/semparallel.nim | 13 +++++++++---- tests/parallel/tdeepcopy.nim | 18 ++++++++++++++++++ 5 files changed, 33 insertions(+), 10 deletions(-) create mode 100644 tests/parallel/tdeepcopy.nim diff --git a/compiler/lowerings.nim b/compiler/lowerings.nim index 4050bb9b44..ddfcb4f011 100644 --- a/compiler/lowerings.nim +++ b/compiler/lowerings.nim @@ -185,14 +185,14 @@ proc callProc(a: PNode): PNode = # - a proc returning non GC'ed memory --> pass as hidden 'var' parameter # - not in a parallel environment --> requires a flowVar for memory safety type - TSpawnResult = enum + TSpawnResult* = enum srVoid, srFlowVar, srByVar TFlowVarKind = enum fvInvalid # invalid type T for 'FlowVar[T]' fvGC # FlowVar of a GC'ed type fvBlob # FlowVar of a blob type -proc spawnResult(t: PType; inParallel: bool): TSpawnResult = +proc spawnResult*(t: PType; inParallel: bool): TSpawnResult = if t.isEmptyType: srVoid elif inParallel and not containsGarbageCollectedRef(t): srByVar else: srFlowVar diff --git a/compiler/sem.nim b/compiler/sem.nim index 8025ef70de..26a59334c0 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -16,7 +16,7 @@ import procfind, lookups, rodread, pragmas, passes, semdata, semtypinst, sigmatch, intsets, transf, vmdef, vm, idgen, aliases, cgmeth, lambdalifting, evaltempl, patterns, parampatterns, sempass2, pretty, semmacrosanity, - semparallel + semparallel, lowerings # implementation diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index d040675fa1..b81d53d41f 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -1643,10 +1643,10 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode = result = setMs(n, s) result.sons[1] = semExpr(c, n.sons[1]) if not result[1].typ.isEmptyType: - if c.inParallelStmt > 0: - result.typ = result[1].typ - else: + if spawnResult(result[1].typ, c.inParallelStmt > 0) == srFlowVar: result.typ = createFlowVar(c, result[1].typ, n.info) + else: + result.typ = result[1].typ result.add instantiateCreateFlowVarCall(c, result[1].typ, n.info).newSymNode else: result = semDirectOp(c, n, flags) diff --git a/compiler/semparallel.nim b/compiler/semparallel.nim index 2ad7ef3416..7c489c3b6f 100644 --- a/compiler/semparallel.nim +++ b/compiler/semparallel.nim @@ -23,7 +23,7 @@ import ast, astalgo, idents, lowerings, magicsys, guards, sempass2, msgs, - renderer + renderer, types from trees import getMagic from strutils import `%` @@ -406,12 +406,17 @@ proc transformSpawn(owner: PSym; n, barrier: PNode): PNode = if result.isNil: result = newNodeI(nkStmtList, n.info) result.add n - result.add wrapProcForSpawn(owner, m, b.typ, barrier, it[0]) - it.sons[it.len-1] = emptyNode + let t = b[1][0].typ.sons[0] + if spawnResult(t, true) == srByVar: + result.add wrapProcForSpawn(owner, m, b.typ, barrier, it[0]) + it.sons[it.len-1] = emptyNode + else: + it.sons[it.len-1] = wrapProcForSpawn(owner, m, b.typ, barrier, nil) if result.isNil: result = n of nkAsgn, nkFastAsgn: let b = n[1] - if getMagic(b) == mSpawn: + if getMagic(b) == mSpawn and (let t = b[1][0].typ.sons[0]; + spawnResult(t, true) == srByVar): let m = transformSlices(b) return wrapProcForSpawn(owner, m, b.typ, barrier, n[0]) result = transformSpawnSons(owner, n, barrier) diff --git a/tests/parallel/tdeepcopy.nim b/tests/parallel/tdeepcopy.nim new file mode 100644 index 0000000000..84e2edf3f4 --- /dev/null +++ b/tests/parallel/tdeepcopy.nim @@ -0,0 +1,18 @@ +discard """ + output: '''13 abc''' +""" + +type + PBinaryTree = ref object + le, ri: PBinaryTree + value: int + + +proc main = + var x: PBinaryTree + deepCopy(x, PBinaryTree(ri: PBinaryTree(le: PBinaryTree(value: 13)))) + var y: string + deepCopy y, "abc" + echo x.ri.le.value, " ", y + +main() From eb6ac2a901d0797eae4c273cef091b530c910a3c Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Sun, 10 Aug 2014 10:54:59 +0100 Subject: [PATCH 125/234] Asynchttpserver now uses new uri module for URL parsing. --- lib/pure/asynchttpserver.nim | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/pure/asynchttpserver.nim b/lib/pure/asynchttpserver.nim index e7abfb97cb..e5992e36fb 100644 --- a/lib/pure/asynchttpserver.nim +++ b/lib/pure/asynchttpserver.nim @@ -11,14 +11,14 @@ ## ## **Note:** This module is still largely experimental. -import strtabs, asyncnet, asyncdispatch, parseutils, parseurl, strutils +import strtabs, asyncnet, asyncdispatch, parseutils, uri, strutils type TRequest* = object client*: PAsyncSocket # TODO: Separate this into a Response object? reqMethod*: string headers*: PStringTable protocol*: tuple[orig: string, major, minor: int] - url*: TURL + url*: TUri hostname*: string ## The hostname of the client that made the request. body*: string @@ -135,7 +135,7 @@ proc processClient(client: PAsyncSocket, address: string, request.headers[kv.key] = kv.value request.reqMethod = reqMethod - request.url = parseUrl(path) + request.url = parseUri(path) try: request.protocol = protocol.parseProtocol() except EInvalidValue: From ef2f377bfa51af0390a691e214214747e0c4f93c Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Sun, 10 Aug 2014 11:39:37 +0100 Subject: [PATCH 126/234] Added SafeDisconn for accept. --- lib/pure/asyncdispatch.nim | 52 ++++++++++++++++++++++++++++---------- lib/pure/asyncnet.nim | 9 ++++--- lib/pure/net.nim | 22 ++++++++++++---- web/news.txt | 2 ++ 4 files changed, 63 insertions(+), 22 deletions(-) diff --git a/lib/pure/asyncdispatch.nim b/lib/pure/asyncdispatch.nim index dea17d1468..e1837b0ea7 100644 --- a/lib/pure/asyncdispatch.nim +++ b/lib/pure/asyncdispatch.nim @@ -524,7 +524,10 @@ when defined(windows) or defined(nimdoc): if errcode == TOSErrorCode(-1): retFuture.complete() else: - retFuture.fail(newException(EOS, osErrorMsg(errcode))) + if flags.isDisconnectionError(errcode): + retFuture.complete() + else: + retFuture.fail(newException(EOS, osErrorMsg(errcode))) ) let ret = WSASend(socket.TSocketHandle, addr dataBuf, 1, addr bytesReceived, @@ -544,13 +547,19 @@ when defined(windows) or defined(nimdoc): # free ``ol``. return retFuture - proc acceptAddr*(socket: TAsyncFD): + proc acceptAddr*(socket: TAsyncFD, flags = {TSocketFlags.SafeDisconn}): PFuture[tuple[address: string, client: TAsyncFD]] = ## Accepts a new connection. Returns a future containing the client socket ## corresponding to that connection and the remote address of the client. ## The future will complete when the connection is successfully accepted. ## - ## The resulting client socket is automatically registered to dispatcher. + ## The resulting client socket is automatically registered to the + ## dispatcher. + ## + ## The ``accept`` call may result in an error if the connecting socket + ## disconnects during the duration of the ``accept``. If the ``SafeDisconn`` + ## flag is specified then this error will not be raised and instead + ## accept will be called again. verifyPresence(socket) var retFuture = newFuture[tuple[address: string, client: TAsyncFD]]("acceptAddr") @@ -584,6 +593,18 @@ when defined(windows) or defined(nimdoc): client: clientSock.TAsyncFD) ) + template failAccept(errcode): stmt = + if flags.isDisconnectionError(errcode): + var newAcceptFut = acceptAddr(socket, flags) + newAcceptFut.callback = + proc () = + if newAcceptFut.failed: + retFuture.fail(newAcceptFut.readError) + else: + retFuture.complete(newAcceptFut.read) + else: + retFuture.fail(newException(EOS, osErrorMsg(errcode))) + var ol = PCustomOverlapped() GC_ref(ol) ol.data = TCompletionData(sock: socket, cb: @@ -592,7 +613,7 @@ when defined(windows) or defined(nimdoc): if errcode == TOSErrorCode(-1): completeAccept() else: - retFuture.fail(newException(EOS, osErrorMsg(errcode))) + failAccept(errcode) ) # http://msdn.microsoft.com/en-us/library/windows/desktop/ms737524%28v=vs.85%29.aspx @@ -605,7 +626,7 @@ when defined(windows) or defined(nimdoc): if not ret: let err = osLastError() if err.int32 != ERROR_IO_PENDING: - retFuture.fail(newException(EOS, osErrorMsg(err))) + failAccept(err) GC_unref(ol) else: completeAccept() @@ -749,7 +770,7 @@ else: proc connect*(socket: TAsyncFD, address: string, port: TPort, af = AF_INET): PFuture[void] = - var retFuture = newFuture[void]() + var retFuture = newFuture[void]("connect") proc cb(sock: TAsyncFD): bool = # We have connected. @@ -784,7 +805,7 @@ else: proc recv*(socket: TAsyncFD, size: int, flags = {TSocketFlags.SafeDisconn}): PFuture[string] = - var retFuture = newFuture[string]() + var retFuture = newFuture[string]("recv") var readBuffer = newString(size) @@ -815,7 +836,7 @@ else: proc send*(socket: TAsyncFD, data: string, flags = {TSocketFlags.SafeDisconn}): PFuture[void] = - var retFuture = newFuture[void]() + var retFuture = newFuture[void]("send") var written = 0 @@ -845,9 +866,10 @@ else: addWrite(socket, cb) return retFuture - proc acceptAddr*(socket: TAsyncFD): + proc acceptAddr*(socket: TAsyncFD, flags = {TSocketFlags.SafeDisconn}): PFuture[tuple[address: string, client: TAsyncFD]] = - var retFuture = newFuture[tuple[address: string, client: TAsyncFD]]() + var retFuture = newFuture[tuple[address: string, + client: TAsyncFD]]("acceptAddr") proc cb(sock: TAsyncFD): bool = result = true var sockAddress: Tsockaddr_in @@ -860,7 +882,10 @@ else: if lastError.int32 == EINTR: return false else: - retFuture.fail(newException(EOS, osErrorMsg(lastError))) + if flags.isDisconnectionError(lastError): + return false + else: + retFuture.fail(newException(EOS, osErrorMsg(lastError))) else: register(client.TAsyncFD) retFuture.complete(($inet_ntoa(sockAddress.sin_addr), client.TAsyncFD)) @@ -875,12 +900,13 @@ proc sleepAsync*(ms: int): PFuture[void] = p.timers.add((epochTime() + (ms / 1000), retFuture)) return retFuture -proc accept*(socket: TAsyncFD): PFuture[TAsyncFD] = +proc accept*(socket: TAsyncFD, + flags = {TSocketFlags.SafeDisconn}): PFuture[TAsyncFD] = ## Accepts a new connection. Returns a future containing the client socket ## corresponding to that connection. ## The future will complete when the connection is successfully accepted. var retFut = newFuture[TAsyncFD]("accept") - var fut = acceptAddr(socket) + var fut = acceptAddr(socket, flags) fut.callback = proc (future: PFuture[tuple[address: string, client: TAsyncFD]]) = assert future.finished diff --git a/lib/pure/asyncnet.nim b/lib/pure/asyncnet.nim index db6f80b06b..b81c4b13a8 100644 --- a/lib/pure/asyncnet.nim +++ b/lib/pure/asyncnet.nim @@ -135,13 +135,13 @@ proc send*(socket: PAsyncSocket, data: string, assert socket != nil result = send(socket.fd.TAsyncFD, data, flags) -proc acceptAddr*(socket: PAsyncSocket): +proc acceptAddr*(socket: PAsyncSocket, flags = {TSocketFlags.SafeDisconn}): PFuture[tuple[address: string, client: PAsyncSocket]] = ## Accepts a new connection. Returns a future containing the client socket ## corresponding to that connection and the remote address of the client. ## The future will complete when the connection is successfully accepted. var retFuture = newFuture[tuple[address: string, client: PAsyncSocket]]("asyncnet.acceptAddr") - var fut = acceptAddr(socket.fd.TAsyncFD) + var fut = acceptAddr(socket.fd.TAsyncFD, flags) fut.callback = proc (future: PFuture[tuple[address: string, client: TAsyncFD]]) = assert future.finished @@ -153,12 +153,13 @@ proc acceptAddr*(socket: PAsyncSocket): retFuture.complete(resultTup) return retFuture -proc accept*(socket: PAsyncSocket): PFuture[PAsyncSocket] = +proc accept*(socket: PAsyncSocket, + flags = {TSocketFlags.SafeDisconn}): PFuture[PAsyncSocket] = ## Accepts a new connection. Returns a future containing the client socket ## corresponding to that connection. ## The future will complete when the connection is successfully accepted. var retFut = newFuture[PAsyncSocket]("asyncnet.accept") - var fut = acceptAddr(socket) + var fut = acceptAddr(socket, flags) fut.callback = proc (future: PFuture[tuple[address: string, client: PAsyncSocket]]) = assert future.finished diff --git a/lib/pure/net.nim b/lib/pure/net.nim index 5f83b1dea4..224087994c 100644 --- a/lib/pure/net.nim +++ b/lib/pure/net.nim @@ -569,8 +569,8 @@ proc bindAddr*(socket: PSocket, port = TPort(0), address = "") {. osError(osLastError()) dealloc(aiList) -proc acceptAddr*(server: PSocket, client: var PSocket, address: var string) {. - tags: [FReadIO].} = +proc acceptAddr*(server: PSocket, client: var PSocket, address: var string, + flags = {TSocketFlags.SafeDisconn}) {.tags: [FReadIO].} = ## Blocks until a connection is being made from a client. When a connection ## is made sets ``client`` to the client socket and ``address`` to the address ## of the connecting client. @@ -581,6 +581,11 @@ proc acceptAddr*(server: PSocket, client: var PSocket, address: var string) {. ## ## **Note**: ``client`` must be initialised (with ``new``), this function ## makes no effort to initialise the ``client`` variable. + ## + ## The ``accept`` call may result in an error if the connecting socket + ## disconnects during the duration of the ``accept``. If the ``SafeDisconn`` + ## flag is specified then this error will not be raised and instead + ## accept will be called again. assert(client != nil) var sockAddress: Tsockaddr_in var addrLen = sizeof(sockAddress).TSocklen @@ -589,6 +594,8 @@ proc acceptAddr*(server: PSocket, client: var PSocket, address: var string) {. if sock == osInvalidSocket: let err = osLastError() + if flags.isDisconnectionError(err): + acceptAddr(server, client, address, flags) osError(err) else: client.fd = sock @@ -658,15 +665,20 @@ when false: #defined(ssl): acceptAddrPlain(AcceptNoClient, AcceptSuccess): doHandshake() -proc accept*(server: PSocket, client: var PSocket) {.tags: [FReadIO].} = +proc accept*(server: PSocket, client: var PSocket, + flags = {TSocketFlags.SafeDisconn}) {.tags: [FReadIO].} = ## Equivalent to ``acceptAddr`` but doesn't return the address, only the ## socket. ## ## **Note**: ``client`` must be initialised (with ``new``), this function ## makes no effort to initialise the ``client`` variable. - + ## + ## The ``accept`` call may result in an error if the connecting socket + ## disconnects during the duration of the ``accept``. If the ``SafeDisconn`` + ## flag is specified then this error will not be raised and instead + ## accept will be called again. var addrDummy = "" - acceptAddr(server, client, addrDummy) + acceptAddr(server, client, addrDummy, flags) proc close*(socket: PSocket) = ## Closes a socket. diff --git a/web/news.txt b/web/news.txt index 20e2412212..a4cbefd52d 100644 --- a/web/news.txt +++ b/web/news.txt @@ -38,6 +38,8 @@ News - ``sequtils.distnct`` has been renamed to ``sequtils.deduplicate``. - Added ``algorithm.reversed`` - Added ``uri.combine`` and ``uri.parseUri``. + - Some sockets procedures now support a ``SafeDisconn`` flag which causes + them to handle disconnection errors and not raise them. 2014-04-21 Version 0.9.4 released ================================= From a2ec3c91f1e32d61510d1e4a387e125291d2deea Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Sun, 10 Aug 2014 12:28:17 +0100 Subject: [PATCH 127/234] Fix asyncnet example. Rearrange net code. --- lib/pure/asyncnet.nim | 4 +- lib/pure/net.nim | 564 +++++++++++++++++++++--------------------- 2 files changed, 284 insertions(+), 284 deletions(-) diff --git a/lib/pure/asyncnet.nim b/lib/pure/asyncnet.nim index b81c4b13a8..5095d94613 100644 --- a/lib/pure/asyncnet.nim +++ b/lib/pure/asyncnet.nim @@ -36,9 +36,9 @@ ## let client = await server.accept() ## clients.add client ## -## processClient(client) +## asyncCheck processClient(client) ## -## serve() +## asyncCheck serve() ## runForever() ## ## diff --git a/lib/pure/net.nim b/lib/pure/net.nim index 224087994c..f35e0cf63e 100644 --- a/lib/pure/net.nim +++ b/lib/pure/net.nim @@ -15,288 +15,6 @@ export TPort, `$` const useWinVersion = defined(Windows) or defined(nimdoc) -type - IpAddressFamily* {.pure.} = enum ## Describes the type of an IP address - IPv6, ## IPv6 address - IPv4 ## IPv4 address - - TIpAddress* = object ## stores an arbitrary IP address - case family*: IpAddressFamily ## the type of the IP address (IPv4 or IPv6) - of IpAddressFamily.IPv6: - address_v6*: array[0..15, uint8] ## Contains the IP address in bytes in - ## case of IPv6 - of IpAddressFamily.IPv4: - address_v4*: array[0..3, uint8] ## Contains the IP address in bytes in - ## case of IPv4 - -proc IPv4_any*(): TIpAddress = - ## Returns the IPv4 any address, which can be used to listen on all available - ## network adapters - result = TIpAddress( - family: IpAddressFamily.IPv4, - address_v4: [0'u8, 0, 0, 0]) - -proc IPv4_loopback*(): TIpAddress = - ## Returns the IPv4 loopback address (127.0.0.1) - result = TIpAddress( - family: IpAddressFamily.IPv4, - address_v4: [127'u8, 0, 0, 1]) - -proc IPv4_broadcast*(): TIpAddress = - ## Returns the IPv4 broadcast address (255.255.255.255) - result = TIpAddress( - family: IpAddressFamily.IPv4, - address_v4: [255'u8, 255, 255, 255]) - -proc IPv6_any*(): TIpAddress = - ## Returns the IPv6 any address (::0), which can be used - ## to listen on all available network adapters - result = TIpAddress( - family: IpAddressFamily.IPv6, - address_v6: [0'u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) - -proc IPv6_loopback*(): TIpAddress = - ## Returns the IPv6 loopback address (::1) - result = TIpAddress( - family: IpAddressFamily.IPv6, - address_v6: [0'u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]) - -proc `==`*(lhs, rhs: TIpAddress): bool = - ## Compares two IpAddresses for Equality. Returns two if the addresses are equal - if lhs.family != rhs.family: return false - if lhs.family == IpAddressFamily.IPv4: - for i in low(lhs.address_v4) .. high(lhs.address_v4): - if lhs.address_v4[i] != rhs.address_v4[i]: return false - else: # IPv6 - for i in low(lhs.address_v6) .. high(lhs.address_v6): - if lhs.address_v6[i] != rhs.address_v6[i]: return false - return true - -proc `$`*(address: TIpAddress): string = - ## Converts an TIpAddress into the textual representation - result = "" - case address.family - of IpAddressFamily.IPv4: - for i in 0 .. 3: - if i != 0: - result.add('.') - result.add($address.address_v4[i]) - of IpAddressFamily.IPv6: - var - currentZeroStart = -1 - currentZeroCount = 0 - biggestZeroStart = -1 - biggestZeroCount = 0 - # Look for the largest block of zeros - for i in 0..7: - var isZero = address.address_v6[i*2] == 0 and address.address_v6[i*2+1] == 0 - if isZero: - if currentZeroStart == -1: - currentZeroStart = i - currentZeroCount = 1 - else: - currentZeroCount.inc() - if currentZeroCount > biggestZeroCount: - biggestZeroCount = currentZeroCount - biggestZeroStart = currentZeroStart - else: - currentZeroStart = -1 - - if biggestZeroCount == 8: # Special case ::0 - result.add("::") - else: # Print address - var printedLastGroup = false - for i in 0..7: - var word:uint16 = (cast[uint16](address.address_v6[i*2])) shl 8 - word = word or cast[uint16](address.address_v6[i*2+1]) - - if biggestZeroCount != 0 and # Check if group is in skip group - (i >= biggestZeroStart and i < (biggestZeroStart + biggestZeroCount)): - if i == biggestZeroStart: # skip start - result.add("::") - printedLastGroup = false - else: - if printedLastGroup: - result.add(':') - var - afterLeadingZeros = false - mask = 0xF000'u16 - for j in 0'u16..3'u16: - var val = (mask and word) shr (4'u16*(3'u16-j)) - if val != 0 or afterLeadingZeros: - if val < 0xA: - result.add(chr(uint16(ord('0'))+val)) - else: # val >= 0xA - result.add(chr(uint16(ord('a'))+val-0xA)) - afterLeadingZeros = true - mask = mask shr 4 - printedLastGroup = true - -proc parseIPv4Address(address_str: string): TIpAddress = - ## Parses IPv4 adresses - ## Raises EInvalidValue on errors - var - byteCount = 0 - currentByte:uint16 = 0 - seperatorValid = false - - result.family = IpAddressFamily.IPv4 - - for i in 0 .. high(address_str): - if address_str[i] in strutils.Digits: # Character is a number - currentByte = currentByte * 10 + - cast[uint16](ord(address_str[i]) - ord('0')) - if currentByte > 255'u16: - raise newException(EInvalidValue, - "Invalid IP Address. Value is out of range") - seperatorValid = true - elif address_str[i] == '.': # IPv4 address separator - if not seperatorValid or byteCount >= 3: - raise newException(EInvalidValue, - "Invalid IP Address. The address consists of too many groups") - result.address_v4[byteCount] = cast[uint8](currentByte) - currentByte = 0 - byteCount.inc - seperatorValid = false - else: - raise newException(EInvalidValue, - "Invalid IP Address. Address contains an invalid character") - - if byteCount != 3 or not seperatorValid: - raise newException(EInvalidValue, "Invalid IP Address") - result.address_v4[byteCount] = cast[uint8](currentByte) - -proc parseIPv6Address(address_str: string): TIpAddress = - ## Parses IPv6 adresses - ## Raises EInvalidValue on errors - result.family = IpAddressFamily.IPv6 - if address_str.len < 2: - raise newException(EInvalidValue, "Invalid IP Address") - - var - groupCount = 0 - currentGroupStart = 0 - currentShort:uint32 = 0 - seperatorValid = true - dualColonGroup = -1 - lastWasColon = false - v4StartPos = -1 - byteCount = 0 - - for i,c in address_str: - if c == ':': - if not seperatorValid: - raise newException(EInvalidValue, - "Invalid IP Address. Address contains an invalid seperator") - if lastWasColon: - if dualColonGroup != -1: - raise newException(EInvalidValue, - "Invalid IP Address. Address contains more than one \"::\" seperator") - dualColonGroup = groupCount - seperatorValid = false - elif i != 0 and i != high(address_str): - if groupCount >= 8: - raise newException(EInvalidValue, - "Invalid IP Address. The address consists of too many groups") - result.address_v6[groupCount*2] = cast[uint8](currentShort shr 8) - result.address_v6[groupCount*2+1] = cast[uint8](currentShort and 0xFF) - currentShort = 0 - groupCount.inc() - if dualColonGroup != -1: seperatorValid = false - elif i == 0: # only valid if address starts with :: - if address_str[1] != ':': - raise newException(EInvalidValue, - "Invalid IP Address. Address may not start with \":\"") - else: # i == high(address_str) - only valid if address ends with :: - if address_str[high(address_str)-1] != ':': - raise newException(EInvalidValue, - "Invalid IP Address. Address may not end with \":\"") - lastWasColon = true - currentGroupStart = i + 1 - elif c == '.': # Switch to parse IPv4 mode - if i < 3 or not seperatorValid or groupCount >= 7: - raise newException(EInvalidValue, "Invalid IP Address") - v4StartPos = currentGroupStart - currentShort = 0 - seperatorValid = false - break - elif c in strutils.HexDigits: - if c in strutils.Digits: # Normal digit - currentShort = (currentShort shl 4) + cast[uint32](ord(c) - ord('0')) - elif c >= 'a' and c <= 'f': # Lower case hex - currentShort = (currentShort shl 4) + cast[uint32](ord(c) - ord('a')) + 10 - else: # Upper case hex - currentShort = (currentShort shl 4) + cast[uint32](ord(c) - ord('A')) + 10 - if currentShort > 65535'u32: - raise newException(EInvalidValue, - "Invalid IP Address. Value is out of range") - lastWasColon = false - seperatorValid = true - else: - raise newException(EInvalidValue, - "Invalid IP Address. Address contains an invalid character") - - - if v4StartPos == -1: # Don't parse v4. Copy the remaining v6 stuff - if seperatorValid: # Copy remaining data - if groupCount >= 8: - raise newException(EInvalidValue, - "Invalid IP Address. The address consists of too many groups") - result.address_v6[groupCount*2] = cast[uint8](currentShort shr 8) - result.address_v6[groupCount*2+1] = cast[uint8](currentShort and 0xFF) - groupCount.inc() - else: # Must parse IPv4 address - for i,c in address_str[v4StartPos..high(address_str)]: - if c in strutils.Digits: # Character is a number - currentShort = currentShort * 10 + cast[uint32](ord(c) - ord('0')) - if currentShort > 255'u32: - raise newException(EInvalidValue, - "Invalid IP Address. Value is out of range") - seperatorValid = true - elif c == '.': # IPv4 address separator - if not seperatorValid or byteCount >= 3: - raise newException(EInvalidValue, "Invalid IP Address") - result.address_v6[groupCount*2 + byteCount] = cast[uint8](currentShort) - currentShort = 0 - byteCount.inc() - seperatorValid = false - else: # Invalid character - raise newException(EInvalidValue, - "Invalid IP Address. Address contains an invalid character") - - if byteCount != 3 or not seperatorValid: - raise newException(EInvalidValue, "Invalid IP Address") - result.address_v6[groupCount*2 + byteCount] = cast[uint8](currentShort) - groupCount += 2 - - # Shift and fill zeros in case of :: - if groupCount > 8: - raise newException(EInvalidValue, - "Invalid IP Address. The address consists of too many groups") - elif groupCount < 8: # must fill - if dualColonGroup == -1: - raise newException(EInvalidValue, - "Invalid IP Address. The address consists of too few groups") - var toFill = 8 - groupCount # The number of groups to fill - var toShift = groupCount - dualColonGroup # Nr of known groups after :: - for i in 0..2*toShift-1: # shift - result.address_v6[15-i] = result.address_v6[groupCount*2-i-1] - for i in 0..2*toFill-1: # fill with 0s - result.address_v6[dualColonGroup*2+i] = 0 - elif dualColonGroup != -1: - raise newException(EInvalidValue, - "Invalid IP Address. The address consists of too many groups") - -proc parseIpAddress*(address_str: string): TIpAddress = - ## Parses an IP address - ## Raises EInvalidValue on error - if address_str == nil: - raise newException(EInvalidValue, "IP Address string is nil") - if address_str.contains(':'): - return parseIPv6Address(address_str) - else: - return parseIPv4Address(address_str) - when defined(ssl): import openssl @@ -1185,3 +903,285 @@ proc isSSL*(socket: PSocket): bool = return socket.isSSL proc getFD*(socket: PSocket): TSocketHandle = return socket.fd ## Returns the socket's file descriptor + +type + IpAddressFamily* {.pure.} = enum ## Describes the type of an IP address + IPv6, ## IPv6 address + IPv4 ## IPv4 address + + TIpAddress* = object ## stores an arbitrary IP address + case family*: IpAddressFamily ## the type of the IP address (IPv4 or IPv6) + of IpAddressFamily.IPv6: + address_v6*: array[0..15, uint8] ## Contains the IP address in bytes in + ## case of IPv6 + of IpAddressFamily.IPv4: + address_v4*: array[0..3, uint8] ## Contains the IP address in bytes in + ## case of IPv4 + +proc IPv4_any*(): TIpAddress = + ## Returns the IPv4 any address, which can be used to listen on all available + ## network adapters + result = TIpAddress( + family: IpAddressFamily.IPv4, + address_v4: [0'u8, 0, 0, 0]) + +proc IPv4_loopback*(): TIpAddress = + ## Returns the IPv4 loopback address (127.0.0.1) + result = TIpAddress( + family: IpAddressFamily.IPv4, + address_v4: [127'u8, 0, 0, 1]) + +proc IPv4_broadcast*(): TIpAddress = + ## Returns the IPv4 broadcast address (255.255.255.255) + result = TIpAddress( + family: IpAddressFamily.IPv4, + address_v4: [255'u8, 255, 255, 255]) + +proc IPv6_any*(): TIpAddress = + ## Returns the IPv6 any address (::0), which can be used + ## to listen on all available network adapters + result = TIpAddress( + family: IpAddressFamily.IPv6, + address_v6: [0'u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) + +proc IPv6_loopback*(): TIpAddress = + ## Returns the IPv6 loopback address (::1) + result = TIpAddress( + family: IpAddressFamily.IPv6, + address_v6: [0'u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]) + +proc `==`*(lhs, rhs: TIpAddress): bool = + ## Compares two IpAddresses for Equality. Returns two if the addresses are equal + if lhs.family != rhs.family: return false + if lhs.family == IpAddressFamily.IPv4: + for i in low(lhs.address_v4) .. high(lhs.address_v4): + if lhs.address_v4[i] != rhs.address_v4[i]: return false + else: # IPv6 + for i in low(lhs.address_v6) .. high(lhs.address_v6): + if lhs.address_v6[i] != rhs.address_v6[i]: return false + return true + +proc `$`*(address: TIpAddress): string = + ## Converts an TIpAddress into the textual representation + result = "" + case address.family + of IpAddressFamily.IPv4: + for i in 0 .. 3: + if i != 0: + result.add('.') + result.add($address.address_v4[i]) + of IpAddressFamily.IPv6: + var + currentZeroStart = -1 + currentZeroCount = 0 + biggestZeroStart = -1 + biggestZeroCount = 0 + # Look for the largest block of zeros + for i in 0..7: + var isZero = address.address_v6[i*2] == 0 and address.address_v6[i*2+1] == 0 + if isZero: + if currentZeroStart == -1: + currentZeroStart = i + currentZeroCount = 1 + else: + currentZeroCount.inc() + if currentZeroCount > biggestZeroCount: + biggestZeroCount = currentZeroCount + biggestZeroStart = currentZeroStart + else: + currentZeroStart = -1 + + if biggestZeroCount == 8: # Special case ::0 + result.add("::") + else: # Print address + var printedLastGroup = false + for i in 0..7: + var word:uint16 = (cast[uint16](address.address_v6[i*2])) shl 8 + word = word or cast[uint16](address.address_v6[i*2+1]) + + if biggestZeroCount != 0 and # Check if group is in skip group + (i >= biggestZeroStart and i < (biggestZeroStart + biggestZeroCount)): + if i == biggestZeroStart: # skip start + result.add("::") + printedLastGroup = false + else: + if printedLastGroup: + result.add(':') + var + afterLeadingZeros = false + mask = 0xF000'u16 + for j in 0'u16..3'u16: + var val = (mask and word) shr (4'u16*(3'u16-j)) + if val != 0 or afterLeadingZeros: + if val < 0xA: + result.add(chr(uint16(ord('0'))+val)) + else: # val >= 0xA + result.add(chr(uint16(ord('a'))+val-0xA)) + afterLeadingZeros = true + mask = mask shr 4 + printedLastGroup = true + +proc parseIPv4Address(address_str: string): TIpAddress = + ## Parses IPv4 adresses + ## Raises EInvalidValue on errors + var + byteCount = 0 + currentByte:uint16 = 0 + seperatorValid = false + + result.family = IpAddressFamily.IPv4 + + for i in 0 .. high(address_str): + if address_str[i] in strutils.Digits: # Character is a number + currentByte = currentByte * 10 + + cast[uint16](ord(address_str[i]) - ord('0')) + if currentByte > 255'u16: + raise newException(EInvalidValue, + "Invalid IP Address. Value is out of range") + seperatorValid = true + elif address_str[i] == '.': # IPv4 address separator + if not seperatorValid or byteCount >= 3: + raise newException(EInvalidValue, + "Invalid IP Address. The address consists of too many groups") + result.address_v4[byteCount] = cast[uint8](currentByte) + currentByte = 0 + byteCount.inc + seperatorValid = false + else: + raise newException(EInvalidValue, + "Invalid IP Address. Address contains an invalid character") + + if byteCount != 3 or not seperatorValid: + raise newException(EInvalidValue, "Invalid IP Address") + result.address_v4[byteCount] = cast[uint8](currentByte) + +proc parseIPv6Address(address_str: string): TIpAddress = + ## Parses IPv6 adresses + ## Raises EInvalidValue on errors + result.family = IpAddressFamily.IPv6 + if address_str.len < 2: + raise newException(EInvalidValue, "Invalid IP Address") + + var + groupCount = 0 + currentGroupStart = 0 + currentShort:uint32 = 0 + seperatorValid = true + dualColonGroup = -1 + lastWasColon = false + v4StartPos = -1 + byteCount = 0 + + for i,c in address_str: + if c == ':': + if not seperatorValid: + raise newException(EInvalidValue, + "Invalid IP Address. Address contains an invalid seperator") + if lastWasColon: + if dualColonGroup != -1: + raise newException(EInvalidValue, + "Invalid IP Address. Address contains more than one \"::\" seperator") + dualColonGroup = groupCount + seperatorValid = false + elif i != 0 and i != high(address_str): + if groupCount >= 8: + raise newException(EInvalidValue, + "Invalid IP Address. The address consists of too many groups") + result.address_v6[groupCount*2] = cast[uint8](currentShort shr 8) + result.address_v6[groupCount*2+1] = cast[uint8](currentShort and 0xFF) + currentShort = 0 + groupCount.inc() + if dualColonGroup != -1: seperatorValid = false + elif i == 0: # only valid if address starts with :: + if address_str[1] != ':': + raise newException(EInvalidValue, + "Invalid IP Address. Address may not start with \":\"") + else: # i == high(address_str) - only valid if address ends with :: + if address_str[high(address_str)-1] != ':': + raise newException(EInvalidValue, + "Invalid IP Address. Address may not end with \":\"") + lastWasColon = true + currentGroupStart = i + 1 + elif c == '.': # Switch to parse IPv4 mode + if i < 3 or not seperatorValid or groupCount >= 7: + raise newException(EInvalidValue, "Invalid IP Address") + v4StartPos = currentGroupStart + currentShort = 0 + seperatorValid = false + break + elif c in strutils.HexDigits: + if c in strutils.Digits: # Normal digit + currentShort = (currentShort shl 4) + cast[uint32](ord(c) - ord('0')) + elif c >= 'a' and c <= 'f': # Lower case hex + currentShort = (currentShort shl 4) + cast[uint32](ord(c) - ord('a')) + 10 + else: # Upper case hex + currentShort = (currentShort shl 4) + cast[uint32](ord(c) - ord('A')) + 10 + if currentShort > 65535'u32: + raise newException(EInvalidValue, + "Invalid IP Address. Value is out of range") + lastWasColon = false + seperatorValid = true + else: + raise newException(EInvalidValue, + "Invalid IP Address. Address contains an invalid character") + + + if v4StartPos == -1: # Don't parse v4. Copy the remaining v6 stuff + if seperatorValid: # Copy remaining data + if groupCount >= 8: + raise newException(EInvalidValue, + "Invalid IP Address. The address consists of too many groups") + result.address_v6[groupCount*2] = cast[uint8](currentShort shr 8) + result.address_v6[groupCount*2+1] = cast[uint8](currentShort and 0xFF) + groupCount.inc() + else: # Must parse IPv4 address + for i,c in address_str[v4StartPos..high(address_str)]: + if c in strutils.Digits: # Character is a number + currentShort = currentShort * 10 + cast[uint32](ord(c) - ord('0')) + if currentShort > 255'u32: + raise newException(EInvalidValue, + "Invalid IP Address. Value is out of range") + seperatorValid = true + elif c == '.': # IPv4 address separator + if not seperatorValid or byteCount >= 3: + raise newException(EInvalidValue, "Invalid IP Address") + result.address_v6[groupCount*2 + byteCount] = cast[uint8](currentShort) + currentShort = 0 + byteCount.inc() + seperatorValid = false + else: # Invalid character + raise newException(EInvalidValue, + "Invalid IP Address. Address contains an invalid character") + + if byteCount != 3 or not seperatorValid: + raise newException(EInvalidValue, "Invalid IP Address") + result.address_v6[groupCount*2 + byteCount] = cast[uint8](currentShort) + groupCount += 2 + + # Shift and fill zeros in case of :: + if groupCount > 8: + raise newException(EInvalidValue, + "Invalid IP Address. The address consists of too many groups") + elif groupCount < 8: # must fill + if dualColonGroup == -1: + raise newException(EInvalidValue, + "Invalid IP Address. The address consists of too few groups") + var toFill = 8 - groupCount # The number of groups to fill + var toShift = groupCount - dualColonGroup # Nr of known groups after :: + for i in 0..2*toShift-1: # shift + result.address_v6[15-i] = result.address_v6[groupCount*2-i-1] + for i in 0..2*toFill-1: # fill with 0s + result.address_v6[dualColonGroup*2+i] = 0 + elif dualColonGroup != -1: + raise newException(EInvalidValue, + "Invalid IP Address. The address consists of too many groups") + +proc parseIpAddress*(address_str: string): TIpAddress = + ## Parses an IP address + ## Raises EInvalidValue on error + if address_str == nil: + raise newException(EInvalidValue, "IP Address string is nil") + if address_str.contains(':'): + return parseIPv6Address(address_str) + else: + return parseIPv4Address(address_str) From b1c8461a3b738cb4383b2e23ba24f36960a8604c Mon Sep 17 00:00:00 2001 From: Araq Date: Sun, 10 Aug 2014 13:46:42 +0200 Subject: [PATCH 128/234] fixes tinavlid_array_bounds test --- compiler/guards.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/guards.nim b/compiler/guards.nim index 4cf06fe026..431de61566 100644 --- a/compiler/guards.nim +++ b/compiler/guards.nim @@ -758,7 +758,7 @@ proc pleViaModelRec(m: var TModel; a, b: PNode): TImplication = result = impliesLe(fact, a, b) if result != impUnknown: return result if sameTree(y, a): - result = ple(m, x, b) + result = ple(m, b, x) if result != impUnknown: return result proc pleViaModel(model: TModel; aa, bb: PNode): TImplication = From 74213fcb9c5387fe0bcdde5d743afcd3b7eb31ba Mon Sep 17 00:00:00 2001 From: Varriount Date: Sun, 10 Aug 2014 17:50:58 -0400 Subject: [PATCH 129/234] Update semexprs.nim --- compiler/semexprs.nim | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 14129332cc..35cebdad7d 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -192,16 +192,12 @@ proc isCastable(dst, src: PType): bool = dstSize = computeSize(dst) srcSize = computeSize(src) if dstSize < 0: - echo 'a' result = false - elif srcSize < 0: - echo 'b' + elif srcSize < 0: result = false elif not typeAllowed(dst, skParam): - echo 'c' result = false else: - echo 'd' result = (dstSize >= srcSize) or (skipTypes(dst, abstractInst).kind in IntegralTypes) or (skipTypes(src, abstractInst-{tyTypeDesc}).kind in IntegralTypes) From 6dd96abdcc30a0002129f77fd2ac85c1a2edcf13 Mon Sep 17 00:00:00 2001 From: Clay Sweetser Date: Sun, 10 Aug 2014 18:32:27 -0400 Subject: [PATCH 130/234] Made the code actually work, updated the docstring to point out that the given file path must exist *and* be accessible from the current working directory of the running program. --- lib/pure/os.nim | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/lib/pure/os.nim b/lib/pure/os.nim index 37d3417873..adde94afce 100644 --- a/lib/pure/os.nim +++ b/lib/pure/os.nim @@ -365,8 +365,9 @@ when defined(windows): template getFilename(f: expr): expr = $f.cFilename proc skipFindData(f: TWIN32_FIND_DATA): bool {.inline.} = + # Note - takes advantage of null delimiter in the cstring const dot = ord('.') - result = f.cFileName[0].int == dot and(f.cFileName[1].int == 0 or + result = f.cFileName[0].int == dot and (f.cFileName[1].int == 0 or f.cFileName[1].int == dot and f.cFileName[2].int == 0) proc existsFile*(filename: string): bool {.rtl, extern: "nos$1", @@ -1997,19 +1998,24 @@ proc getFileInfo*(path: string, followSymlink = true): FileInfo = proc isHidden*(path: string): bool = ## Determines whether a given path is hidden or not. Returns false if the - ## file doesn't exist. On Windows, a file is hidden if the file's 'hidden' - ## attribute is set. On Unix-like systems, a file is hidden if it starts - ## with a '.' ." + ## file doesn't exist. The given path must be accessible from the current + ## working directory of the program. + ## + ## On Windows, a file is hidden if the file's 'hidden' attribute is set. + ## On Unix-like systems, a file is hidden if it starts with a '.' (period) + ## and is not *just* '.' or '..' ' ." when defined(Windows): wrapUnary(attributes, getFileAttributesW, path) if attributes != -1'i32: result = (attributes and FILE_ATTRIBUTE_HIDDEN) != 0'i32 - else: - result = false else: if fileExists(path): - result = (path[0] == '.') - else: - result = false + let + fileName = extractFilename(path) + nameLen = len(fileName) + if nameLen == 2: + result = (fileName[0] == '.') and (fileName[1] != '.') + elif nameLen > 2: + result = (fileName[0] == '.') and (fileName[3] != '.') {.pop.} From dd806cafa0193acb9e79fdd47ec6810da3c48272 Mon Sep 17 00:00:00 2001 From: Araq Date: Mon, 11 Aug 2014 20:38:28 +0200 Subject: [PATCH 131/234] distinguish between 'defined' and 'declared' --- compiler/commands.nim | 3 +++ compiler/condsyms.nim | 46 ++++++++++++++++++++++++++++++++++++ compiler/llstream.nim | 2 +- compiler/nimrod.nim | 2 +- compiler/semexprs.nim | 14 +++++++---- compiler/testability.nim | 2 +- compiler/vm.nim | 4 +--- doc/basicopt.txt | 1 + lib/core/typeinfo.nim | 2 +- lib/impure/re.nim | 2 +- lib/pure/math.nim | 2 +- lib/pure/nimprof.nim | 10 ++++---- lib/pure/os.nim | 18 +++++++------- lib/pure/osproc.nim | 2 +- lib/pure/parseopt.nim | 4 ++-- lib/pure/parseopt2.nim | 2 +- lib/pure/pegs.nim | 2 +- lib/pure/unittest.nim | 6 ++--- lib/system.nim | 39 +++++++++++++++++------------- lib/system/ansi_c.nim | 4 ++-- lib/system/arithm.nim | 12 +++++----- lib/system/atomics.nim | 6 ++--- lib/system/channels.nim | 2 +- lib/system/deepcopy.nim | 2 +- lib/system/excpt.nim | 4 ++-- lib/system/gc.nim | 4 ++-- lib/system/gc2.nim | 2 +- lib/system/hti.nim | 2 +- lib/system/repr.nim | 12 +++++----- lib/system/sysspawn.nim | 2 +- lib/system/sysstr.nim | 4 ++-- lib/system/threads.nim | 12 +++++----- lib/system/widestrs.nim | 4 ++-- lib/wrappers/sdl/sdl_ttf.nim | 10 ++------ todo.txt | 2 +- web/news.txt | 4 ++++ 36 files changed, 155 insertions(+), 96 deletions(-) diff --git a/compiler/commands.nim b/compiler/commands.nim index 7219c168ad..c15cc674ca 100644 --- a/compiler/commands.nim +++ b/compiler/commands.nim @@ -315,6 +315,9 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) = of "undef", "u": expectArg(switch, arg, pass, info) undefSymbol(arg) + of "symbol": + expectArg(switch, arg, pass, info) + declareSymbol(arg) of "compile": expectArg(switch, arg, pass, info) if pass in {passCmd2, passPP}: processCompile(arg) diff --git a/compiler/condsyms.nim b/compiler/condsyms.nim index 76026a59d5..5eb951e26d 100644 --- a/compiler/condsyms.nim +++ b/compiler/condsyms.nim @@ -19,6 +19,9 @@ var gSymbols: PStringTable proc defineSymbol*(symbol: string) = gSymbols[symbol] = "true" +proc declareSymbol*(symbol: string) = + gSymbols[symbol] = "unknown" + proc undefSymbol*(symbol: string) = gSymbols[symbol] = "false" @@ -27,6 +30,7 @@ proc isDefined*(symbol: string): bool = result = gSymbols[symbol] == "true" proc isDefined*(symbol: PIdent): bool = isDefined(symbol.s) +proc isDeclared*(symbol: PIdent): bool = gSymbols.hasKey(symbol.s) iterator definedSymbolNames*: string = for key, val in pairs(gSymbols): @@ -37,6 +41,36 @@ proc countDefinedSymbols*(): int = for key, val in pairs(gSymbols): if val == "true": inc(result) +# For ease of bootstrapping, we keep there here and not in the global config +# file for now: +const + additionalSymbols = """ + x86 itanium x8664 + msdos mswindows win32 unix posix sunos bsd macintosh RISCOS doslike hpux + mac + + hppa hp9000 hp9000s300 hp9000s700 hp9000s800 hp9000s820 ELATE sparcv9 + + ecmascript js nimrodvm nimffi nimdoc cpp objc + gcc llvmgcc clang lcc bcc dmc wcc vcc tcc pcc ucc icl + boehmgc gcmarkandsweep gcgenerational nogc gcUseBitvectors + endb profiler + executable guiapp consoleapp library dll staticlib + + quick nimbabel + release debug + useWinAnsi useFork useNimRtl useMalloc useRealtimeGC ssl memProfiler + nodejs kwin + + usesysassert usegcassert tinyC useFFI + useStdoutAsStdmsg createNimRtl + booting fulldebug corruption nimsuperops noSignalHandler useGnuReadline + noCaas noDocGen noBusyWaiting nativeStackTrace useNodeIds selftest + reportMissedDeadlines avoidTimeMachine useClone ignoreAllocationSize + debugExecProcesses pcreDll useLipzipSrc + preventDeadlocks UNICODE winUnicode trackGcHeaders posixRealtime + """.split + proc initDefines*() = gSymbols = newStringTable(modeStyleInsensitive) defineSymbol("nimrod") # 'nimrod' is always defined @@ -53,6 +87,17 @@ proc initDefines*() = defineSymbol("nimparsebiggestfloatmagic") # add platform specific symbols: + for c in low(CPU)..high(CPU): + declareSymbol("cpu" & $CPU[c].bit) + declareSymbol(normalize(EndianToStr[CPU[c].endian])) + declareSymbol(CPU[c].name) + for o in low(platform.OS)..high(platform.OS): + declareSymbol(platform.OS[o].name) + + for a in additionalSymbols: + declareSymbol(a) + + # ----------------------------------------------------------- case targetCPU of cpuI386: defineSymbol("x86") of cpuIa64: defineSymbol("itanium") @@ -88,5 +133,6 @@ proc initDefines*() = defineSymbol(normalize(EndianToStr[CPU[targetCPU].endian])) defineSymbol(CPU[targetCPU].name) defineSymbol(platform.OS[targetOS].name) + declareSymbol("emulatedthreadvars") if platform.OS[targetOS].props.contains(ospLacksThreadVars): defineSymbol("emulatedthreadvars") diff --git a/compiler/llstream.nim b/compiler/llstream.nim index 86bfeaabd2..5aefd468aa 100644 --- a/compiler/llstream.nim +++ b/compiler/llstream.nim @@ -77,7 +77,7 @@ proc llStreamClose(s: PLLStream) = of llsFile: close(s.f) -when not defined(readLineFromStdin): +when not declared(readLineFromStdin): # fallback implementation: proc readLineFromStdin(prompt: string, line: var string): bool = stdout.write(prompt) diff --git a/compiler/nimrod.nim b/compiler/nimrod.nim index ea7621b095..618d98698f 100644 --- a/compiler/nimrod.nim +++ b/compiler/nimrod.nim @@ -79,7 +79,7 @@ proc handleCmdLine() = var ex = quoteShell(binPath) execExternalProgram(ex & ' ' & service.arguments) -when defined(GC_setMaxPause): +when declared(GC_setMaxPause): GC_setMaxPause 2_000 when compileOption("gc", "v2") or compileOption("gc", "refc"): diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 7e97eb293c..ad8554500a 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -1393,10 +1393,16 @@ proc semDefined(c: PContext, n: PNode, onlyCurrentScope: bool): PNode = checkSonsLen(n, 2) # we replace this node by a 'true' or 'false' node: result = newIntNode(nkIntLit, 0) - if lookUpForDefined(c, n.sons[1], onlyCurrentScope) != nil: - result.intVal = 1 - elif not onlyCurrentScope and (n.sons[1].kind == nkIdent) and - condsyms.isDefined(n.sons[1].ident): + if not onlyCurrentScope and considerQuotedIdent(n[0]).s == "defined": + if n.sons[1].kind != nkIdent: + localError(n.info, "obsolete usage of 'defined', use 'declared' instead") + elif condsyms.isDefined(n.sons[1].ident): + result.intVal = 1 + elif not condsyms.isDeclared(n.sons[1].ident): + message(n.info, warnUser, + "undeclared conditional symbol; use --symbol to declare it: " & + n[1].ident.s) + elif lookUpForDefined(c, n.sons[1], onlyCurrentScope) != nil: result.intVal = 1 result.info = n.info result.typ = getSysType(tyBool) diff --git a/compiler/testability.nim b/compiler/testability.nim index ceefd0a5e3..4587a53445 100644 --- a/compiler/testability.nim +++ b/compiler/testability.nim @@ -1,5 +1,5 @@ template tests*(body: stmt) {.immediate.} = when defined(selftest): - when not defined(unittest): import unittest + when not declared(unittest): import unittest body diff --git a/compiler/vm.nim b/compiler/vm.nim index aedbb92b43..a06d10f81a 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -87,9 +87,7 @@ proc bailOut(c: PCtx; tos: PStackFrame) = when not defined(nimComputedGoto): {.pragma: computedGoto.} -proc myreset(n: var TFullReg) = - when defined(system.reset): - reset(n) +proc myreset(n: var TFullReg) = reset(n) template ensureKind(k: expr) {.immediate, dirty.} = if regs[ra].kind != k: diff --git a/doc/basicopt.txt b/doc/basicopt.txt index 3a29b78298..fdb0e36e1c 100644 --- a/doc/basicopt.txt +++ b/doc/basicopt.txt @@ -13,6 +13,7 @@ Options: -p, --path:PATH add path to search paths -d, --define:SYMBOL define a conditional symbol -u, --undef:SYMBOL undefine a conditional symbol + --symbol:SYMBOL declare a conditional symbol -f, --forceBuild force rebuilding of all modules --stackTrace:on|off turn stack tracing on|off --lineTrace:on|off turn line tracing on|off diff --git a/lib/core/typeinfo.nim b/lib/core/typeinfo.nim index 57e11664b5..8df1b3dfbe 100644 --- a/lib/core/typeinfo.nim +++ b/lib/core/typeinfo.nim @@ -102,7 +102,7 @@ proc newAny(value: pointer, rawType: PNimType): TAny = result.value = value result.rawType = rawType -when defined(system.TVarSlot): +when declared(system.TVarSlot): proc toAny*(x: TVarSlot): TAny {.inline.} = ## constructs a ``TAny`` object from a variable slot ``x``. ## This captures `x`'s address, so `x` can be modified with its diff --git a/lib/impure/re.nim b/lib/impure/re.nim index f6511dab4a..ac07b2d6ba 100644 --- a/lib/impure/re.nim +++ b/lib/impure/re.nim @@ -243,7 +243,7 @@ template `=~` *(s: string, pattern: TRegex): expr = ## echo("syntax error") ## bind maxSubPatterns - when not definedInScope(matches): + when not declaredInScope(matches): var matches {.inject.}: array[0..MaxSubpatterns-1, string] match(s, pattern, matches) diff --git a/lib/pure/math.nim b/lib/pure/math.nim index 2f7a696b90..e76e96da5d 100644 --- a/lib/pure/math.nim +++ b/lib/pure/math.nim @@ -219,7 +219,7 @@ when not defined(JS): proc randomize(seed: int) = srand(cint(seed)) - when defined(srand48): srand48(seed) + when declared(srand48): srand48(seed) proc random(max: int): int = result = int(rand()) mod max diff --git a/lib/pure/nimprof.nim b/lib/pure/nimprof.nim index ab7cd1944d..6f94d0656a 100644 --- a/lib/pure/nimprof.nim +++ b/lib/pure/nimprof.nim @@ -26,7 +26,7 @@ const withThreads = compileOption("threads") tickCountCorrection = 50_000 -when not defined(system.TStackTrace): +when not declared(system.TStackTrace): type TStackTrace = array [0..20, cstring] # We use a simple hash table of bounded size to keep track of the stack traces: @@ -146,7 +146,7 @@ proc `//`(a, b: int): string = result = format("$1/$2 = $3%", a, b, formatFloat(a / b * 100.0, ffDefault, 2)) proc writeProfile() {.noconv.} = - when defined(system.TStackTrace): + when declared(system.TStackTrace): system.profilerHook = nil const filename = "profile_results.txt" echo "writing " & filename & "..." @@ -189,16 +189,16 @@ var disabled: int proc disableProfiling*() = - when defined(system.TStackTrace): + when declared(system.TStackTrace): atomicDec disabled system.profilerHook = nil proc enableProfiling*() = - when defined(system.TStackTrace): + when declared(system.TStackTrace): if atomicInc(disabled) >= 0: system.profilerHook = hook -when defined(system.TStackTrace): +when declared(system.TStackTrace): system.profilerHook = hook addQuitProc(writeProfile) diff --git a/lib/pure/os.nim b/lib/pure/os.nim index 44673d3e0f..13b9cab3f4 100644 --- a/lib/pure/os.nim +++ b/lib/pure/os.nim @@ -997,7 +997,7 @@ proc moveFile*(source, dest: string) {.rtl, extern: "nos$1", if c_rename(source, dest) != 0'i32: raise newException(EOS, $strerror(errno)) -when not defined(ENOENT) and not defined(Windows): +when not declared(ENOENT) and not defined(Windows): when NoFakeVars: const ENOENT = cint(2) # 2 on most systems including Solaris else: @@ -1615,11 +1615,11 @@ when defined(nimdoc): ## ## **Availability**: On Posix there is no portable way to get the command ## line from a DLL and thus the proc isn't defined in this environment. You - ## can test for its availability with `defined() `_. + ## can test for its availability with `declared() `_. ## Example: ## ## .. code-block:: nimrod - ## when defined(paramCount): + ## when declared(paramCount): ## # Use paramCount() here ## else: ## # Do something else! @@ -1638,11 +1638,11 @@ when defined(nimdoc): ## ## **Availability**: On Posix there is no portable way to get the command ## line from a DLL and thus the proc isn't defined in this environment. You - ## can test for its availability with `defined() `_. + ## can test for its availability with `declared() `_. ## Example: ## ## .. code-block:: nimrod - ## when defined(paramStr): + ## when declared(paramStr): ## # Use paramStr() here ## else: ## # Do something else! @@ -1682,7 +1682,7 @@ elif not defined(createNimRtl): # Docstring in nimdoc block. result = cmdCount-1 -when defined(paramCount) or defined(nimdoc): +when declared(paramCount) or defined(nimdoc): proc commandLineParams*(): seq[TaintedString] = ## Convenience proc which returns the command line parameters. ## @@ -1691,11 +1691,11 @@ when defined(paramCount) or defined(nimdoc): ## ## **Availability**: On Posix there is no portable way to get the command ## line from a DLL and thus the proc isn't defined in this environment. You - ## can test for its availability with `defined() `_. + ## can test for its availability with `declared() `_. ## Example: ## ## .. code-block:: nimrod - ## when defined(commandLineParams): + ## when declared(commandLineParams): ## # Use commandLineParams() here ## else: ## # Do something else! @@ -1714,7 +1714,7 @@ when defined(linux) or defined(solaris) or defined(bsd) or defined(aix): when not (defined(windows) or defined(macosx)): proc getApplHeuristic(): string = - when defined(paramStr): + when declared(paramStr): result = string(paramStr(0)) # POSIX guaranties that this contains the executable # as it has been executed by the calling process diff --git a/lib/pure/osproc.nim b/lib/pure/osproc.nim index c74fa1ceb6..3c181bf533 100644 --- a/lib/pure/osproc.nim +++ b/lib/pure/osproc.nim @@ -643,7 +643,7 @@ elif not defined(useNimRtl): data.workingDir = workingDir - when defined(posix_spawn) and not defined(useFork) and + when declared(posix_spawn) and not defined(useFork) and not defined(useClone) and not defined(linux): pid = startProcessAuxSpawn(data) else: diff --git a/lib/pure/parseopt.nim b/lib/pure/parseopt.nim index 68ae537c77..f43853fe68 100644 --- a/lib/pure/parseopt.nim +++ b/lib/pure/parseopt.nim @@ -37,7 +37,7 @@ type ## or the argument, ``value`` is not "" if ## the option was given a value -when defined(os.paramCount): +when declared(os.paramCount): # we cannot provide this for NimRtl creation on Posix, because we can't # access the command line arguments then! @@ -127,7 +127,7 @@ proc cmdLineRest*(p: TOptParser): TaintedString {. ## retrieves the rest of the command line that has not been parsed yet. result = strip(substr(p.cmd, p.pos, len(p.cmd) - 1)).TaintedString -when defined(initOptParser): +when declared(initOptParser): iterator getopt*(): tuple[kind: TCmdLineKind, key, val: TaintedString] = ## This is an convenience iterator for iterating over the command line. diff --git a/lib/pure/parseopt2.nim b/lib/pure/parseopt2.nim index 5e79d8a180..7638171d1d 100644 --- a/lib/pure/parseopt2.nim +++ b/lib/pure/parseopt2.nim @@ -119,7 +119,7 @@ proc cmdLineRest*(p: TOptParser): TaintedString {.rtl, extern: "npo$1", deprecat type TGetoptResult* = tuple[kind: TCmdLineKind, key, val: TaintedString] -when defined(paramCount): +when declared(paramCount): iterator getopt*(): TGetoptResult = ## This is an convenience iterator for iterating over the command line. ## This uses the TOptParser object. Example: diff --git a/lib/pure/pegs.nim b/lib/pure/pegs.nim index 68b1ab2237..efe169c1d1 100644 --- a/lib/pure/pegs.nim +++ b/lib/pure/pegs.nim @@ -870,7 +870,7 @@ template `=~`*(s: string, pattern: TPeg): bool = ## echo("syntax error") ## bind maxSubpatterns - when not definedInScope(matches): + when not declaredInScope(matches): var matches {.inject.}: array[0..MaxSubpatterns-1, string] match(s, pattern, matches) diff --git a/lib/pure/unittest.nim b/lib/pure/unittest.nim index f5640a1b4b..7cc95f0ad1 100644 --- a/lib/pure/unittest.nim +++ b/lib/pure/unittest.nim @@ -19,7 +19,7 @@ import macros -when defined(stdout): +when declared(stdout): import os when not defined(ECMAScript): @@ -99,7 +99,7 @@ template fail* = when not defined(ECMAScript): if AbortOnError: quit(1) - when defined(TestStatusIMPL): + when declared(TestStatusIMPL): TestStatusIMPL = FAILED else: program_result += 1 @@ -188,7 +188,7 @@ macro expect*(exceptions: varargs[expr], body: stmt): stmt {.immediate.} = result = getAst(expectBody(errorTypes, exp.lineinfo, body)) -when defined(stdout): +when declared(stdout): ## Reading settings var envOutLvl = os.getEnv("NIMTEST_OUTPUT_LVL").string diff --git a/lib/system.nim b/lib/system.nim index 1f09a6d2b0..03275b8faa 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -98,16 +98,8 @@ type proc defined*(x: expr): bool {.magic: "Defined", noSideEffect.} ## Special compile-time procedure that checks whether `x` is - ## defined. `x` has to be an identifier or a qualified identifier. - ## This can be used to check whether a library provides a certain - ## feature or not: - ## - ## .. code-block:: Nimrod - ## when not defined(strutils.toUpper): - ## # provide our own toUpper proc here, because strutils is - ## # missing it. - ## - ## You can also check external symbols introduced through the compiler's + ## defined. + ## `x` is an external symbol introduced through the compiler's ## `-d:x switch `_ to enable build time ## conditionals: ## @@ -116,13 +108,28 @@ proc defined*(x: expr): bool {.magic: "Defined", noSideEffect.} ## # Do here programmer friendly expensive sanity checks. ## # Put here the normal code +proc declared*(x: expr): bool {.magic: "Defined", noSideEffect.} + ## Special compile-time procedure that checks whether `x` is + ## declared. `x` has to be an identifier or a qualified identifier. + ## This can be used to check whether a library provides a certain + ## feature or not: + ## + ## .. code-block:: Nimrod + ## when not defined(strutils.toUpper): + ## # provide our own toUpper proc here, because strutils is + ## # missing it. + when defined(useNimRtl): {.deadCodeElim: on.} proc definedInScope*(x: expr): bool {. - magic: "DefinedInScope", noSideEffect.} + magic: "DefinedInScope", noSideEffect, deprecated.} + ## **Deprecated since version 0.9.6**: Use ``declaredInScope`` instead. + +proc declaredInScope*(x: expr): bool {. + magic: "DefinedInScope", noSideEffect, deprecated.} ## Special compile-time procedure that checks whether `x` is - ## defined in the current scope. `x` has to be an identifier. + ## declared in the current scope. `x` has to be an identifier. proc `not` *(x: bool): bool {.magic: "Not", noSideEffect.} ## Boolean not; returns true iff ``x == false``. @@ -2118,7 +2125,7 @@ template newException*(exceptn: typedesc, message: string): expr = when hostOS == "standalone": include panicoverride -when not defined(sysFatal): +when not declared(sysFatal): template sysFatal(exceptn: typedesc, message: string) = when hostOS == "standalone": panic(message) @@ -2170,7 +2177,7 @@ when not defined(JS): #and not defined(NimrodVM): # WARNING: This is very fragile! An array size of 8 does not work on my # Linux 64bit system. -- That's because the stack direction is the other # way round. - when defined(setStackBottom): + when declared(setStackBottom): var locals {.volatile.}: pointer locals = addr(locals) setStackBottom(locals) @@ -2443,7 +2450,7 @@ when not defined(JS): #and not defined(NimrodVM): hasRaiseAction: bool raiseAction: proc (e: ref E_Base): bool {.closure.} - when defined(initAllocator): + when declared(initAllocator): initAllocator() when hasThreadSupport: include "system/syslocks" @@ -3016,7 +3023,7 @@ proc compiles*(x): bool {.magic: "Compiles", noSideEffect.} = ## echo "'+' for integers is available" discard -when defined(initDebugger): +when declared(initDebugger): initDebugger() when hostOS != "standalone": diff --git a/lib/system/ansi_c.nim b/lib/system/ansi_c.nim index 511a006d30..e012697ae7 100644 --- a/lib/system/ansi_c.nim +++ b/lib/system/ansi_c.nim @@ -39,7 +39,7 @@ var c_stderr {.importc: "stderr", nodecl.}: C_TextFileStar # constants faked as variables: -when not defined(SIGINT): +when not declared(SIGINT): when NoFakeVars: when defined(windows): const @@ -132,7 +132,7 @@ proc c_realloc(p: pointer, newsize: int): pointer {. importc: "realloc", header: "".} when hostOS != "standalone": - when not defined(errno): + when not declared(errno): when defined(NimrodVM): var vmErrnoWrapper {.importc.}: ptr cint template errno: expr = diff --git a/lib/system/arithm.nim b/lib/system/arithm.nim index d9b3aebac1..bb15360fdb 100644 --- a/lib/system/arithm.nim +++ b/lib/system/arithm.nim @@ -241,26 +241,26 @@ elif false: # asmVersion and (defined(gcc) or defined(llvm_gcc)): """ # Platform independent versions of the above (slower!) -when not defined(addInt): +when not declared(addInt): proc addInt(a, b: int): int {.compilerProc, inline.} = result = a +% b if (result xor a) >= 0 or (result xor b) >= 0: return result raiseOverflow() -when not defined(subInt): +when not declared(subInt): proc subInt(a, b: int): int {.compilerProc, inline.} = result = a -% b if (result xor a) >= 0 or (result xor not b) >= 0: return result raiseOverflow() -when not defined(negInt): +when not declared(negInt): proc negInt(a: int): int {.compilerProc, inline.} = if a != low(int): return -a raiseOverflow() -when not defined(divInt): +when not declared(divInt): proc divInt(a, b: int): int {.compilerProc, inline.} = if b == 0: raiseDivByZero() @@ -268,13 +268,13 @@ when not defined(divInt): raiseOverflow() return a div b -when not defined(modInt): +when not declared(modInt): proc modInt(a, b: int): int {.compilerProc, inline.} = if b == 0: raiseDivByZero() return a mod b -when not defined(mulInt): +when not declared(mulInt): # # This code has been inspired by Python's source code. # The native int product x*y is either exactly right or *way* off, being diff --git a/lib/system/atomics.nim b/lib/system/atomics.nim index 82ec5dbdeb..695a5f63e0 100644 --- a/lib/system/atomics.nim +++ b/lib/system/atomics.nim @@ -174,7 +174,7 @@ proc atomicInc*(memLoc: var int, x: int = 1): int = proc atomicDec*(memLoc: var int, x: int = 1): int = when defined(gcc) and hasThreadSupport: - when defined(atomic_sub_fetch): + when declared(atomic_sub_fetch): result = atomic_sub_fetch(memLoc.addr, x, ATOMIC_RELAXED) else: result = atomic_add_fetch(memLoc.addr, -x, ATOMIC_RELAXED) @@ -201,14 +201,14 @@ when (defined(x86) or defined(amd64)) and (defined(gcc) or defined(llvm_gcc)): {.emit: """asm volatile("pause" ::: "memory");""".} elif (defined(x86) or defined(amd64)) and defined(vcc): proc cpuRelax {.importc: "YieldProcessor", header: "".} -elif defined(intelc): +elif defined(icl): proc cpuRelax {.importc: "_mm_pause", header: "xmmintrin.h".} elif false: from os import sleep proc cpuRelax {.inline.} = os.sleep(1) -when not defined(fence) and hasThreadSupport: +when not declared(fence) and hasThreadSupport: # XXX fixme proc fence*() {.inline.} = var dummy: bool diff --git a/lib/system/channels.nim b/lib/system/channels.nim index e5535dbdc8..df46922e4e 100644 --- a/lib/system/channels.nim +++ b/lib/system/channels.nim @@ -14,7 +14,7 @@ ## **Note:** The current implementation of message passing is slow and does ## not work with cyclic data structures. -when not defined(NimString): +when not declared(NimString): {.error: "You must not import this module explicitly".} type diff --git a/lib/system/deepcopy.nim b/lib/system/deepcopy.nim index bd8d005275..e7eb1cdb42 100644 --- a/lib/system/deepcopy.nim +++ b/lib/system/deepcopy.nim @@ -93,7 +93,7 @@ proc genericDeepCopyAux(dest, src: pointer, mt: PNimType) = if s2 == nil: unsureAsgnRef(cast[PPointer](dest), s2) return - when defined(usrToCell): + when declared(usrToCell): # unfortunately we only have cycle detection for our native GCs. let x = usrToCell(s2) let forw = cast[int](x.typ) diff --git a/lib/system/excpt.nim b/lib/system/excpt.nim index e1a5a958fe..c3586be0f3 100644 --- a/lib/system/excpt.nim +++ b/lib/system/excpt.nim @@ -307,7 +307,7 @@ when not defined(noSignalHandler): action("SIGBUS: Illegal storage access. (Attempt to read from nil?)\n") else: block platformSpecificSignal: - when defined(SIGPIPE): + when declared(SIGPIPE): if s == SIGPIPE: action("SIGPIPE: Pipe closed.\n") break platformSpecificSignal @@ -336,7 +336,7 @@ when not defined(noSignalHandler): c_signal(SIGFPE, signalHandler) c_signal(SIGILL, signalHandler) c_signal(SIGBUS, signalHandler) - when defined(SIGPIPE): + when declared(SIGPIPE): c_signal(SIGPIPE, signalHandler) registerSignalHandler() # call it in initialization section diff --git a/lib/system/gc.nim b/lib/system/gc.nim index 3b85fe6002..0c1fc7748d 100644 --- a/lib/system/gc.nim +++ b/lib/system/gc.nim @@ -30,7 +30,7 @@ const # cycles instead of the complex # algorithm -when withRealTime and not defined(getTicks): +when withRealTime and not declared(getTicks): include "system/timers" when defined(memProfiler): proc nimProfile(requestedSize: int) @@ -413,7 +413,7 @@ proc addNewObjToZCT(res: PCell, gch: var TGcHeap) {.inline.} = {.push stackTrace: off, profiler:off.} proc gcInvariant*() = sysAssert(allocInv(gch.region), "injected") - when defined(markForDebug): + when declared(markForDebug): markForDebug(gch) {.pop.} diff --git a/lib/system/gc2.nim b/lib/system/gc2.nim index 31c99a601c..132da9885b 100644 --- a/lib/system/gc2.nim +++ b/lib/system/gc2.nim @@ -26,7 +26,7 @@ const # this seems to be a good value withRealTime = defined(useRealtimeGC) -when withRealTime and not defined(getTicks): +when withRealTime and not declared(getTicks): include "system/timers" when defined(memProfiler): proc nimProfile(requestedSize: int) diff --git a/lib/system/hti.nim b/lib/system/hti.nim index 5689f92b36..ef8f50831d 100644 --- a/lib/system/hti.nim +++ b/lib/system/hti.nim @@ -7,7 +7,7 @@ # distribution, for details about the copyright. # -when defined(NimString): +when declared(NimString): # we are in system module: {.pragma: codegenType, compilerproc.} else: diff --git a/lib/system/repr.nim b/lib/system/repr.nim index f8f9496680..d6df61fd3a 100644 --- a/lib/system/repr.nim +++ b/lib/system/repr.nim @@ -121,7 +121,7 @@ proc reprSet(p: pointer, typ: PNimType): string {.compilerRtl.} = type TReprClosure {.final.} = object # we cannot use a global variable here # as this wouldn't be thread-safe - when defined(TCellSet): + when declared(TCellSet): marked: TCellSet recdepth: int # do not recurse endlessly indent: int # indentation @@ -130,16 +130,16 @@ when not defined(useNimRtl): proc initReprClosure(cl: var TReprClosure) = # Important: cellsets does not lock the heap when doing allocations! We # have to do it here ... - when hasThreadSupport and hasSharedHeap and defined(heapLock): + when hasThreadSupport and hasSharedHeap and declared(heapLock): AcquireSys(HeapLock) - when defined(TCellSet): + when declared(TCellSet): init(cl.marked) cl.recdepth = -1 # default is to display everything! cl.indent = 0 proc deinitReprClosure(cl: var TReprClosure) = - when defined(TCellSet): deinit(cl.marked) - when hasThreadSupport and hasSharedHeap and defined(heapLock): + when declared(TCellSet): deinit(cl.marked) + when hasThreadSupport and hasSharedHeap and declared(heapLock): ReleaseSys(HeapLock) proc reprBreak(result: var string, cl: TReprClosure) = @@ -201,7 +201,7 @@ when not defined(useNimRtl): proc reprRef(result: var string, p: pointer, typ: PNimType, cl: var TReprClosure) = # we know that p is not nil here: - when defined(TCellSet): + when declared(TCellSet): when defined(boehmGC) or defined(nogc): var cell = cast[PCell](p) else: diff --git a/lib/system/sysspawn.nim b/lib/system/sysspawn.nim index 95cdba65d1..5161104a9f 100644 --- a/lib/system/sysspawn.nim +++ b/lib/system/sysspawn.nim @@ -9,7 +9,7 @@ ## Implements Nimrod's 'spawn'. -when not defined(NimString): +when not declared(NimString): {.error: "You must not import this module explicitly".} {.push stackTrace:off.} diff --git a/lib/system/sysstr.nim b/lib/system/sysstr.nim index 9db8ce378e..bc79bb254d 100644 --- a/lib/system/sysstr.nim +++ b/lib/system/sysstr.nim @@ -32,7 +32,7 @@ proc eqStrings(a, b: NimString): bool {.inline, compilerProc.} = return a.len == b.len and c_memcmp(a.data, b.data, a.len * sizeof(char)) == 0'i32 -when defined(allocAtomic): +when declared(allocAtomic): template allocStr(size: expr): expr = cast[NimString](allocAtomic(size)) else: @@ -85,7 +85,7 @@ proc copyStringRC1(src: NimString): NimString {.compilerRtl.} = if src != nil: var s = src.space if s < 8: s = 7 - when defined(newObjRC1): + when declared(newObjRC1): result = cast[NimString](newObjRC1(addr(strDesc), sizeof(TGenericSeq) + s+1)) else: diff --git a/lib/system/threads.nim b/lib/system/threads.nim index d3b3aa457e..4717659e5f 100644 --- a/lib/system/threads.nim +++ b/lib/system/threads.nim @@ -39,7 +39,7 @@ ## createThread(thr[i], threadFunc, (i*10, i*10+5)) ## joinThreads(thr) -when not defined(NimString): +when not declared(NimString): {.error: "You must not import this module explicitly".} const @@ -267,7 +267,7 @@ when not defined(boehmgc) and not hasSharedHeap: proc deallocOsPages() template threadProcWrapperBody(closure: expr) {.immediate.} = - when defined(globalsSlot): ThreadVarSetValue(globalsSlot, closure) + when declared(globalsSlot): ThreadVarSetValue(globalsSlot, closure) var t = cast[ptr TThread[TArg]](closure) when useStackMaskHack: var tls: TThreadLocalStorage @@ -275,13 +275,13 @@ template threadProcWrapperBody(closure: expr) {.immediate.} = # init the GC for this thread: setStackBottom(addr(t)) initGC() - when defined(registerThread): + when declared(registerThread): t.stackBottom = addr(t) registerThread(t) when TArg is void: t.dataFn() else: t.dataFn(t.data) - when defined(registerThread): unregisterThread(t) - when defined(deallocOsPages): deallocOsPages() + when declared(registerThread): unregisterThread(t) + when declared(deallocOsPages): deallocOsPages() # Since an unhandled exception terminates the whole process (!), there is # no need for a ``try finally`` here, nor would it be correct: The current # exception is tried to be re-raised by the code-gen after the ``finally``! @@ -332,7 +332,7 @@ when false: discard TerminateThread(t.sys, 1'i32) else: discard pthread_cancel(t.sys) - when defined(registerThread): unregisterThread(addr(t)) + when declared(registerThread): unregisterThread(addr(t)) t.dataFn = nil proc createThread*[TArg](t: var TThread[TArg], diff --git a/lib/system/widestrs.nim b/lib/system/widestrs.nim index e9673888c2..cd64ff410e 100644 --- a/lib/system/widestrs.nim +++ b/lib/system/widestrs.nim @@ -10,7 +10,7 @@ # Nimrod support for C/C++'s `wide strings`:idx:. This is part of the system # module! Do not import it directly! -when not defined(NimString): +when not declared(NimString): {.error: "You must not import this module explicitly".} type @@ -103,7 +103,7 @@ proc newWideCString*(source: cstring, L: int): WideCString = proc newWideCString*(s: cstring): WideCString = if s.isNil: return nil - when not defined(c_strlen): + when not declared(c_strlen): proc c_strlen(a: cstring): int {. header: "", noSideEffect, importc: "strlen".} diff --git a/lib/wrappers/sdl/sdl_ttf.nim b/lib/wrappers/sdl/sdl_ttf.nim index f501e31d83..45247df4dc 100644 --- a/lib/wrappers/sdl/sdl_ttf.nim +++ b/lib/wrappers/sdl/sdl_ttf.nim @@ -333,11 +333,5 @@ proc VERSION*(X: var sdl.Tversion) = X.patch = PATCHLEVEL -when not (defined(Workaround_RenderText_Solid)): - proc RenderText_Solid*(font: PFont, text: cstring, fg: TColor): PSurface{. - cdecl, importc: "TTF_RenderText_Solid", dynlib: ttfLibName.} -else: - proc RenderText_Solid(font: PFont, text: cstring, fg: TColor): PSurface = - var Black: TColor # initialized to zero - result = RenderText_Shaded(font, text, fg, Black) - +proc RenderText_Solid*(font: PFont, text: cstring, fg: TColor): PSurface{. + cdecl, importc: "TTF_RenderText_Solid", dynlib: ttfLibName.} diff --git a/todo.txt b/todo.txt index 6ae5df509c..05426d71da 100644 --- a/todo.txt +++ b/todo.txt @@ -8,7 +8,7 @@ version 0.9.6 Concurrency ----------- -- 'gcsafe' inferrence needs to be fixed +- 'gcsafe' inference needs to be fixed - 'deepCopy' needs to be instantiated for generics *when the type is constructed* - test 'deepCopy' diff --git a/web/news.txt b/web/news.txt index 20e2412212..3af154be3f 100644 --- a/web/news.txt +++ b/web/news.txt @@ -23,6 +23,9 @@ News - The ``destructor`` pragma has been deprecated. Use the ``override`` pragma instead. The destructor's name has to be ``destroy`` now. - ``lambda`` is not a keyword anymore. + - **system.defined has been split into system.defined and system.declared**. + You have to use ``--symbol`` to declare new conditional symbols that can be + set via ``--define``. Language Additions ------------------ @@ -39,6 +42,7 @@ News - Added ``algorithm.reversed`` - Added ``uri.combine`` and ``uri.parseUri``. + 2014-04-21 Version 0.9.4 released ================================= From 61a6ecfd94140f8f6546eb008ccf1bfd5422e2ef Mon Sep 17 00:00:00 2001 From: def Date: Mon, 11 Aug 2014 21:05:21 +0200 Subject: [PATCH 132/234] Move newSeqWith to sequtils --- lib/pure/collections/sequtils.nim | 24 ++++++++++++++++++++++++ lib/system.nim | 17 ----------------- 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/lib/pure/collections/sequtils.nim b/lib/pure/collections/sequtils.nim index c50c4165b0..2629e9f407 100644 --- a/lib/pure/collections/sequtils.nim +++ b/lib/pure/collections/sequtils.nim @@ -409,6 +409,23 @@ template mapIt*(varSeq, pred: expr) = let it {.inject.} = varSeq[i] varSeq[i] = pred +template newSeqWith*(len: int, init: expr): expr = + ## creates a new sequence, calling `init` to initialize each value. Example: + ## + ## .. code-block:: nimrod + ## var seq2D = newSeqWith(20, newSeq[bool](10)) + ## seq2D[0][0] = true + ## seq2D[1][0] = true + ## seq2D[0][1] = true + ## + ## import math + ## var seqRand = newSeqWith(20, random(10)) + ## echo seqRand + var result {.gensym.} = newSeq[type(init)](len) + for i in 0 .. Date: Mon, 11 Aug 2014 20:47:38 +0100 Subject: [PATCH 133/234] Fixes incorrect macro stack traces. --- compiler/vm.nim | 11 ++++++++++- compiler/vmdef.nim | 4 +++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/compiler/vm.nim b/compiler/vm.nim index a06d10f81a..e40acca6ca 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -1078,6 +1078,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = of opcNKind: decodeB(rkInt) regs[ra].intVal = ord(regs[rb].node.kind) + c.comesFromHeuristic = regs[rb].node.info of opcNIntVal: decodeB(rkInt) let a = regs[rb].node @@ -1253,8 +1254,16 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = internalError(c.debug[pc], "request to create a NimNode of invalid kind") let cc = regs[rc].node + regs[ra].node = newNodeI(TNodeKind(int(k)), - if cc.kind == nkNilLit: c.debug[pc] else: cc.info) + if cc.kind != nkNilLit: + cc.info + elif c.comesFromHeuristic.line > -1: + c.comesFromHeuristic + elif c.callsite != nil and c.callsite.safeLen > 1: + c.callsite[1].info + else: + c.debug[pc]) regs[ra].node.flags.incl nfIsRef of opcNCopyNimNode: decodeB(rkNode) diff --git a/compiler/vmdef.nim b/compiler/vmdef.nim index 873d8eebd9..cad48abeae 100644 --- a/compiler/vmdef.nim +++ b/compiler/vmdef.nim @@ -188,6 +188,7 @@ type features*: TSandboxFlags traceActive*: bool loopIterations*: int + comesFromHeuristic*: TLineInfo # Heuristic for better macro stack traces TPosition* = distinct int @@ -196,7 +197,8 @@ type proc newCtx*(module: PSym): PCtx = PCtx(code: @[], debug: @[], globals: newNode(nkStmtListExpr), constants: newNode(nkStmtList), types: @[], - prc: PProc(blocks: @[]), module: module, loopIterations: MaxLoopIterations) + prc: PProc(blocks: @[]), module: module, loopIterations: MaxLoopIterations, + comesFromHeuristic: unknownLineInfo()) proc refresh*(c: PCtx, module: PSym) = c.module = module From 05dbba0e3899d86a4f7dbc6e81b1b5f9771aa2e0 Mon Sep 17 00:00:00 2001 From: Araq Date: Tue, 12 Aug 2014 00:22:14 +0200 Subject: [PATCH 134/234] fixes #1431 --- compiler/semexprs.nim | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 510efb530f..aadcdb2f49 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -1768,8 +1768,9 @@ proc checkPar(n: PNode): TParKind = var length = sonsLen(n) if length == 0: result = paTuplePositions # () - elif length == 1: - result = paSingle # (expr) + elif length == 1: + if n.sons[0].kind == nkExprColonExpr: result = paTupleFields + else: result = paSingle # (expr) else: if n.sons[0].kind == nkExprColonExpr: result = paTupleFields else: result = paTuplePositions From b8ce3a41753fa3aeeeee1e91401e9909d63cfbe7 Mon Sep 17 00:00:00 2001 From: Araq Date: Tue, 12 Aug 2014 08:47:31 +0200 Subject: [PATCH 135/234] fixes 'gcsafe' --- compiler/astalgo.nim | 11 +++++++++++ compiler/options.nim | 2 +- compiler/sempass2.nim | 29 +++++++++++++++++------------ lib/system.nim | 12 ++++++------ tests/effects/teffects1.nim | 2 +- tests/effects/tgcsafe.nim | 16 ++++++++++++++++ todo.txt | 2 -- web/news.txt | 4 ++++ 8 files changed, 56 insertions(+), 22 deletions(-) create mode 100644 tests/effects/tgcsafe.nim diff --git a/compiler/astalgo.nim b/compiler/astalgo.nim index dbf13f7640..3431aaf418 100644 --- a/compiler/astalgo.nim +++ b/compiler/astalgo.nim @@ -124,6 +124,17 @@ proc skipConv*(n: PNode): PNode = result = n.sons[1] else: result = n +proc skipConvAndClosure*(n: PNode): PNode = + result = n + while true: + case result.kind + of nkObjUpConv, nkObjDownConv, nkChckRange, nkChckRangeF, nkChckRange64, + nkClosure: + result = result.sons[0] + of nkHiddenStdConv, nkHiddenSubConv, nkConv: + result = result.sons[1] + else: break + proc skipConvTakeType*(n: PNode): PNode = result = n.skipConv result.typ = n.typ diff --git a/compiler/options.nim b/compiler/options.nim index 58a340d213..02719cacce 100644 --- a/compiler/options.nim +++ b/compiler/options.nim @@ -95,7 +95,7 @@ var optBoundsCheck, optOverflowCheck, optAssert, optWarns, optHints, optStackTrace, optLineTrace, optPatterns, optNilCheck} - gGlobalOptions*: TGlobalOptions = {} + gGlobalOptions*: TGlobalOptions = {optThreadAnalysis} gExitcode*: int8 gCmd*: TCommands = cmdNone # the command gSelectedGC* = gcRefc # the selected GC diff --git a/compiler/sempass2.nim b/compiler/sempass2.nim index c8ce5e7875..acc2425f14 100644 --- a/compiler/sempass2.nim +++ b/compiler/sempass2.nim @@ -115,7 +115,7 @@ proc useVar(a: PEffects, n: PNode) = a.addUse(copyNode(n)) if (tfHasGCedMem in s.typ.flags or s.typ.isGCedMem) and tfGcSafe notin s.typ.flags: - message(n.info, warnGcUnsafe, renderTree(n)) + if warnGcUnsafe in gNotes: message(n.info, warnGcUnsafe, renderTree(n)) a.gcUnsafe = true type @@ -332,7 +332,7 @@ proc propagateEffects(tracked: PEffects, n: PNode, s: PSym) = mergeTags(tracked, tagSpec, n) if notGcSafe(s.typ) and sfImportc notin s.flags: - message(n.info, warnGcUnsafe, renderTree(n)) + if warnGcUnsafe in gNotes: message(n.info, warnGcUnsafe, renderTree(n)) tracked.gcUnsafe = true when trackGlobals: @@ -358,7 +358,7 @@ proc notNilCheck(tracked: PEffects, n: PNode, paramType: PType) = of impYes: discard proc trackOperand(tracked: PEffects, n: PNode, paramType: PType) = - let op = n.typ + let op = skipConvAndClosure(n).typ if op != nil and op.kind == tyProc and n.kind != nkNilLit: internalAssert op.n.sons[0].kind == nkEffectList var effectList = op.n.sons[0] @@ -367,21 +367,24 @@ proc trackOperand(tracked: PEffects, n: PNode, paramType: PType) = propagateEffects(tracked, n, s.sym) elif effectList.len == 0: if isForwardedProc(n): + # we have no explicit effects but it's a forward declaration and so it's + # stated there are no additional effects, so simply propagate them: propagateEffects(tracked, n, n.sym) else: + # we have no explicit effects so assume the worst: addEffect(tracked, createRaise(n)) addTag(tracked, createTag(n)) when trackGlobals: addUse(tracked, createAnyGlobal(n)) - # assume GcUnsafe unless in its type: - if notGcSafe(op): - message(n.info, warnGcUnsafe, renderTree(n)) + # assume GcUnsafe unless in its type; 'forward' does not matter: + if notGcSafe(op): + if warnGcUnsafe in gNotes: message(n.info, warnGcUnsafe, renderTree(n)) tracked.gcUnsafe = true else: mergeEffects(tracked, effectList.sons[exceptionEffects], n) mergeTags(tracked, effectList.sons[tagEffects], n) when trackGlobals: mergeUses(tracked, effectList.sons[usesEffects], n) if notGcSafe(op): - message(n.info, warnGcUnsafe, renderTree(n)) + if warnGcUnsafe in gNotes: message(n.info, warnGcUnsafe, renderTree(n)) tracked.gcUnsafe = true notNilCheck(tracked, n, paramType) @@ -510,9 +513,6 @@ proc track(tracked: PEffects, n: PNode) = if op != nil and op.kind == tyProc and op.n.sons[0].kind == nkEffectList: if a.kind == nkSym and a.sym == tracked.owner: tracked.isRecursive = true - elif notGcSafe(op) and not importedFromC(a): - message(n.info, warnGcUnsafe, renderTree(n)) - tracked.gcUnsafe = true var effectList = op.n.sons[0] if a.kind == nkSym and a.sym.kind == skMethod: propagateEffects(tracked, n, a.sym) @@ -528,6 +528,11 @@ proc track(tracked: PEffects, n: PNode) = mergeEffects(tracked, effectList.sons[exceptionEffects], n) mergeTags(tracked, effectList.sons[tagEffects], n) when trackGlobals: mergeUses(tracked, effectList.sons[usesEffects], n) + if notGcSafe(op) and not importedFromC(a): + # and it's not a recursive call: + if not (a.kind == nkSym and a.sym == tracked.owner): + message(n.info, warnGcUnsafe, renderTree(n)) + tracked.gcUnsafe = true for i in 1 .. Date: Tue, 12 Aug 2014 10:11:58 +0200 Subject: [PATCH 136/234] fix failed tests due to gcsafe --- lib/pure/ftpclient.nim | 67 ++++++++++++++++---------------- lib/pure/ropes.nim | 4 +- lib/pure/subexes.nim | 3 +- lib/system.nim | 4 +- lib/system/excpt.nim | 6 +-- tests/async/tasyncexceptions.nim | 18 +++++---- tests/async/tasynciossl.nim | 3 +- 7 files changed, 55 insertions(+), 50 deletions(-) diff --git a/lib/pure/ftpclient.nim b/lib/pure/ftpclient.nim index 53f6688b9b..d4922d1abe 100644 --- a/lib/pure/ftpclient.nim +++ b/lib/pure/ftpclient.nim @@ -588,39 +588,40 @@ proc register*(d: PDispatcher, ftp: PAsyncFTPClient): PDelegate {.discardable.} return ftp.disp.register(ftp.asyncCSock) when isMainModule: - var d = newDispatcher() - let hev = - proc (ftp: PAsyncFTPClient, event: TFTPEvent) = - case event.typ - of EvStore: - echo("Upload finished!") - ftp.retrFile("payload.JPG", "payload2.JPG", async = true) - of EvTransferProgress: - var time: int64 = -1 - if event.speed != 0: - time = (event.bytesTotal - event.bytesFinished) div event.speed - echo(event.currentJob) - echo(event.speed div 1000, " kb/s. - ", - event.bytesFinished, "/", event.bytesTotal, - " - ", time, " seconds") - echo(d.len) - of EvRetr: - echo("Download finished!") - ftp.close() - echo d.len - else: assert(false) - var ftp = asyncFTPClient("picheta.me", user = "test", pass = "asf", handleEvent = hev) - - d.register(ftp) - d.len.echo() - ftp.connect() - echo "connected" - ftp.store("payload.JPG", "payload.JPG", async = true) - d.len.echo() - echo "uploading..." - while true: - if not d.poll(): break - + proc main = + var d = newDispatcher() + let hev = + proc (ftp: PAsyncFTPClient, event: TFTPEvent) = + case event.typ + of EvStore: + echo("Upload finished!") + ftp.retrFile("payload.JPG", "payload2.JPG", async = true) + of EvTransferProgress: + var time: int64 = -1 + if event.speed != 0: + time = (event.bytesTotal - event.bytesFinished) div event.speed + echo(event.currentJob) + echo(event.speed div 1000, " kb/s. - ", + event.bytesFinished, "/", event.bytesTotal, + " - ", time, " seconds") + echo(d.len) + of EvRetr: + echo("Download finished!") + ftp.close() + echo d.len + else: assert(false) + var ftp = asyncFTPClient("picheta.me", user = "test", pass = "asf", handleEvent = hev) + + d.register(ftp) + d.len.echo() + ftp.connect() + echo "connected" + ftp.store("payload.JPG", "payload.JPG", async = true) + d.len.echo() + echo "uploading..." + while true: + if not d.poll(): break + main() when isMainModule and false: var ftp = ftpClient("picheta.me", user = "asdasd", pass = "asfwq") diff --git a/lib/pure/ropes.nim b/lib/pure/ropes.nim index 4a6c3f5306..eb3792bcea 100644 --- a/lib/pure/ropes.nim +++ b/lib/pure/ropes.nim @@ -58,8 +58,8 @@ proc newRope(data: string): PRope = result.data = data var - cache: PRope # the root of the cache tree - N: PRope # dummy rope needed for splay algorithm + cache {.threadvar.}: PRope # the root of the cache tree + N {.threadvar.}: PRope # dummy rope needed for splay algorithm when countCacheMisses: var misses, hits: int diff --git a/lib/pure/subexes.nim b/lib/pure/subexes.nim index 92797744a4..ed87610d61 100644 --- a/lib/pure/subexes.nim +++ b/lib/pure/subexes.nim @@ -84,7 +84,8 @@ proc getFormatArg(p: var TFormatParser, a: openArray[string]): int = if result >=% a.len: raiseInvalidFormat("index out of bounds: " & $result) p.i = i -proc scanDollar(p: var TFormatParser, a: openarray[string], s: var string) +proc scanDollar(p: var TFormatParser, a: openarray[string], s: var string) {. + noSideEffect.} proc emitChar(p: var TFormatParser, x: var string, ch: char) {.inline.} = x.add(ch) diff --git a/lib/system.nim b/lib/system.nim index 66eda57414..3dc7e308e5 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -2567,11 +2567,11 @@ when not defined(JS): #and not defined(NimrodVM): include "system/assign" include "system/repr" - proc getCurrentException*(): ref E_Base {.compilerRtl, inl.} = + proc getCurrentException*(): ref E_Base {.compilerRtl, inl, gcsafe.} = ## retrieves the current exception; if there is none, nil is returned. result = currException - proc getCurrentExceptionMsg*(): string {.inline.} = + proc getCurrentExceptionMsg*(): string {.inline, gcsafe.} = ## retrieves the error message that was attached to the current ## exception; if there is none, "" is returned. var e = getCurrentException() diff --git a/lib/system/excpt.nim b/lib/system/excpt.nim index c3586be0f3..3c5436afb5 100644 --- a/lib/system/excpt.nim +++ b/lib/system/excpt.nim @@ -38,11 +38,11 @@ proc chckRangeF(x, a, b: float): float {.inline, compilerproc, gcsafe.} proc chckNil(p: pointer) {.noinline, compilerproc, gcsafe.} var - framePtr {.rtlThreadVar.}: PFrame - excHandler {.rtlThreadVar.}: PSafePoint + framePtr {.threadvar.}: PFrame + excHandler {.threadvar.}: PSafePoint # list of exception handlers # a global variable for the root of all try blocks - currException {.rtlThreadVar.}: ref E_Base + currException {.threadvar.}: ref E_Base proc popFrame {.compilerRtl, inl.} = framePtr = framePtr.prev diff --git a/tests/async/tasyncexceptions.nim b/tests/async/tasyncexceptions.nim index 9474fbae8a..ca73c6a3d1 100644 --- a/tests/async/tasyncexceptions.nim +++ b/tests/async/tasyncexceptions.nim @@ -28,11 +28,13 @@ proc serve() {.async.} = await processClient(fut) when isMainModule: - var fut = serve() - fut.callback = - proc () = - if fut.failed: - # This test ensures that this exception crashes the application - # as it is not handled. - raise fut.error - runForever() + proc main = + var fut = serve() + fut.callback = + proc () = + if fut.failed: + # This test ensures that this exception crashes the application + # as it is not handled. + raise fut.error + runForever() + main() diff --git a/tests/async/tasynciossl.nim b/tests/async/tasynciossl.nim index 26c4c587c8..6b38fcf7b1 100644 --- a/tests/async/tasynciossl.nim +++ b/tests/async/tasynciossl.nim @@ -5,7 +5,8 @@ discard """ """ import sockets, asyncio, strutils, times -var disp = newDispatcher() +var disp {.threadvar.}: PDispatcher +disp = newDispatcher() var msgCount = 0 when defined(ssl): From 1ee87b88ee90fe563fbe047e9d8dcdd972f87fbf Mon Sep 17 00:00:00 2001 From: Araq Date: Tue, 12 Aug 2014 22:38:10 +0200 Subject: [PATCH 137/234] asyncio compiles again --- lib/pure/asyncio.nim | 43 ++++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/lib/pure/asyncio.nim b/lib/pure/asyncio.nim index c68ca4350e..6b67bf4b5a 100644 --- a/lib/pure/asyncio.nim +++ b/lib/pure/asyncio.nim @@ -671,25 +671,26 @@ when isMainModule: testRead(s, 2) disp.register(client) - var d = newDispatcher() - - var s = AsyncSocket() - s.connect("amber.tenthbit.net", TPort(6667)) - s.handleConnect = - proc (s: PAsyncSocket) = - testConnect(s, 1) - s.handleRead = - proc (s: PAsyncSocket) = - testRead(s, 1) - d.register(s) - - var server = AsyncSocket() - server.handleAccept = - proc (s: PAsyncSocket) = - testAccept(s, d, 78) - server.bindAddr(TPort(5555)) - server.listen() - d.register(server) - - while d.poll(-1): discard + proc main = + var d = newDispatcher() + var s = AsyncSocket() + s.connect("amber.tenthbit.net", TPort(6667)) + s.handleConnect = + proc (s: PAsyncSocket) = + testConnect(s, 1) + s.handleRead = + proc (s: PAsyncSocket) = + testRead(s, 1) + d.register(s) + + var server = AsyncSocket() + server.handleAccept = + proc (s: PAsyncSocket) = + testAccept(s, d, 78) + server.bindAddr(TPort(5555)) + server.listen() + d.register(server) + + while d.poll(-1): discard + main() From 62e454f41beb5a742dbb8137198629fdc1f1153a Mon Sep 17 00:00:00 2001 From: Araq Date: Wed, 13 Aug 2014 01:16:18 +0200 Subject: [PATCH 138/234] asynchttpserver compiles again; made some tests green --- .../ios/scripts/xcode_prebuild.sh | 0 lib/pure/asynchttpserver.nim | 22 ++++++++++--------- tests/system/toString.nim | 8 +++---- tests/threads/tthreadanalysis.nim | 4 ++-- tests/threads/tthreadheapviolation1.nim | 4 ++-- 5 files changed, 19 insertions(+), 19 deletions(-) mode change 100755 => 100644 examples/cross_calculator/ios/scripts/xcode_prebuild.sh diff --git a/examples/cross_calculator/ios/scripts/xcode_prebuild.sh b/examples/cross_calculator/ios/scripts/xcode_prebuild.sh old mode 100755 new mode 100644 diff --git a/lib/pure/asynchttpserver.nim b/lib/pure/asynchttpserver.nim index e5992e36fb..26e3a2a7b8 100644 --- a/lib/pure/asynchttpserver.nim +++ b/lib/pure/asynchttpserver.nim @@ -184,7 +184,7 @@ proc processClient(client: PAsyncSocket, address: string, break proc serve*(server: PAsyncHttpServer, port: TPort, - callback: proc (request: TRequest): PFuture[void], + callback: proc (request: TRequest): PFuture[void] {.gcsafe.}, address = "") {.async.} = ## Starts the process of listening for incoming HTTP connections on the ## specified address and port. @@ -207,13 +207,15 @@ proc close*(server: PAsyncHttpServer) = server.socket.close() when isMainModule: - var server = newAsyncHttpServer() - proc cb(req: TRequest) {.async.} = - #echo(req.reqMethod, " ", req.url) - #echo(req.headers) - let headers = {"Date": "Tue, 29 Apr 2014 23:40:08 GMT", - "Content-type": "text/plain; charset=utf-8"} - await req.respond(Http200, "Hello World", headers.newStringTable()) + proc main = + var server = newAsyncHttpServer() + proc cb(req: TRequest) {.async.} = + #echo(req.reqMethod, " ", req.url) + #echo(req.headers) + let headers = {"Date": "Tue, 29 Apr 2014 23:40:08 GMT", + "Content-type": "text/plain; charset=utf-8"} + await req.respond(Http200, "Hello World", headers.newStringTable()) - asyncCheck server.serve(TPort(5555), cb) - runForever() + asyncCheck server.serve(TPort(5555), cb) + runForever() + main() diff --git a/tests/system/toString.nim b/tests/system/toString.nim index 17dcb3cb48..52e7a4b92a 100644 --- a/tests/system/toString.nim +++ b/tests/system/toString.nim @@ -1,11 +1,9 @@ discard """ output:'''@[23, 45] -@[, foo, bar] -[, foo, bar] -[23, 45]''' +@[, foo, bar]''' """ echo($(@[23, 45])) echo($(@["", "foo", "bar"])) -echo($(["", "foo", "bar"])) -echo($([23, 45])) +#echo($(["", "foo", "bar"])) +#echo($([23, 45])) diff --git a/tests/threads/tthreadanalysis.nim b/tests/threads/tthreadanalysis.nim index 383680d816..37369b79cc 100644 --- a/tests/threads/tthreadanalysis.nim +++ b/tests/threads/tthreadanalysis.nim @@ -1,7 +1,7 @@ discard """ outputsub: "101" - msg: "Warning: write to foreign heap" - line: 37 + errormsg: "'threadFunc' is not GC-safe" + line: 39 cmd: "nimrod $target --hints:on --threads:on $options $file" """ diff --git a/tests/threads/tthreadheapviolation1.nim b/tests/threads/tthreadheapviolation1.nim index f3a36e036d..e0629ed083 100644 --- a/tests/threads/tthreadheapviolation1.nim +++ b/tests/threads/tthreadheapviolation1.nim @@ -1,6 +1,6 @@ discard """ - line: 12 - errormsg: "write to foreign heap" + line: 11 + errormsg: "'horrible' is not GC-safe" cmd: "nimrod $target --hints:on --threads:on $options $file" """ From 4d8c127838f692860b5e30314c1959b84e5dbcff Mon Sep 17 00:00:00 2001 From: Araq Date: Wed, 13 Aug 2014 01:30:42 +0200 Subject: [PATCH 139/234] made some tests green --- tests/converter/tconvert.nim | 30 ++--------------------------- tests/init/tuninit1.nim | 2 +- tests/objvariant/tcheckedfield1.nim | 2 +- tests/range/tmatrix3.nim | 4 ++-- 4 files changed, 6 insertions(+), 32 deletions(-) diff --git a/tests/converter/tconvert.nim b/tests/converter/tconvert.nim index a8ddcf1193..a371402349 100644 --- a/tests/converter/tconvert.nim +++ b/tests/converter/tconvert.nim @@ -1,5 +1,3 @@ -import - Cairo converter FloatConversion64(x: int): float64 = return toFloat(x) converter FloatConversion32(x: int): float32 = return toFloat(x) @@ -7,34 +5,10 @@ converter FloatConversionPlain(x: int): float = return toFloat(x) const width = 500 const height = 500 -const outFile = "CairoTest.png" -var surface = Cairo.ImageSurfaceCreate(CAIRO.FORMAT_RGB24, width, height) -var ç = Cairo.Create(surface) +proc ImageSurfaceCreate(w, h: float) = discard -ç.SetSourceRGB(1, 1, 1) -ç.Paint() - -ç.SetLineWidth(10) -ç.SetLineCap(CAIRO.LINE_CAP_ROUND) - -const count = 12 -var winc = width / count -var hinc = width / count -for i in 1 .. count-1: - var amount = i / count - ç.SetSourceRGB(0, 1 - amount, amount) - ç.MoveTo(i * winc, hinc) - ç.LineTo(width - i * winc, height - hinc) - ç.Stroke() - - ç.SetSourceRGB(1 - amount, 0, amount) - ç.MoveTo(winc, i * hinc) - ç.LineTo(width - winc, height - i * hinc) - ç.Stroke() - -echo(surface.WriteToPNG(outFile)) -surface.Destroy() +ImageSurfaceCreate(width, height) type TFoo = object diff --git a/tests/init/tuninit1.nim b/tests/init/tuninit1.nim index 2a994b1879..57443a7d3d 100644 --- a/tests/init/tuninit1.nim +++ b/tests/init/tuninit1.nim @@ -1,5 +1,5 @@ discard """ - errormsg: "'y' might not have been initialized" + msg: "Warning: 'y' might not have been initialized [Uninit]" line:34 """ diff --git a/tests/objvariant/tcheckedfield1.nim b/tests/objvariant/tcheckedfield1.nim index 5ade3a13a5..1963ceb8d5 100644 --- a/tests/objvariant/tcheckedfield1.nim +++ b/tests/objvariant/tcheckedfield1.nim @@ -1,5 +1,5 @@ discard """ - errormsg: "cannot prove that field 'x.s' is accessible" + msg: "Warning: cannot prove that field 'x.s' is accessible [ProveField]" line:51 """ diff --git a/tests/range/tmatrix3.nim b/tests/range/tmatrix3.nim index 9004045249..80d38d63d9 100644 --- a/tests/range/tmatrix3.nim +++ b/tests/range/tmatrix3.nim @@ -1,6 +1,6 @@ discard """ - output: '''0.0000000000000000e+00 -0.0000000000000000e+00 + output: '''0.0 +0.0 0 0 0 From 9d5d3c9fa149c8bfef6169884510d4027a1e0b6e Mon Sep 17 00:00:00 2001 From: Araq Date: Wed, 13 Aug 2014 02:06:21 +0200 Subject: [PATCH 140/234] fixes #820 --- doc/lib.txt | 2 - lib/windows/ole2.nim | 208 ------------------------------------------- 2 files changed, 210 deletions(-) delete mode 100644 lib/windows/ole2.nim diff --git a/doc/lib.txt b/doc/lib.txt index 76e7354e01..b5f8115b0b 100644 --- a/doc/lib.txt +++ b/doc/lib.txt @@ -466,8 +466,6 @@ Windows specific * `windows `_ Contains a wrapper for the Win32 API. -* `ole2 `_ - Contains GUIDs for OLE2 automation support. * `shellapi `_ Contains a wrapper for the ``shellapi.h`` header. * `shfolder `_ diff --git a/lib/windows/ole2.nim b/lib/windows/ole2.nim deleted file mode 100644 index ec0ab8f5da..0000000000 --- a/lib/windows/ole2.nim +++ /dev/null @@ -1,208 +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. -# - -import - windows - -const - GUID_NULL*: TGUID = (D1: 0x00000000, D2: 0x00000000, D3: 0x00000000, D4: [ - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000]) - IID_IUnknown*: TGUID = (D1: 0x00000000, D2: 0x00000000, D3: 0x00000000, D4: [ - 0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000046]) - IID_IClassFactory*: TGUID = (D1: 0x00000001, D2: 0x00000000, D3: 0x00000000, D4: [ - 0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000046]) - IID_IMarshal*: TGUID = (D1: 0x00000003, D2: 0x00000000, D3: 0x00000000, D4: [ - 0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000046]) - IID_IMalloc*: TGUID = (D1: 0x00000002, D2: 0x00000000, D3: 0x00000000, D4: [ - 0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000046]) - IID_IStdMarshalInfo*: TGUID = (D1: 0x00000018, D2: 0x00000000, D3: 0x00000000, D4: [ - 0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000046]) - IID_IExternalConnection*: TGUID = (D1: 0x00000019, D2: 0x00000000, - D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000046]) - IID_IEnumUnknown*: TGUID = (D1: 0x00000100, D2: 0x00000000, D3: 0x00000000, D4: [ - 0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000046]) - IID_IBindCtx*: TGUID = (D1: 0x0000000E, D2: 0x00000000, D3: 0x00000000, D4: [ - 0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000046]) - IID_IEnumMoniker*: TGUID = (D1: 0x00000102, D2: 0x00000000, D3: 0x00000000, D4: [ - 0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000046]) - IID_IRunnableObject*: TGUID = (D1: 0x00000126, D2: 0x00000000, D3: 0x00000000, D4: [ - 0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000046]) - IID_IRunningObjectTable*: TGUID = (D1: 0x00000010, D2: 0x00000000, - D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000046]) - IID_IPersist*: TGUID = (D1: 0x0000010C, D2: 0x00000000, D3: 0x00000000, D4: [ - 0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000046]) - IID_IPersistStream*: TGUID = (D1: 0x00000109, D2: 0x00000000, D3: 0x00000000, D4: [ - 0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000046]) - IID_IMoniker*: TGUID = (D1: 0x0000000F, D2: 0x00000000, D3: 0x00000000, D4: [ - 0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000046]) - IID_IEnumString*: TGUID = (D1: 0x00000101, D2: 0x00000000, D3: 0x00000000, D4: [ - 0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000046]) - IID_IStream*: TGUID = (D1: 0x0000000C, D2: 0x00000000, D3: 0x00000000, D4: [ - 0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000046]) - IID_IEnumStatStg*: TGUID = (D1: 0x0000000D, D2: 0x00000000, D3: 0x00000000, D4: [ - 0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000046]) - IID_IStorage*: TGUID = (D1: 0x0000000B, D2: 0x00000000, D3: 0x00000000, D4: [ - 0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000046]) - IID_IPersistFile*: TGUID = (D1: 0x0000010B, D2: 0x00000000, D3: 0x00000000, D4: [ - 0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000046]) - IID_IPersistStorage*: TGUID = (D1: 0x0000010A, D2: 0x00000000, D3: 0x00000000, D4: [ - 0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000046]) - IID_ILockBytes*: TGUID = (D1: 0x0000000A, D2: 0x00000000, D3: 0x00000000, D4: [ - 0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000046]) - IID_IEnumFormatEtc*: TGUID = (D1: 0x00000103, D2: 0x00000000, D3: 0x00000000, D4: [ - 0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000046]) - IID_IEnumStatData*: TGUID = (D1: 0x00000105, D2: 0x00000000, D3: 0x00000000, D4: [ - 0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000046]) - IID_IRootStorage*: TGUID = (D1: 0x00000012, D2: 0x00000000, D3: 0x00000000, D4: [ - 0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000046]) - IID_IAdviseSink*: TGUID = (D1: 0x0000010F, D2: 0x00000000, D3: 0x00000000, D4: [ - 0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000046]) - IID_IAdviseSink2*: TGUID = (D1: 0x00000125, D2: 0x00000000, D3: 0x00000000, D4: [ - 0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000046]) - IID_IDataObject*: TGUID = (D1: 0x0000010E, D2: 0x00000000, D3: 0x00000000, D4: [ - 0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000046]) - IID_IDataAdviseHolder*: TGUID = (D1: 0x00000110, D2: 0x00000000, - D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000046]) - IID_IMessageFilter*: TGUID = (D1: 0x00000016, D2: 0x00000000, D3: 0x00000000, D4: [ - 0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000046]) - IID_IRpcChannelBuffer*: TGUID = (D1: 0xD5F56B60, D2: 0x0000593B, - D3: 0x0000101A, D4: [0x000000B5, 0x00000069, 0x00000008, 0x00000000, - 0x0000002B, 0x0000002D, 0x000000BF, 0x0000007A]) - IID_IRpcProxyBuffer*: TGUID = (D1: 0xD5F56A34, D2: 0x0000593B, D3: 0x0000101A, D4: [ - 0x000000B5, 0x00000069, 0x00000008, 0x00000000, 0x0000002B, 0x0000002D, - 0x000000BF, 0x0000007A]) - IID_IRpcStubBuffer*: TGUID = (D1: 0xD5F56AFC, D2: 0x0000593B, D3: 0x0000101A, D4: [ - 0x000000B5, 0x00000069, 0x00000008, 0x00000000, 0x0000002B, 0x0000002D, - 0x000000BF, 0x0000007A]) - IID_IPSFactoryBuffer*: TGUID = (D1: 0xD5F569D0, D2: 0x0000593B, - D3: 0x0000101A, D4: [0x000000B5, 0x00000069, 0x00000008, 0x00000000, - 0x0000002B, 0x0000002D, 0x000000BF, 0x0000007A]) - IID_ICreateTypeInfo*: TGUID = (D1: 0x00020405, D2: 0x00000000, D3: 0x00000000, D4: [ - 0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000046]) - IID_ICreateTypeLib*: TGUID = (D1: 0x00020406, D2: 0x00000000, D3: 0x00000000, D4: [ - 0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000046]) - IID_IDispatch*: TGUID = (D1: 0x00020400, D2: 0x00000000, D3: 0x00000000, D4: [ - 0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000046]) - IID_IEnumVariant*: TGUID = (D1: 0x00020404, D2: 0x00000000, D3: 0x00000000, D4: [ - 0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000046]) - IID_ITypeComp*: TGUID = (D1: 0x00020403, D2: 0x00000000, D3: 0x00000000, D4: [ - 0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000046]) - IID_ITypeInfo*: TGUID = (D1: 0x00020401, D2: 0x00000000, D3: 0x00000000, D4: [ - 0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000046]) - IID_ITypeLib*: TGUID = (D1: 0x00020402, D2: 0x00000000, D3: 0x00000000, D4: [ - 0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000046]) - IID_IErrorInfo*: TGUID = (D1: 0x1CF2B120, D2: 0x0000547D, D3: 0x0000101B, D4: [ - 0x0000008E, 0x00000065, 0x00000008, 0x00000000, 0x0000002B, 0x0000002B, - 0x000000D1, 0x00000019]) - IID_ICreateErrorInfo*: TGUID = (D1: 0x22F03340, D2: 0x0000547D, - D3: 0x0000101B, D4: [0x0000008E, 0x00000065, 0x00000008, 0x00000000, - 0x0000002B, 0x0000002B, 0x000000D1, 0x00000019]) - IID_ISupportErrorInfo*: TGUID = (D1: 0xDF0B3D60, D2: 0x0000548F, - D3: 0x0000101B, D4: [0x0000008E, 0x00000065, 0x00000008, 0x00000000, - 0x0000002B, 0x0000002B, 0x000000D1, 0x00000019]) - IID_IOleAdviseHolder*: TGUID = (D1: 0x00000111, D2: 0x00000000, - D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000046]) - IID_IOleCache*: TGUID = (D1: 0x0000011E, D2: 0x00000000, D3: 0x00000000, D4: [ - 0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000046]) - IID_IOleCache2*: TGUID = (D1: 0x00000128, D2: 0x00000000, D3: 0x00000000, D4: [ - 0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000046]) - IID_IOleCacheControl*: TGUID = (D1: 0x00000129, D2: 0x00000000, - D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000046]) - IID_IParseDisplayName*: TGUID = (D1: 0x0000011A, D2: 0x00000000, - D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000046]) - IID_IOleContainer*: TGUID = (D1: 0x0000011B, D2: 0x00000000, D3: 0x00000000, D4: [ - 0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000046]) - IID_IOleClientSite*: TGUID = (D1: 0x00000118, D2: 0x00000000, D3: 0x00000000, D4: [ - 0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000046]) - IID_IOleObject*: TGUID = (D1: 0x00000112, D2: 0x00000000, D3: 0x00000000, D4: [ - 0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000046]) - IID_IOleWindow*: TGUID = (D1: 0x00000114, D2: 0x00000000, D3: 0x00000000, D4: [ - 0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000046]) - IID_IOleLink*: TGUID = (D1: 0x0000011D, D2: 0x00000000, D3: 0x00000000, D4: [ - 0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000046]) - IID_IOleItemContainer*: TGUID = (D1: 0x0000011C, D2: 0x00000000, - D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000046]) - IID_IOleInPlaceUIWindow*: TGUID = (D1: 0x00000115, D2: 0x00000000, - D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000046]) - IID_IOleInPlaceActiveObject*: TGUID = (D1: 0x00000117, D2: 0x00000000, - D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000046]) - IID_IOleInPlaceFrame*: TGUID = (D1: 0x00000116, D2: 0x00000000, - D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000046]) - IID_IOleInPlaceObject*: TGUID = (D1: 0x00000113, D2: 0x00000000, - D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000046]) - IID_IOleInPlaceSite*: TGUID = (D1: 0x00000119, D2: 0x00000000, D3: 0x00000000, D4: [ - 0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000046]) - IID_IViewObject*: TGUID = (D1: 0x0000010D, D2: 0x00000000, D3: 0x00000000, D4: [ - 0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000046]) - IID_IViewObject2*: TGUID = (D1: 0x00000127, D2: 0x00000000, D3: 0x00000000, D4: [ - 0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000046]) - IID_IDropSource*: TGUID = (D1: 0x00000121, D2: 0x00000000, D3: 0x00000000, D4: [ - 0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000046]) - IID_IDropTarget*: TGUID = (D1: 0x00000122, D2: 0x00000000, D3: 0x00000000, D4: [ - 0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000046]) - IID_IEnumOleVerb*: TGUID = (D1: 0x00000104, D2: 0x00000000, D3: 0x00000000, D4: [ - 0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000046]) From abc844733157441ed5a1aee23476e55c2fcd8a83 Mon Sep 17 00:00:00 2001 From: Araq Date: Wed, 13 Aug 2014 02:34:08 +0200 Subject: [PATCH 141/234] fixes #1413 --- lib/pure/collections/sets.nim | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/lib/pure/collections/sets.nim b/lib/pure/collections/sets.nim index 42cdc682fb..22eff9c557 100644 --- a/lib/pure/collections/sets.nim +++ b/lib/pure/collections/sets.nim @@ -713,6 +713,24 @@ proc `$`*[A](s: TOrderedSet[A]): string = assert s.isValid, "The set needs to be initialized." dollarImpl() +proc `==`*[A](s, t: TOrderedSet[A]): bool = + ## Equality for ordered sets. + if s.counter != t.counter: return false + var h = s.first + var g = s.first + var compared = 0 + while h >= 0 and g >= 0: + var nxh = s.data[h].next + var nxg = t.data[g].next + if s.data[h].slot == seFilled and s.data[g].slot == seFilled: + if s.data[h].key == s.data[g].key: + inc compared + else: + return false + h = nxh + g = nxg + result = compared == s.counter + proc testModule() = ## Internal micro test to validate docstrings and such. block isValidTest: @@ -858,7 +876,7 @@ proc testModule() = var b = initOrderedSet[int]() for x in [2, 4, 5]: b.incl(x) assert($a == $b) - # assert(a == b) # https://github.com/Araq/Nimrod/issues/1413 + assert(a == b) # https://github.com/Araq/Nimrod/issues/1413 block initBlocks: var a: TOrderedSet[int] From 32a5d4baf0e4930dbb9da47b060784a948bc2bee Mon Sep 17 00:00:00 2001 From: Araq Date: Wed, 13 Aug 2014 02:53:00 +0200 Subject: [PATCH 142/234] fixes #1442 --- compiler/types.nim | 10 ++++++++-- tests/misc/tstrange.nim | 10 ++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/compiler/types.nim b/compiler/types.nim index 786eea14e7..7559f4d2d6 100644 --- a/compiler/types.nim +++ b/compiler/types.nim @@ -582,7 +582,10 @@ proc firstOrd(t: PType): BiggestInt = of tyGenericInst, tyDistinct, tyConst, tyMutable, tyTypeDesc, tyFieldAccessor: result = firstOrd(lastSon(t)) - else: + of tyOrdinal: + if t.len > 0: result = firstOrd(lastSon(t)) + else: internalError("invalid kind for first(" & $t.kind & ')') + else: internalError("invalid kind for first(" & $t.kind & ')') result = 0 @@ -617,7 +620,10 @@ proc lastOrd(t: PType): BiggestInt = tyTypeDesc, tyFieldAccessor: result = lastOrd(lastSon(t)) of tyProxy: result = 0 - else: + of tyOrdinal: + if t.len > 0: result = lastOrd(lastSon(t)) + else: internalError("invalid kind for last(" & $t.kind & ')') + else: internalError("invalid kind for last(" & $t.kind & ')') result = 0 diff --git a/tests/misc/tstrange.nim b/tests/misc/tstrange.nim index 3947755fcf..6bafcabdc3 100644 --- a/tests/misc/tstrange.nim +++ b/tests/misc/tstrange.nim @@ -1,6 +1,9 @@ discard """ file: "tstrange.nim" - output: "hallo4" + output: '''hallo4 +0 +1 +2''' """ # test for extremely strange bug @@ -19,5 +22,8 @@ gen("hallo") write(stdout, ack(5, 4)) #OUT hallo4 - +# bug #1442 +let h=3 +for x in 0.. Date: Wed, 13 Aug 2014 12:58:49 +0200 Subject: [PATCH 143/234] fixes #1475 --- lib/system/repr.nim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/system/repr.nim b/lib/system/repr.nim index d6df61fd3a..8e1bc5f264 100644 --- a/lib/system/repr.nim +++ b/lib/system/repr.nim @@ -221,7 +221,7 @@ when not defined(useNimRtl): dec(cl.recdepth) case typ.kind of tySet: reprSetAux(result, p, typ) - of tyArray: reprArray(result, p, typ, cl) + of tyArray, tyArrayConstr: reprArray(result, p, typ, cl) of tyTuple: reprRecord(result, p, typ, cl) of tyObject: var t = cast[ptr PNimType](p)[] @@ -275,7 +275,7 @@ when not defined(useNimRtl): cl: TReprClosure initReprClosure(cl) result = "" - if typ.kind in {tyObject, tyTuple, tyArray, tySet}: + if typ.kind in {tyObject, tyTuple, tyArray, tyArrayConstr, tySet}: reprAux(result, p, typ, cl) else: var p = p From 3b7a1498e7e06576c461df9a910b3e6ba79a9feb Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Wed, 13 Aug 2014 20:46:28 +0100 Subject: [PATCH 144/234] Removed zmq wrapper. --- lib/wrappers/zmq.nim | 322 ------------------------------------------- 1 file changed, 322 deletions(-) delete mode 100644 lib/wrappers/zmq.nim diff --git a/lib/wrappers/zmq.nim b/lib/wrappers/zmq.nim deleted file mode 100644 index 9826ab8130..0000000000 --- a/lib/wrappers/zmq.nim +++ /dev/null @@ -1,322 +0,0 @@ -# Nimrod wrapper of 0mq -# Generated by c2nim with modifications and enhancement from Andreas Rumpf -# Original licence follows: - -# -# Copyright (c) 2007-2011 iMatix Corporation -# Copyright (c) 2007-2011 Other contributors as noted in the AUTHORS file -# -# This file is part of 0MQ. -# -# 0MQ is free software; you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# 0MQ is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with this program. If not, see . -# - -# Generated from zmq version 2.1.5 - -## Nimrod 0mq wrapper. This file contains the low level C wrappers as well as -## some higher level constructs. The higher level constructs are easily -## recognizable because they are the only ones that have documentation. -## -## Example of a client: -## -## .. code-block:: nimrod -## import zmq -## -## var connection = zmq.open("tcp://localhost:5555", server=false) -## echo("Connecting...") -## for i in 0..10: -## echo("Sending hello...", i) -## send(connection, "Hello") -## var reply = receive(connection) -## echo("Received ...", reply) -## close(connection) -## -## Example of a server: -## -## .. code-block:: nimrod -## -## import zmq -## var connection = zmq.open("tcp://*:5555", server=true) -## while True: -## var request = receive(connection) -## echo("Received: ", request) -## send(connection, "World") -## close(connection) - -{.deadCodeElim: on.} -when defined(windows): - const - zmqdll* = "zmq.dll" -elif defined(macosx): - const - zmqdll* = "libzmq.dylib" -else: - const - zmqdll* = "libzmq.so" - -# A number random enough not to collide with different errno ranges on -# different OSes. The assumption is that error_t is at least 32-bit type. -const - HAUSNUMERO* = 156384712 - # On Windows platform some of the standard POSIX errnos are not defined. - ENOTSUP* = (HAUSNUMERO + 1) - EPROTONOSUPPORT* = (HAUSNUMERO + 2) - ENOBUFS* = (HAUSNUMERO + 3) - ENETDOWN* = (HAUSNUMERO + 4) - EADDRINUSE* = (HAUSNUMERO + 5) - EADDRNOTAVAIL* = (HAUSNUMERO + 6) - ECONNREFUSED* = (HAUSNUMERO + 7) - EINPROGRESS* = (HAUSNUMERO + 8) - # Native 0MQ error codes. - EFSM* = (HAUSNUMERO + 51) - ENOCOMPATPROTO* = (HAUSNUMERO + 52) - ETERM* = (HAUSNUMERO + 53) - EMTHREAD* = (HAUSNUMERO + 54) - # Maximal size of "Very Small Message". VSMs are passed by value - # to avoid excessive memory allocation/deallocation. - # If VMSs larger than 255 bytes are required, type of 'vsm_size' - # field in msg_t structure should be modified accordingly. - MAX_VSM_SIZE* = 30 - - POLLIN* = 1 - POLLOUT* = 2 - POLLERR* = 4 - - STREAMER* = 1 - FORWARDER* = 2 - QUEUE* = 3 - - PAIR* = 0 - PUB* = 1 - SUB* = 2 - REQ* = 3 - REP* = 4 - DEALER* = 5 - ROUTER* = 6 - PULL* = 7 - PUSH* = 8 - XPUB* = 9 - XSUB* = 10 - XREQ* = DEALER # Old alias, remove in 3.x - XREP* = ROUTER # Old alias, remove in 3.x - UPSTREAM* = PULL # Old alias, remove in 3.x - DOWNSTREAM* = PUSH # Old alias, remove in 3.x - -type - # Message types. These integers may be stored in 'content' member of the - # message instead of regular pointer to the data. - TMsgTypes* = enum - DELIMITER = 31, - VSM = 32 - # Message flags. MSG_SHARED is strictly speaking not a message flag - # (it has no equivalent in the wire format), however, making it a flag - # allows us to pack the stucture tighter and thus improve performance. - TMsgFlags* = enum - MSG_MORE = 1, - MSG_SHARED = 128, - MSG_MASK = 129 # Merges all the flags - # A message. Note that 'content' is not a pointer to the raw data. - # Rather it is pointer to zmq::msg_content_t structure - # (see src/msg_content.hpp for its definition). - TMsg*{.pure, final.} = object - content*: pointer - flags*: char - vsm_size*: char - vsm_data*: array[0..MAX_VSM_SIZE - 1, char] - - TFreeFn = proc (data, hint: pointer) {.noconv.} - - TContext {.final, pure.} = object - PContext* = ptr TContext - - # Socket Types - TSocket {.final, pure.} = object - PSocket* = ptr TSocket - - # Socket options. - TSockOptions* = enum - HWM = 1, - SWAP = 3, - AFFINITY = 4, - IDENTITY = 5, - SUBSCRIBE = 6, - UNSUBSCRIBE = 7, - RATE = 8, - RECOVERY_IVL = 9, - MCAST_LOOP = 10, - SNDBUF = 11, - RCVBUF = 12, - RCVMORE = 13, - FD = 14, - EVENTS = 15, - theTYPE = 16, - LINGER = 17, - RECONNECT_IVL = 18, - BACKLOG = 19, - RECOVERY_IVL_MSEC = 20, # opt. recovery time, reconcile in 3.x - RECONNECT_IVL_MAX = 21 - - # Send/recv options. - TSendRecvOptions* = enum - NOBLOCK, SNDMORE - - TPollItem*{.pure, final.} = object - socket*: PSocket - fd*: cint - events*: cshort - revents*: cshort - -# Run-time API version detection - -proc version*(major: var cint, minor: var cint, patch: var cint){.cdecl, - importc: "zmq_version", dynlib: zmqdll.} -#**************************************************************************** -# 0MQ errors. -#**************************************************************************** - -# This function retrieves the errno as it is known to 0MQ library. The goal -# of this function is to make the code 100% portable, including where 0MQ -# compiled with certain CRT library (on Windows) is linked to an -# application that uses different CRT library. - -proc errno*(): cint{.cdecl, importc: "zmq_errno", dynlib: zmqdll.} -# Resolves system errors and 0MQ errors to human-readable string. - -proc strerror*(errnum: cint): cstring {.cdecl, importc: "zmq_strerror", - dynlib: zmqdll.} -#**************************************************************************** -# 0MQ message definition. -#**************************************************************************** - -proc msg_init*(msg: var TMsg): cint{.cdecl, importc: "zmq_msg_init", - dynlib: zmqdll.} -proc msg_init*(msg: var TMsg, size: int): cint{.cdecl, - importc: "zmq_msg_init_size", dynlib: zmqdll.} -proc msg_init*(msg: var TMsg, data: cstring, size: int, - ffn: TFreeFn, hint: pointer): cint{.cdecl, - importc: "zmq_msg_init_data", dynlib: zmqdll.} -proc msg_close*(msg: var TMsg): cint {.cdecl, importc: "zmq_msg_close", - dynlib: zmqdll.} -proc msg_move*(dest, src: var TMsg): cint{.cdecl, - importc: "zmq_msg_move", dynlib: zmqdll.} -proc msg_copy*(dest, src: var TMsg): cint{.cdecl, - importc: "zmq_msg_copy", dynlib: zmqdll.} -proc msg_data*(msg: var TMsg): cstring {.cdecl, importc: "zmq_msg_data", - dynlib: zmqdll.} -proc msg_size*(msg: var TMsg): int {.cdecl, importc: "zmq_msg_size", - dynlib: zmqdll.} - -#**************************************************************************** -# 0MQ infrastructure (a.k.a. context) initialisation & termination. -#**************************************************************************** - -proc init*(io_threads: cint): PContext {.cdecl, importc: "zmq_init", - dynlib: zmqdll.} -proc term*(context: PContext): cint {.cdecl, importc: "zmq_term", - dynlib: zmqdll.} -#**************************************************************************** -# 0MQ socket definition. -#**************************************************************************** - -proc socket*(context: PContext, theType: cint): PSocket {.cdecl, - importc: "zmq_socket", dynlib: zmqdll.} -proc close*(s: PSocket): cint{.cdecl, importc: "zmq_close", dynlib: zmqdll.} -proc setsockopt*(s: PSocket, option: cint, optval: pointer, - optvallen: int): cint {.cdecl, importc: "zmq_setsockopt", - dynlib: zmqdll.} -proc getsockopt*(s: PSocket, option: cint, optval: pointer, - optvallen: ptr int): cint{.cdecl, - importc: "zmq_getsockopt", dynlib: zmqdll.} -proc bindAddr*(s: PSocket, address: cstring): cint{.cdecl, importc: "zmq_bind", - dynlib: zmqdll.} -proc connect*(s: PSocket, address: cstring): cint{.cdecl, - importc: "zmq_connect", dynlib: zmqdll.} -proc send*(s: PSocket, msg: var TMsg, flags: cint): cint{.cdecl, - importc: "zmq_send", dynlib: zmqdll.} -proc recv*(s: PSocket, msg: var TMsg, flags: cint): cint{.cdecl, - importc: "zmq_recv", dynlib: zmqdll.} -#**************************************************************************** -# I/O multiplexing. -#**************************************************************************** - -proc poll*(items: ptr TPollItem, nitems: cint, timeout: int): cint{. - cdecl, importc: "zmq_poll", dynlib: zmqdll.} - -#**************************************************************************** -# Built-in devices -#**************************************************************************** - -proc device*(device: cint, insocket, outsocket: PSocket): cint{. - cdecl, importc: "zmq_device", dynlib: zmqdll.} - -type - EZmq* = object of ESynch ## exception that is raised if something fails - TConnection* {.pure, final.} = object ## a connection - c*: PContext ## the embedded context - s*: PSocket ## the embedded socket - - TConnectionMode* = enum ## connection mode - conPAIR = 0, - conPUB = 1, - conSUB = 2, - conREQ = 3, - conREP = 4, - conDEALER = 5, - conROUTER = 6, - conPULL = 7, - conPUSH = 8, - conXPUB = 9, - conXSUB = 10 - -proc zmqError*() {.noinline, noreturn.} = - ## raises EZmq with error message from `zmq.strerror`. - var e: ref EZmq - new(e) - e.msg = $strerror(errno()) - raise e - -proc open*(address: string, server: bool, mode: TConnectionMode = conDEALER, - numthreads = 4): TConnection = - ## opens a new connection. If `server` is true, it uses `bindAddr` for the - ## underlying socket, otherwise it opens the socket with `connect`. - result.c = init(cint(numthreads)) - if result.c == nil: zmqError() - result.s = socket(result.c, cint(ord(mode))) - if result.s == nil: zmqError() - if server: - if bindAddr(result.s, address) != 0'i32: zmqError() - else: - if connect(result.s, address) != 0'i32: zmqError() - -proc close*(c: TConnection) = - ## closes the connection. - if close(c.s) != 0'i32: zmqError() - if term(c.c) != 0'i32: zmqError() - -proc send*(c: TConnection, msg: string) = - ## sends a message over the connection. - var m: TMsg - if msg_init(m, msg.len) != 0'i32: zmqError() - copyMem(msg_data(m), cstring(msg), msg.len) - if send(c.s, m, 0'i32) != 0'i32: zmqError() - discard msg_close(m) - -proc receive*(c: TConnection): string = - ## receives a message from a connection. - var m: TMsg - if msg_init(m) != 0'i32: zmqError() - if recv(c.s, m, 0'i32) != 0'i32: zmqError() - result = newString(msg_size(m)) - copyMem(addr(result[0]), msg_data(m), result.len) - discard msg_close(m) From f3d530e482249215da56cf1898edd20b51d4480d Mon Sep 17 00:00:00 2001 From: Araq Date: Thu, 14 Aug 2014 00:02:24 +0200 Subject: [PATCH 145/234] fixes #1434 --- compiler/ccgcalls.nim | 13 +++++++------ compiler/ccgexprs.nim | 1 - compiler/ccgstmts.nim | 16 +++++++++++++--- compiler/ccgtrav.nim | 2 +- compiler/cgen.nim | 4 ++-- tests/ccgbugs/tmissinginit.nim | 30 ++++++++++++++++++++++++++++++ tests/misc/tstrange.nim | 3 +-- 7 files changed, 54 insertions(+), 15 deletions(-) create mode 100644 tests/ccgbugs/tmissinginit.nim diff --git a/compiler/ccgcalls.nim b/compiler/ccgcalls.nim index 71e23aa1dd..adcc95e846 100644 --- a/compiler/ccgcalls.nim +++ b/compiler/ccgcalls.nim @@ -29,7 +29,7 @@ proc fixupCall(p: BProc, le, ri: PNode, d: var TLoc, # beware of 'result = p(result)'. We may need to allocate a temporary: if d.k in {locTemp, locNone} or not leftAppearsOnRightSide(le, ri): # Great, we can use 'd': - if d.k == locNone: getTemp(p, typ.sons[0], d) + if d.k == locNone: getTemp(p, typ.sons[0], d, needsInit=true) elif d.k notin {locExpr, locTemp} and not hasNoInit(ri): # reset before pass as 'result' var: resetLoc(p, d) @@ -38,7 +38,7 @@ proc fixupCall(p: BProc, le, ri: PNode, d: var TLoc, line(p, cpsStmts, pl) else: var tmp: TLoc - getTemp(p, typ.sons[0], tmp) + getTemp(p, typ.sons[0], tmp, needsInit=true) app(pl, addrLoc(tmp)) app(pl, ~");$n") line(p, cpsStmts, pl) @@ -195,7 +195,8 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) = # beware of 'result = p(result)'. We may need to allocate a temporary: if d.k in {locTemp, locNone} or not leftAppearsOnRightSide(le, ri): # Great, we can use 'd': - if d.k == locNone: getTemp(p, typ.sons[0], d) + if d.k == locNone: + getTemp(p, typ.sons[0], d, needsInit=true) elif d.k notin {locExpr, locTemp} and not hasNoInit(ri): # reset before pass as 'result' var: resetLoc(p, d) @@ -203,7 +204,7 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) = genCallPattern() else: var tmp: TLoc - getTemp(p, typ.sons[0], tmp) + getTemp(p, typ.sons[0], tmp, needsInit=true) app(pl, addrLoc(tmp)) genCallPattern() genAssignment(p, d, tmp, {}) # no need for deep copying @@ -278,14 +279,14 @@ proc genNamedParamCall(p: BProc, ri: PNode, d: var TLoc) = # beware of 'result = p(result)'. We always allocate a temporary: if d.k in {locTemp, locNone}: # We already got a temp. Great, special case it: - if d.k == locNone: getTemp(p, typ.sons[0], d) + if d.k == locNone: getTemp(p, typ.sons[0], d, needsInit=true) app(pl, ~"Result: ") app(pl, addrLoc(d)) app(pl, ~"];$n") line(p, cpsStmts, pl) else: var tmp: TLoc - getTemp(p, typ.sons[0], tmp) + getTemp(p, typ.sons[0], tmp, needsInit=true) app(pl, addrLoc(tmp)) app(pl, ~"];$n") line(p, cpsStmts, pl) diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 3fe6140a34..b5817de05a 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -1217,7 +1217,6 @@ proc genOf(p: BProc, n: PNode, d: var TLoc) = genOf(p, n.sons[1], n.sons[2].typ, d) proc genRepr(p: BProc, e: PNode, d: var TLoc) = - # XXX we don't generate keep alive info for now here var a: TLoc initLocExpr(p, e.sons[1], a) var t = skipTypes(e.sons[1].typ, abstractVarRange) diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index a8cfa57e46..f32ff3c78b 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -24,6 +24,15 @@ proc registerGcRoot(p: BProc, v: PSym) = linefmt(p.module.initProc, cpsStmts, "#nimRegisterGlobalMarker($1);$n", prc) +proc isAssignedImmediately(n: PNode): bool {.inline.} = + if n.kind == nkEmpty: return false + if isInvalidReturnType(n.typ): + # var v = f() + # is transformed into: var v; f(addr v) + # where 'f' **does not** initialize the result! + return false + result = true + proc genVarTuple(p: BProc, n: PNode) = var tup, field: TLoc if n.kind != nkVarTuple: internalError(n.info, "genVarTuple") @@ -40,7 +49,7 @@ proc genVarTuple(p: BProc, n: PNode) = registerGcRoot(p, v) else: assignLocalVar(p, v) - initLocalVar(p, v, immediateAsgn=true) + initLocalVar(p, v, immediateAsgn=isAssignedImmediately(n[L-1])) initLoc(field, locExpr, t.sons[i], tup.s) if t.kind == tyTuple: field.r = ropef("$1.Field$2", [rdLoc(tup), toRope(i)]) @@ -146,11 +155,12 @@ proc genBreakState(p: BProc, n: PNode) = # lineF(p, cpsStmts, "if (($1) < 0) break;$n", [rdLoc(a)]) proc genVarPrototypeAux(m: BModule, sym: PSym) + proc genSingleVar(p: BProc, a: PNode) = var v = a.sons[0].sym if sfCompileTime in v.flags: return var targetProc = p - var immediateAsgn = a.sons[2].kind != nkEmpty + var immediateAsgn = isAssignedImmediately(a.sons[2]) if sfGlobal in v.flags: if sfPure in v.flags: # v.owner.kind != skModule: @@ -177,7 +187,7 @@ proc genSingleVar(p: BProc, a: PNode) = loadInto(targetProc, a.sons[0], a.sons[2], v.loc) proc genClosureVar(p: BProc, a: PNode) = - var immediateAsgn = a.sons[2].kind != nkEmpty + var immediateAsgn = isAssignedImmediately(a.sons[2]) if immediateAsgn: var v: TLoc initLocExpr(p, a.sons[0], v) diff --git a/compiler/ccgtrav.nim b/compiler/ccgtrav.nim index 26f4746598..a5bf9e7a74 100644 --- a/compiler/ccgtrav.nim +++ b/compiler/ccgtrav.nim @@ -19,7 +19,7 @@ type proc genTraverseProc(c: var TTraversalClosure, accessor: PRope, typ: PType) proc genCaseRange(p: BProc, branch: PNode) -proc getTemp(p: BProc, t: PType, result: var TLoc) +proc getTemp(p: BProc, t: PType, result: var TLoc; needsInit=false) proc genTraverseProc(c: var TTraversalClosure, accessor: PRope, n: PNode) = if n == nil: return diff --git a/compiler/cgen.nim b/compiler/cgen.nim index b930bea8d4..d3f6614660 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -399,7 +399,7 @@ proc initLocalVar(p: BProc, v: PSym, immediateAsgn: bool) = if not immediateAsgn: constructLoc(p, v.loc) -proc getTemp(p: BProc, t: PType, result: var TLoc) = +proc getTemp(p: BProc, t: PType, result: var TLoc; needsInit=false) = inc(p.labels) if gCmd == cmdCompileToLLVM: result.r = con("%LOC", toRope(p.labels)) @@ -411,7 +411,7 @@ proc getTemp(p: BProc, t: PType, result: var TLoc) = result.t = getUniqueType(t) result.s = OnStack result.flags = {} - constructLoc(p, result, isTemp=true) + constructLoc(p, result, not needsInit) proc keepAlive(p: BProc, toKeepAlive: TLoc) = when false: diff --git a/tests/ccgbugs/tmissinginit.nim b/tests/ccgbugs/tmissinginit.nim new file mode 100644 index 0000000000..36648ef8d9 --- /dev/null +++ b/tests/ccgbugs/tmissinginit.nim @@ -0,0 +1,30 @@ +discard """ + output: '''0 +0 +0 +0 +[[a = nil, +b = nil]] +""" + +# bug #1475 +type + Crash = object + a: string + b: seq[string] + +proc initCrash(): Crash = discard + +proc test() = + var blongname = [initCrash()] + echo repr(blongname) + +# bug #1434 +proc bug: array[1, int] = discard + +echo bug()[0] +echo bug()[0] +echo bug()[0] +echo bug()[0] + +when isMainModule: test() diff --git a/tests/misc/tstrange.nim b/tests/misc/tstrange.nim index 6bafcabdc3..8742011bb6 100644 --- a/tests/misc/tstrange.nim +++ b/tests/misc/tstrange.nim @@ -1,7 +1,6 @@ discard """ file: "tstrange.nim" - output: '''hallo4 -0 + output: '''hallo40 1 2''' """ From a772105e7d1662cfc3bf4ce382349d4ea4b72a30 Mon Sep 17 00:00:00 2001 From: Reimer Behrends Date: Thu, 14 Aug 2014 02:10:28 +0200 Subject: [PATCH 146/234] Fixed stack bottom initialization for DLLs. --- compiler/cgen.nim | 2 +- lib/system.nim | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/cgen.nim b/compiler/cgen.nim index 41f380d1b4..112a2af34d 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -967,11 +967,11 @@ proc genMainProc(m: BModule) = # functions, which might otherwise merge their stack frames. NimMainBody = "N_CDECL(void, NimMainInner)(void) {$N" & - "\tPreMain();$N" & "$1" & "}$N$N" & "N_CDECL(void, NimMain)(void) {$N" & "\tvoid (*volatile inner)();$N" & + "\tPreMain();$N" & "\tinner = NimMainInner;$N" & "$2" & "\t(*inner)();$N" & diff --git a/lib/system.nim b/lib/system.nim index 8ab3ee2e5d..3bf65c6957 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -2185,7 +2185,7 @@ when not defined(JS): #and not defined(NimrodVM): proc initStackBottomWith(locals: pointer) {.inline, compilerproc.} = # We need to keep initStackBottom around for now to avoid # bootstrapping problems. - when defined(setStackBottom): + when declared(setStackBottom): setStackBottom(locals) var From 2728bbccc4888ddc90adbdf469891935407b80af Mon Sep 17 00:00:00 2001 From: Araq Date: Thu, 14 Aug 2014 02:42:26 +0200 Subject: [PATCH 147/234] fixes newly introduced bugs --- compiler/ccgstmts.nim | 9 ++++----- doc/lib.txt | 4 ---- lib/system.nim | 2 +- web/nimrod.ini | 2 +- 4 files changed, 6 insertions(+), 11 deletions(-) diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index f32ff3c78b..eca026e127 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -1,7 +1,7 @@ # # # The Nimrod Compiler -# (c) Copyright 2013 Andreas Rumpf +# (c) Copyright 2014 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. @@ -160,7 +160,6 @@ proc genSingleVar(p: BProc, a: PNode) = var v = a.sons[0].sym if sfCompileTime in v.flags: return var targetProc = p - var immediateAsgn = isAssignedImmediately(a.sons[2]) if sfGlobal in v.flags: if sfPure in v.flags: # v.owner.kind != skModule: @@ -180,14 +179,14 @@ proc genSingleVar(p: BProc, a: PNode) = registerGcRoot(p, v) else: assignLocalVar(p, v) - initLocalVar(p, v, immediateAsgn) + initLocalVar(p, v, isAssignedImmediately(a.sons[2])) - if immediateAsgn: + if a.sons[2].kind != nkEmpty: genLineDir(targetProc, a) loadInto(targetProc, a.sons[0], a.sons[2], v.loc) proc genClosureVar(p: BProc, a: PNode) = - var immediateAsgn = isAssignedImmediately(a.sons[2]) + var immediateAsgn = a.sons[2].kind != nkEmpty if immediateAsgn: var v: TLoc initLocExpr(p, a.sons[0], v) diff --git a/doc/lib.txt b/doc/lib.txt index b5f8115b0b..26ea1b7350 100644 --- a/doc/lib.txt +++ b/doc/lib.txt @@ -450,10 +450,6 @@ Other This module contains code for reading from `stdin`:idx:. On UNIX the GNU readline library is wrapped and set up. -* `zmq `_ - Nimrod 0mq wrapper. This file contains the low level C wrappers as well as - some higher level constructs. - Wrappers ======== diff --git a/lib/system.nim b/lib/system.nim index 8ab3ee2e5d..3bf65c6957 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -2185,7 +2185,7 @@ when not defined(JS): #and not defined(NimrodVM): proc initStackBottomWith(locals: pointer) {.inline, compilerproc.} = # We need to keep initStackBottom around for now to avoid # bootstrapping problems. - when defined(setStackBottom): + when declared(setStackBottom): setStackBottom(locals) var diff --git a/web/nimrod.ini b/web/nimrod.ini index 38a906ac57..3277718508 100644 --- a/web/nimrod.ini +++ b/web/nimrod.ini @@ -54,7 +54,7 @@ srcdoc2: "pure/httpserver;pure/httpclient;pure/smtp;impure/ssl;pure/fsmonitor" srcdoc2: "pure/ropes;pure/unidecode/unidecode;pure/xmldom;pure/xmldomparser" srcdoc2: "pure/xmlparser;pure/htmlparser;pure/xmltree;pure/colors;pure/mimetypes" srcdoc2: "pure/json;pure/base64;pure/scgi;pure/redis;impure/graphics" -srcdoc2: "impure/rdstdin;wrappers/zmq;wrappers/sphinx" +srcdoc2: "impure/rdstdin;wrappers/sphinx" srcdoc2: "pure/collections/tables;pure/collections/sets;pure/collections/lists" srcdoc2: "pure/collections/intsets;pure/collections/queues;pure/encodings" srcdoc2: "pure/events;pure/collections/sequtils;pure/irc;pure/cookies" From dc15e68c25eef0864a881e18d53efb0e6548fbb0 Mon Sep 17 00:00:00 2001 From: Araq Date: Thu, 14 Aug 2014 02:48:09 +0200 Subject: [PATCH 148/234] fixes #1472 --- lib/system.nim | 9 --------- 1 file changed, 9 deletions(-) diff --git a/lib/system.nim b/lib/system.nim index 3bf65c6957..a10c673f94 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -3079,12 +3079,3 @@ when hostOS != "standalone" and not defined(NimrodVM) and not defined(JS): include "system/deepcopy" {.pop.} #{.push warning[GcMem]: off.} - -when not defined(booting): - type - semistatic*[T] = static[T] | T - # indicates a param of proc specialized for each static value, - # but also accepting run-time values - - template isStatic*(x): expr = compiles(static(x)) - # checks whether `x` is a value known at compile-time From 8f5bf0652828e1a477494976e40c1839270c2747 Mon Sep 17 00:00:00 2001 From: Araq Date: Thu, 14 Aug 2014 02:55:04 +0200 Subject: [PATCH 149/234] fixes #1450 --- lib/core/macros.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/core/macros.nim b/lib/core/macros.nim index 334a4b8c76..e290cce329 100644 --- a/lib/core/macros.nim +++ b/lib/core/macros.nim @@ -627,7 +627,7 @@ proc `$`*(node: PNimrodNode): string {.compileTime.} = case node.kind of nnkIdent: result = $node.ident - of nnkStrLit: + of nnkStrLit..nnkTripleStrLit: result = node.strVal else: badNodeKind node.kind, "$" From 65587f726e39af1c8e84c927db8ac26403f02d27 Mon Sep 17 00:00:00 2001 From: Araq Date: Thu, 14 Aug 2014 03:02:36 +0200 Subject: [PATCH 150/234] fixes #1433 --- compiler/vmgen.nim | 2 ++ 1 file changed, 2 insertions(+) diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim index fd0c3fc69c..adbca8ccaa 100644 --- a/compiler/vmgen.nim +++ b/compiler/vmgen.nim @@ -1093,6 +1093,8 @@ proc setSlot(c: PCtx; v: PSym) = # XXX generate type initialization here? if v.position == 0: if c.prc.maxSlots == 0: c.prc.maxSlots = 1 + if c.prc.maxSlots >= high(TRegister): + internalError(v.info, "cannot generate code; too many registers required") v.position = c.prc.maxSlots c.prc.slots[v.position] = (inUse: true, kind: if v.kind == skLet: slotFixedLet else: slotFixedVar) From d59b9a21689d82d424b7be0d699ccbf3ba538d31 Mon Sep 17 00:00:00 2001 From: Reimer Behrends Date: Thu, 14 Aug 2014 03:09:39 +0200 Subject: [PATCH 151/234] Fix stack bottom initialization for non-main modules. Because PreMain() was now called before the new stack bottom initialization, it still relied on the old version of initStackBottom(), which may not handle the top few words of the stack correctly. This patch also sets the stack bottom in PreMain() using the new approach. --- compiler/cgen.nim | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/compiler/cgen.nim b/compiler/cgen.nim index 112a2af34d..2d3831a15a 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -949,12 +949,23 @@ proc genFilenames(m: BModule): PRope = proc genMainProc(m: BModule) = const + # The use of a volatile function pointer to call Pre/NimMainInner + # prevents inlining of the NimMainInner function and dependent + # functions, which might otherwise merge their stack frames. PreMainBody = - "\tsystemDatInit();$N" & + "void PreMainInner() {$N" & "\tsystemInit();$N" & "$1" & "$2" & - "$3" + "$3" & + "}$N$N" & + "void PreMain() {$N" & + "\tvoid (*volatile inner)();$N" & + "\tsystemDatInit();$N" & + "\tinner = PreMainInner;$N" & + "$4" & + "\t(*inner)();$N" & + "}$N$N" MainProcs = "\tNimMain();$N" @@ -962,9 +973,6 @@ proc genMainProc(m: BModule) = MainProcsWithResult = MainProcs & "\treturn nim_program_result;$N" - # The use of a volatile function pointer to call NimMainInner - # prevents inlining of the NimMainInner function and dependent - # functions, which might otherwise merge their stack frames. NimMainBody = "N_CDECL(void, NimMainInner)(void) {$N" & "$1" & @@ -1047,8 +1055,8 @@ proc genMainProc(m: BModule) = platform.targetOS == osStandalone: "".toRope else: ropecg(m, "\t#initStackBottomWith((void *)&inner);$N") inc(m.labels) - appcg(m, m.s[cfsProcs], "void PreMain() {$N" & PreMainBody & "}$N$N", [ - mainDatInit, gBreakpoints, otherModsInit]) + appcg(m, m.s[cfsProcs], PreMainBody, [ + mainDatInit, gBreakpoints, otherModsInit, initStackBottomCall]) appcg(m, m.s[cfsProcs], nimMain, [mainModInit, initStackBottomCall, toRope(m.labels)]) if optNoMain notin gGlobalOptions: From 1a7be4c66f90e63995eec0c27efdf85fa454c130 Mon Sep 17 00:00:00 2001 From: Araq Date: Thu, 14 Aug 2014 03:26:08 +0200 Subject: [PATCH 152/234] fixes #722 --- doc/manual.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/manual.txt b/doc/manual.txt index 6d49bcd32d..89a417fb22 100644 --- a/doc/manual.txt +++ b/doc/manual.txt @@ -5321,7 +5321,7 @@ See `Ordinary vs immediate templates`_. compilation option pragmas -------------------------- The listed pragmas here can be used to override the code generation options -for a section of code. +for a proc/method/converter. The implementation currently provides the following possible options (various others may be added later). From bd32255f90f0789db10865ce5b5565c3af5b033b Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Thu, 14 Aug 2014 19:03:31 +0100 Subject: [PATCH 153/234] Fixes #1158. --- lib/pure/asyncdispatch.nim | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/pure/asyncdispatch.nim b/lib/pure/asyncdispatch.nim index e1837b0ea7..5597acf6fa 100644 --- a/lib/pure/asyncdispatch.nim +++ b/lib/pure/asyncdispatch.nim @@ -27,7 +27,6 @@ export TPort, TSocketFlags ## **Note:** This module is still largely experimental. -# TODO: Discarded void PFutures need to be checked for exception. # TODO: ``except`` statement (without `try`) does not work. # TODO: Multiple exception names in a ``except`` don't work. # TODO: The effect system (raises: []) has trouble with my try transformation. @@ -1003,7 +1002,7 @@ proc processBody(node, retFutureSym: PNimrodNode, of nnkIdent: # await x result = newNimNode(nnkYieldStmt, node).add(node[1]) # -> yield x - of nnkCall: + of nnkCall, nnkCommand: # await foo(p, x) var futureValue: PNimrodNode result.createVar("future" & $node[1][0].toStrLit, node[1], futureValue, @@ -1020,7 +1019,7 @@ proc processBody(node, retFutureSym: PNimrodNode, of nnkVarSection, nnkLetSection: case node[0][2].kind of nnkCommand: - if node[0][2][0].ident == !"await": + if node[0][2][0].kind == nnkIdent and node[0][2][0].ident == !"await": # var x = await y var newVarSection = node # TODO: Should this use copyNimNode? result.createVar("future" & $node[0][0].ident, node[0][2][1], From 06ad50b671f4d236ac558f6fe71fc374f80ead2a Mon Sep 17 00:00:00 2001 From: Araq Date: Thu, 14 Aug 2014 21:56:06 +0200 Subject: [PATCH 154/234] fixes #669 --- compiler/seminst.nim | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/seminst.nim b/compiler/seminst.nim index b93d7ca157..b205eb09a4 100644 --- a/compiler/seminst.nim +++ b/compiler/seminst.nim @@ -33,7 +33,8 @@ proc instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable, localError(a.info, errCannotInstantiateX, s.name.s) t = errorType(c) elif t.kind == tyGenericParam: - internalError(a.info, "instantiateGenericParamList: " & q.name.s) + localError(a.info, errCannotInstantiateX, q.name.s) + t = errorType(c) elif t.kind == tyGenericInvokation: #t = instGenericContainer(c, a, t) t = generateTypeInstance(c, pt, a, t) From 4ab56d6be02de18d5da71f97918ff7d3c78e8340 Mon Sep 17 00:00:00 2001 From: Araq Date: Thu, 14 Aug 2014 22:22:04 +0200 Subject: [PATCH 155/234] some minor fixes --- lib/system.nim | 2 +- tests/assert/tuserassert.nim | 2 +- tests/ccgbugs/tmissinginit.nim | 2 +- tests/testament/specs.nim | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/system.nim b/lib/system.nim index a10c673f94..0d8f63bd48 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -127,7 +127,7 @@ proc definedInScope*(x: expr): bool {. ## **Deprecated since version 0.9.6**: Use ``declaredInScope`` instead. proc declaredInScope*(x: expr): bool {. - magic: "DefinedInScope", noSideEffect, deprecated.} + magic: "DefinedInScope", noSideEffect.} ## Special compile-time procedure that checks whether `x` is ## declared in the current scope. `x` has to be an identifier. diff --git a/tests/assert/tuserassert.nim b/tests/assert/tuserassert.nim index 8710ee4867..57b229ca91 100644 --- a/tests/assert/tuserassert.nim +++ b/tests/assert/tuserassert.nim @@ -3,7 +3,7 @@ discard """ """ template myAssert(cond: expr) = - when rand(3) < 3: + when 3 <= 3: let c = cond.astToStr if not cond: echo c, "ugh" diff --git a/tests/ccgbugs/tmissinginit.nim b/tests/ccgbugs/tmissinginit.nim index 36648ef8d9..d440608e65 100644 --- a/tests/ccgbugs/tmissinginit.nim +++ b/tests/ccgbugs/tmissinginit.nim @@ -4,7 +4,7 @@ discard """ 0 0 [[a = nil, -b = nil]] +b = nil]]''' """ # bug #1475 diff --git a/tests/testament/specs.nim b/tests/testament/specs.nim index 6e72f4b5e3..184f07c510 100644 --- a/tests/testament/specs.nim +++ b/tests/testament/specs.nim @@ -53,7 +53,7 @@ const targetToExt*: array[TTarget, string] = ["c", "cpp", "m", "js"] targetToCmd*: array[TTarget, string] = ["c", "cpp", "objc", "js"] -when not defined(parseCfgBool): +when not declared(parseCfgBool): # candidate for the stdlib: proc parseCfgBool(s: string): bool = case normalize(s) From ae681be62918ea1e766b230e2d098177794469e9 Mon Sep 17 00:00:00 2001 From: Araq Date: Fri, 15 Aug 2014 09:57:03 +0200 Subject: [PATCH 156/234] fixes #1343 --- compiler/vmgen.nim | 7 +++---- tests/vm/twrongarray.nim | 17 +++++++++++++++++ tests/vm/twrongconst.nim | 2 +- 3 files changed, 21 insertions(+), 5 deletions(-) create mode 100644 tests/vm/twrongarray.nim diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim index adbca8ccaa..94afbf008e 100644 --- a/compiler/vmgen.nim +++ b/compiler/vmgen.nim @@ -1118,10 +1118,9 @@ proc checkCanEval(c: PCtx; n: PNode) = # we need to ensure that we don't evaluate 'x' here: # proc foo() = var x ... let s = n.sym - if s.position == 0: - if s.kind in {skVar, skTemp, skLet, skParam, skResult} and - not s.isOwnedBy(c.prc.sym) and s.owner != c.module: - cannotEval(n) + if s.kind in {skVar, skTemp, skLet, skParam, skResult} and + not s.isOwnedBy(c.prc.sym) and s.owner != c.module: + cannotEval(n) proc isTemp(c: PCtx; dest: TDest): bool = result = dest >= 0 and c.prc.slots[dest].kind >= slotTempUnknown diff --git a/tests/vm/twrongarray.nim b/tests/vm/twrongarray.nim new file mode 100644 index 0000000000..c1514d0e9b --- /dev/null +++ b/tests/vm/twrongarray.nim @@ -0,0 +1,17 @@ +discard """ + errormsg: "cannot evaluate at compile time: size" + line: 16 +""" + +#bug #1343 + +when false: + proc one(dummy: int, size: int) = + var x: array[size, int] # compile error: constant expression expected + + proc three(size: int) = + var x: array[size * 1, int] # compile error: cannot evaluate at compile time: size + +proc two(dummy: int, size: int) = + var x: array[size * 1, int] # compiles, but shouldn't? + #assert(x.len == size) # just for fun diff --git a/tests/vm/twrongconst.nim b/tests/vm/twrongconst.nim index 5c0c80f9fd..68ab2757cf 100644 --- a/tests/vm/twrongconst.nim +++ b/tests/vm/twrongconst.nim @@ -4,6 +4,6 @@ discard """ """ var x: array[100, char] -template Foo : expr = x[42] +template foo : expr = x[42] const myConst = foo From 7a5a6ec5bc763eea2d6ec4b18028f22527da637c Mon Sep 17 00:00:00 2001 From: def Date: Fri, 15 Aug 2014 19:06:13 +0200 Subject: [PATCH 157/234] Fix array address on nkHiddenAddr --- compiler/jsgen.nim | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim index 96d8b3d111..cd17202e8b 100644 --- a/compiler/jsgen.nim +++ b/compiler/jsgen.nim @@ -881,14 +881,15 @@ proc genArrayAddr(p: PProc, n: PNode, r: var TCompRes) = a, b: TCompRes first: BiggestInt r.typ = etyBaseIndex - gen(p, n.sons[0], a) - gen(p, n.sons[1], b) + let m = if n.kind == nkHiddenAddr: n.sons[0] else: n + gen(p, m.sons[0], a) + gen(p, m.sons[1], b) internalAssert a.typ != etyBaseIndex and b.typ != etyBaseIndex r.address = a.res - var typ = skipTypes(n.sons[0].typ, abstractPtrs) + var typ = skipTypes(m.sons[0].typ, abstractPtrs) if typ.kind in {tyArray, tyArrayConstr}: first = firstOrd(typ.sons[0]) else: first = 0 - if optBoundsCheck in p.options and not isConstExpr(n.sons[1]): + if optBoundsCheck in p.options and not isConstExpr(m.sons[1]): useMagic(p, "chckIndx") r.res = ropef("chckIndx($1, $2, $3.length)-$2", [b.res, toRope(first), a.res]) From 6a7062fb600f88056e79d9a08828988b00a0ed1a Mon Sep 17 00:00:00 2001 From: def Date: Fri, 15 Aug 2014 19:34:28 +0200 Subject: [PATCH 158/234] Fix swap in jsgen --- compiler/jsgen.nim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim index 96d8b3d111..b4db1a6411 100644 --- a/compiler/jsgen.nim +++ b/compiler/jsgen.nim @@ -833,8 +833,8 @@ proc genSwap(p: PProc, n: PNode) = "local $1 = $2; $2 = $3; $3 = $1;$n", [ tmp, a.address, b.address]) tmp = tmp2 - appf(p.body, "var $1 = $2; $2 = $3; $3 = $1" | - "local $1 = $2; $2 = $3; $3 = $1", [tmp, a.res, b.res]) + appf(p.body, "var $1 = $2; $2 = $3; $3 = $1;" | + "local $1 = $2; $2 = $3; $3 = $1;", [tmp, a.res, b.res]) proc getFieldPosition(f: PNode): int = case f.kind From e460d6e40e5e4aa25905ad55a5153931c686c880 Mon Sep 17 00:00:00 2001 From: def Date: Fri, 15 Aug 2014 19:49:15 +0200 Subject: [PATCH 159/234] Fix CopyStr (substr in system.nim) for javascript target --- compiler/jsgen.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim index 96d8b3d111..d62d99d9d0 100644 --- a/compiler/jsgen.nim +++ b/compiler/jsgen.nim @@ -1351,7 +1351,7 @@ proc genMagic(p: PProc, n: PNode, r: var TCompRes) = of mEcho: genEcho(p, n, r) of mSlurp, mStaticExec: localError(n.info, errXMustBeCompileTime, n.sons[0].sym.name.s) - of mCopyStr: binaryExpr(p, n, r, "", "($1.slice($2,-1))") + of mCopyStr: binaryExpr(p, n, r, "", "($1.slice($2))") of mCopyStrLast: ternaryExpr(p, n, r, "", "($1.slice($2, ($3)+1).concat(0))") of mNewString: unaryExpr(p, n, r, "mnewString", "mnewString($1)") of mNewStringOfCap: unaryExpr(p, n, r, "mnewString", "mnewString(0)") From d10cef11dc70af73b7d0465e55ac07d9469cc417 Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Sat, 16 Aug 2014 00:45:21 +0100 Subject: [PATCH 160/234] Fixes #710. --- compiler/semcall.nim | 2 ++ tests/misc/tissue710.nim | 10 ++++++++++ 2 files changed, 12 insertions(+) create mode 100644 tests/misc/tissue710.nim diff --git a/compiler/semcall.nim b/compiler/semcall.nim index 65a2d7ab89..927b23cf25 100644 --- a/compiler/semcall.nim +++ b/compiler/semcall.nim @@ -81,6 +81,8 @@ proc notFoundError*(c: PContext, n: PNode, errors: seq[string]) = if c.inCompilesContext > 0: # fail fast: globalError(n.info, errTypeMismatch, "") + if errors.len == 0: + localError(n.info, errExprXCannotBeCalled, n[0].renderTree) var result = msgKindToString(errTypeMismatch) add(result, describeArgs(c, n, 1)) add(result, ')') diff --git a/tests/misc/tissue710.nim b/tests/misc/tissue710.nim new file mode 100644 index 0000000000..9e8735eb3b --- /dev/null +++ b/tests/misc/tissue710.nim @@ -0,0 +1,10 @@ +discard """ + file: "tissue710.nim" + line: 8 + errorMsg: "expression '||' cannot be called" +""" +var sum = 0 +for x in 3..1000: + if (x mod 3 == 0) || (x mod 5 == 0): + sum += x +echo(sum) From 53b8d6281d193b72b733a302ae1ec6b93332ac8f Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Sat, 16 Aug 2014 01:15:36 +0100 Subject: [PATCH 161/234] Fixes tenumitems test. --- tests/enum/tenumitems.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/enum/tenumitems.nim b/tests/enum/tenumitems.nim index b6eee5ba81..b92cff6bf5 100644 --- a/tests/enum/tenumitems.nim +++ b/tests/enum/tenumitems.nim @@ -1,6 +1,6 @@ discard """ line: 7 - errormsg: "type mismatch" + errormsg: "expression 'items' cannot be called" """ type a = enum b,c,d From dfba87f3ed05ac46b161e80f1cd2e114be53150c Mon Sep 17 00:00:00 2001 From: def Date: Sat, 16 Aug 2014 02:16:21 +0200 Subject: [PATCH 162/234] Make times module compile with javascript backend --- lib/pure/times.nim | 76 +++++++++++++++++++++++----------------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/lib/pure/times.nim b/lib/pure/times.nim index 4985118998..ebc3b9fdb8 100644 --- a/lib/pure/times.nim +++ b/lib/pure/times.nim @@ -63,44 +63,44 @@ elif defined(windows): elif defined(JS): type TTime* {.final, importc.} = object - getDay: proc (): int {.tags: [], raises: [].} - getFullYear: proc (): int {.tags: [], raises: [].} - getHours: proc (): int {.tags: [], raises: [].} - getMilliseconds: proc (): int {.tags: [], raises: [].} - getMinutes: proc (): int {.tags: [], raises: [].} - getMonth: proc (): int {.tags: [], raises: [].} - getSeconds: proc (): int {.tags: [], raises: [].} - getTime: proc (): int {.tags: [], raises: [].} - getTimezoneOffset: proc (): int {.tags: [], raises: [].} - getDate: proc (): int {.tags: [], raises: [].} - getUTCDate: proc (): int {.tags: [], raises: [].} - getUTCFullYear: proc (): int {.tags: [], raises: [].} - getUTCHours: proc (): int {.tags: [], raises: [].} - getUTCMilliseconds: proc (): int {.tags: [], raises: [].} - getUTCMinutes: proc (): int {.tags: [], raises: [].} - getUTCMonth: proc (): int {.tags: [], raises: [].} - getUTCSeconds: proc (): int {.tags: [], raises: [].} - getUTCDay: proc (): int {.tags: [], raises: [].} - getYear: proc (): int {.tags: [], raises: [].} - parse: proc (s: cstring): TTime {.tags: [], raises: [].} - setDate: proc (x: int) {.tags: [], raises: [].} - setFullYear: proc (x: int) {.tags: [], raises: [].} - setHours: proc (x: int) {.tags: [], raises: [].} - setMilliseconds: proc (x: int) {.tags: [], raises: [].} - setMinutes: proc (x: int) {.tags: [], raises: [].} - setMonth: proc (x: int) {.tags: [], raises: [].} - setSeconds: proc (x: int) {.tags: [], raises: [].} - setTime: proc (x: int) {.tags: [], raises: [].} - setUTCDate: proc (x: int) {.tags: [], raises: [].} - setUTCFullYear: proc (x: int) {.tags: [], raises: [].} - setUTCHours: proc (x: int) {.tags: [], raises: [].} - setUTCMilliseconds: proc (x: int) {.tags: [], raises: [].} - setUTCMinutes: proc (x: int) {.tags: [], raises: [].} - setUTCMonth: proc (x: int) {.tags: [], raises: [].} - setUTCSeconds: proc (x: int) {.tags: [], raises: [].} - setYear: proc (x: int) {.tags: [], raises: [].} - toGMTString: proc (): cstring {.tags: [], raises: [].} - toLocaleString: proc (): cstring {.tags: [], raises: [].} + getDay: proc (): int {.tags: [], raises: [], gcsafe.} + getFullYear: proc (): int {.tags: [], raises: [], gcsafe.} + getHours: proc (): int {.tags: [], raises: [], gcsafe.} + getMilliseconds: proc (): int {.tags: [], raises: [], gcsafe.} + getMinutes: proc (): int {.tags: [], raises: [], gcsafe.} + getMonth: proc (): int {.tags: [], raises: [], gcsafe.} + getSeconds: proc (): int {.tags: [], raises: [], gcsafe.} + getTime: proc (): int {.tags: [], raises: [], gcsafe.} + getTimezoneOffset: proc (): int {.tags: [], raises: [], gcsafe.} + getDate: proc (): int {.tags: [], raises: [], gcsafe.} + getUTCDate: proc (): int {.tags: [], raises: [], gcsafe.} + getUTCFullYear: proc (): int {.tags: [], raises: [], gcsafe.} + getUTCHours: proc (): int {.tags: [], raises: [], gcsafe.} + getUTCMilliseconds: proc (): int {.tags: [], raises: [], gcsafe.} + getUTCMinutes: proc (): int {.tags: [], raises: [], gcsafe.} + getUTCMonth: proc (): int {.tags: [], raises: [], gcsafe.} + getUTCSeconds: proc (): int {.tags: [], raises: [], gcsafe.} + getUTCDay: proc (): int {.tags: [], raises: [], gcsafe.} + getYear: proc (): int {.tags: [], raises: [], gcsafe.} + parse: proc (s: cstring): TTime {.tags: [], raises: [], gcsafe.} + setDate: proc (x: int) {.tags: [], raises: [], gcsafe.} + setFullYear: proc (x: int) {.tags: [], raises: [], gcsafe.} + setHours: proc (x: int) {.tags: [], raises: [], gcsafe.} + setMilliseconds: proc (x: int) {.tags: [], raises: [], gcsafe.} + setMinutes: proc (x: int) {.tags: [], raises: [], gcsafe.} + setMonth: proc (x: int) {.tags: [], raises: [], gcsafe.} + setSeconds: proc (x: int) {.tags: [], raises: [], gcsafe.} + setTime: proc (x: int) {.tags: [], raises: [], gcsafe.} + setUTCDate: proc (x: int) {.tags: [], raises: [], gcsafe.} + setUTCFullYear: proc (x: int) {.tags: [], raises: [], gcsafe.} + setUTCHours: proc (x: int) {.tags: [], raises: [], gcsafe.} + setUTCMilliseconds: proc (x: int) {.tags: [], raises: [], gcsafe.} + setUTCMinutes: proc (x: int) {.tags: [], raises: [], gcsafe.} + setUTCMonth: proc (x: int) {.tags: [], raises: [], gcsafe.} + setUTCSeconds: proc (x: int) {.tags: [], raises: [], gcsafe.} + setYear: proc (x: int) {.tags: [], raises: [], gcsafe.} + toGMTString: proc (): cstring {.tags: [], raises: [], gcsafe.} + toLocaleString: proc (): cstring {.tags: [], raises: [], gcsafe.} type TTimeInfo* = object of TObject ## represents a time in different parts From b1b681aec6ad5774a8f46b52b433dbebb6da77ae Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Sun, 17 Aug 2014 19:18:10 +0100 Subject: [PATCH 163/234] Remove irc module. Ref #1486. --- lib/pure/irc.nim | 503 ----------------------------------------------- 1 file changed, 503 deletions(-) delete mode 100644 lib/pure/irc.nim diff --git a/lib/pure/irc.nim b/lib/pure/irc.nim deleted file mode 100644 index 49d9a9a34e..0000000000 --- a/lib/pure/irc.nim +++ /dev/null @@ -1,503 +0,0 @@ -# -# -# Nimrod's Runtime Library -# (c) Copyright 2012 Dominik Picheta -# See the file "copying.txt", included in this -# distribution, for details about the copyright. -# - -## This module implements an asynchronous IRC client. -## -## Currently this module requires at least some knowledge of the IRC protocol. -## It provides a function for sending raw messages to the IRC server, together -## with some basic functions like sending a message to a channel. -## It automizes the process of keeping the connection alive, so you don't -## need to reply to PING messages. In fact, the server is also PING'ed to check -## the amount of lag. -## -## .. code-block:: Nimrod -## -## var client = irc("picheta.me", joinChans = @["#bots"]) -## client.connect() -## while True: -## var event: TIRCEvent -## if client.poll(event): -## case event.typ -## of EvConnected: nil -## of EvDisconnected: -## client.reconnect() -## of EvMsg: -## # Write your message reading code here. -## -## **Warning:** The API of this module is unstable, and therefore is subject -## to change. - -include "system/inclrtl" - -import sockets, strutils, parseutils, times, asyncio, os - -type - TIRC* = object of TObject - address: string - port: TPort - nick, user, realname, serverPass: string - case isAsync: bool - of true: - handleEvent: proc (irc: PAsyncIRC, ev: TIRCEvent) {.closure, gcsafe.} - asyncSock: PAsyncSocket - myDispatcher: PDispatcher - of false: - dummyA: pointer - dummyB: pointer # workaround a Nimrod API issue - dummyC: pointer - sock: TSocket - status: TInfo - lastPing: float - lastPong: float - lag: float - channelsToJoin: seq[string] - msgLimit: bool - messageBuffer: seq[tuple[timeToSend: float, m: string]] - lastReconnect: float - - PIRC* = ref TIRC - - PAsyncIRC* = ref TAsyncIRC - TAsyncIRC* = object of TIRC - - TIRCMType* = enum - MUnknown, - MNumeric, - MPrivMsg, - MJoin, - MPart, - MMode, - MTopic, - MInvite, - MKick, - MQuit, - MNick, - MNotice, - MPing, - MPong, - MError - - TIRCEventType* = enum - EvMsg, EvConnected, EvDisconnected - TIRCEvent* = object ## IRC Event - case typ*: TIRCEventType - of EvConnected: - ## Connected to server. - ## Only occurs with AsyncIRC. - nil - of EvDisconnected: - ## Disconnected from the server - nil - of EvMsg: ## Message from the server - cmd*: TIRCMType ## Command (e.g. PRIVMSG) - nick*, user*, host*, servername*: string - numeric*: string ## Only applies to ``MNumeric`` - params*: seq[string] ## Parameters of the IRC message - origin*: string ## The channel/user that this msg originated from - raw*: string ## Raw IRC message - timestamp*: TTime ## UNIX epoch time the message was received - -proc send*(irc: PIRC, message: string, sendImmediately = false) = - ## Sends ``message`` as a raw command. It adds ``\c\L`` for you. - var sendMsg = true - if irc.msgLimit and not sendImmediately: - var timeToSend = epochTime() - if irc.messageBuffer.len() >= 3: - timeToSend = (irc.messageBuffer[irc.messageBuffer.len()-1][0] + 2.0) - - irc.messageBuffer.add((timeToSend, message)) - sendMsg = false - - if sendMsg: - try: - if irc.isAsync: - irc.asyncSock.send(message & "\c\L") - else: - irc.sock.send(message & "\c\L") - except EOS: - # Assuming disconnection of every EOS could be bad, - # but I can't exactly check for EBrokenPipe. - irc.status = SockClosed - -proc privmsg*(irc: PIRC, target, message: string) = - ## Sends ``message`` to ``target``. ``Target`` can be a channel, or a user. - irc.send("PRIVMSG $1 :$2" % [target, message]) - -proc notice*(irc: PIRC, target, message: string) = - ## Sends ``notice`` to ``target``. ``Target`` can be a channel, or a user. - irc.send("NOTICE $1 :$2" % [target, message]) - -proc join*(irc: PIRC, channel: string, key = "") = - ## Joins ``channel``. - ## - ## If key is not ``""``, then channel is assumed to be key protected and this - ## function will join the channel using ``key``. - if key == "": - irc.send("JOIN " & channel) - else: - irc.send("JOIN " & channel & " " & key) - -proc part*(irc: PIRC, channel, message: string) = - ## Leaves ``channel`` with ``message``. - irc.send("PART " & channel & " :" & message) - -proc close*(irc: PIRC) = - ## Closes connection to an IRC server. - ## - ## **Warning:** This procedure does not send a ``QUIT`` message to the server. - irc.status = SockClosed - if irc.isAsync: - irc.asyncSock.close() - else: - irc.sock.close() - -proc isNumber(s: string): bool = - ## Checks if `s` contains only numbers. - var i = 0 - while s[i] in {'0'..'9'}: inc(i) - result = i == s.len and s.len > 0 - -proc parseMessage(msg: string): TIRCEvent = - result.typ = EvMsg - result.cmd = MUnknown - result.raw = msg - result.timestamp = times.getTime() - var i = 0 - # Process the prefix - if msg[i] == ':': - inc(i) # Skip `:` - var nick = "" - i.inc msg.parseUntil(nick, {'!', ' '}, i) - result.nick = "" - result.serverName = "" - if msg[i] == '!': - result.nick = nick - inc(i) # Skip `!` - i.inc msg.parseUntil(result.user, {'@'}, i) - inc(i) # Skip `@` - i.inc msg.parseUntil(result.host, {' '}, i) - inc(i) # Skip ` ` - else: - result.serverName = nick - inc(i) # Skip ` ` - - # Process command - var cmd = "" - i.inc msg.parseUntil(cmd, {' '}, i) - - if cmd.isNumber: - result.cmd = MNumeric - result.numeric = cmd - else: - case cmd - of "PRIVMSG": result.cmd = MPrivMsg - of "JOIN": result.cmd = MJoin - of "PART": result.cmd = MPart - of "PONG": result.cmd = MPong - of "PING": result.cmd = MPing - of "MODE": result.cmd = MMode - of "TOPIC": result.cmd = MTopic - of "INVITE": result.cmd = MInvite - of "KICK": result.cmd = MKick - of "QUIT": result.cmd = MQuit - of "NICK": result.cmd = MNick - of "NOTICE": result.cmd = MNotice - of "ERROR": result.cmd = MError - else: result.cmd = MUnknown - - # Don't skip space here. It is skipped in the following While loop. - - # Params - result.params = @[] - var param = "" - while msg[i] != '\0' and msg[i] != ':': - inc(i) # Skip ` `. - i.inc msg.parseUntil(param, {' ', ':', '\0'}, i) - if param != "": - result.params.add(param) - param.setlen(0) - - if msg[i] == ':': - inc(i) # Skip `:`. - result.params.add(msg[i..msg.len-1]) - -proc connect*(irc: PIRC) = - ## Connects to an IRC server as specified by ``irc``. - assert(irc.address != "") - assert(irc.port != TPort(0)) - - irc.sock.connect(irc.address, irc.port) - - irc.status = SockConnected - - # Greet the server :) - if irc.serverPass != "": irc.send("PASS " & irc.serverPass, true) - irc.send("NICK " & irc.nick, true) - irc.send("USER $1 * 0 :$2" % [irc.user, irc.realname], true) - -proc reconnect*(irc: PIRC, timeout = 5000) = - ## Reconnects to an IRC server. - ## - ## ``Timeout`` specifies the time to wait in miliseconds between multiple - ## consecutive reconnections. - ## - ## This should be used when an ``EvDisconnected`` event occurs. - let secSinceReconnect = int(epochTime() - irc.lastReconnect) - if secSinceReconnect < timeout: - sleep(timeout - secSinceReconnect) - irc.sock = socket() - if irc.sock == InvalidSocket: osError(osLastError()) - irc.connect() - irc.lastReconnect = epochTime() - -proc irc*(address: string, port: TPort = 6667.TPort, - nick = "NimrodBot", - user = "NimrodBot", - realname = "NimrodBot", serverPass = "", - joinChans: seq[string] = @[], - msgLimit: bool = true): PIRC = - ## Creates a ``TIRC`` object. - new(result) - result.address = address - result.port = port - result.nick = nick - result.user = user - result.realname = realname - result.serverPass = serverPass - result.lastPing = epochTime() - result.lastPong = -1.0 - result.lag = -1.0 - result.channelsToJoin = joinChans - result.msgLimit = msgLimit - result.messageBuffer = @[] - result.status = SockIdle - result.sock = socket() - if result.sock == InvalidSocket: osError(osLastError()) - -proc processLine(irc: PIRC, line: string): TIRCEvent = - if line.len == 0: - irc.close() - result.typ = EvDisconnected - else: - result = parseMessage(line) - # Get the origin - result.origin = result.params[0] - if result.origin == irc.nick and - result.nick != "": result.origin = result.nick - - if result.cmd == MError: - irc.close() - result.typ = EvDisconnected - return - - if result.cmd == MPing: - irc.send("PONG " & result.params[0]) - if result.cmd == MPong: - irc.lag = epochTime() - parseFloat(result.params[result.params.high]) - irc.lastPong = epochTime() - if result.cmd == MNumeric: - if result.numeric == "001": - # Check the nickname. - if irc.nick != result.params[0]: - assert ' ' notin result.params[0] - irc.nick = result.params[0] - for chan in items(irc.channelsToJoin): - irc.join(chan) - if result.cmd == MNick: - if result.nick == irc.nick: - irc.nick = result.params[0] - -proc processOther(irc: PIRC, ev: var TIRCEvent): bool = - result = false - if epochTime() - irc.lastPing >= 20.0: - irc.lastPing = epochTime() - irc.send("PING :" & formatFloat(irc.lastPing), true) - - if epochTime() - irc.lastPong >= 120.0 and irc.lastPong != -1.0: - irc.close() - ev.typ = EvDisconnected # TODO: EvTimeout? - return true - - for i in 0..irc.messageBuffer.len-1: - if epochTime() >= irc.messageBuffer[0][0]: - irc.send(irc.messageBuffer[0].m, true) - irc.messageBuffer.delete(0) - else: - break # messageBuffer is guaranteed to be from the quickest to the - # later-est. - -proc poll*(irc: PIRC, ev: var TIRCEvent, - timeout: int = 500): bool = - ## This function parses a single message from the IRC server and returns - ## a TIRCEvent. - ## - ## This function should be called often as it also handles pinging - ## the server. - ## - ## This function provides a somewhat asynchronous IRC implementation, although - ## it should only be used for simple things for example an IRC bot which does - ## not need to be running many time critical tasks in the background. If you - ## require this, use the asyncio implementation. - - if not (irc.status == SockConnected): - # Do not close the socket here, it is already closed! - ev.typ = EvDisconnected - var line = TaintedString"" - var socks = @[irc.sock] - var ret = socks.select(timeout) - if ret == -1: osError(osLastError()) - if socks.len() != 0 and ret != 0: - irc.sock.readLine(line) - ev = irc.processLine(line.string) - result = true - - if processOther(irc, ev): result = true - -proc getLag*(irc: PIRC): float = - ## Returns the latency between this client and the IRC server in seconds. - ## - ## If latency is unknown, returns -1.0. - return irc.lag - -proc isConnected*(irc: PIRC): bool = - ## Returns whether this IRC client is connected to an IRC server. - return irc.status == SockConnected - -proc getNick*(irc: PIRC): string = - ## Returns the current nickname of the client. - return irc.nick - -# -- Asyncio dispatcher - -proc handleConnect(s: PAsyncSocket, irc: PAsyncIRC) = - # Greet the server :) - if irc.serverPass != "": irc.send("PASS " & irc.serverPass, true) - irc.send("NICK " & irc.nick, true) - irc.send("USER $1 * 0 :$2" % [irc.user, irc.realname], true) - irc.status = SockConnected - - var ev: TIRCEvent - ev.typ = EvConnected - irc.handleEvent(irc, ev) - -proc handleRead(s: PAsyncSocket, irc: PAsyncIRC) = - var line = "".TaintedString - var ret = s.readLine(line) - if ret: - if line == "": - var ev: TIRCEvent - irc.close() - ev.typ = EvDisconnected - irc.handleEvent(irc, ev) - else: - var ev = irc.processLine(line.string) - irc.handleEvent(irc, ev) - -proc handleTask(s: PAsyncSocket, irc: PAsyncIRC) = - var ev: TIRCEvent - if irc.processOther(ev): - irc.handleEvent(irc, ev) - -proc register*(d: PDispatcher, irc: PAsyncIRC) = - ## Registers ``irc`` with dispatcher ``d``. - irc.asyncSock.handleConnect = - proc (s: PAsyncSocket) = - handleConnect(s, irc) - irc.asyncSock.handleRead = - proc (s: PAsyncSocket) = - handleRead(s, irc) - irc.asyncSock.handleTask = - proc (s: PAsyncSocket) = - handleTask(s, irc) - d.register(irc.asyncSock) - irc.myDispatcher = d - -proc connect*(irc: PAsyncIRC) = - ## Equivalent of connect for ``TIRC`` but specifically created for asyncio. - assert(irc.address != "") - assert(irc.port != TPort(0)) - - irc.asyncSock.connect(irc.address, irc.port) - -proc reconnect*(irc: PAsyncIRC, timeout = 5000) = - ## Reconnects to an IRC server. - ## - ## ``Timeout`` specifies the time to wait in miliseconds between multiple - ## consecutive reconnections. - ## - ## This should be used when an ``EvDisconnected`` event occurs. - ## - ## When successfully reconnected an ``EvConnected`` event will occur. - let secSinceReconnect = int(epochTime() - irc.lastReconnect) - if secSinceReconnect < timeout: - sleep(timeout - secSinceReconnect) - irc.asyncSock = AsyncSocket() - irc.myDispatcher.register(irc) - irc.connect() - irc.lastReconnect = epochTime() - -proc asyncIRC*(address: string, port: TPort = 6667.TPort, - nick = "NimrodBot", - user = "NimrodBot", - realname = "NimrodBot", serverPass = "", - joinChans: seq[string] = @[], - msgLimit: bool = true, - ircEvent: proc (irc: PAsyncIRC, ev: TIRCEvent) {.closure,gcsafe.} - ): PAsyncIRC = - ## Use this function if you want to use asyncio's dispatcher. - ## - ## **Note:** Do **NOT** use this if you're writing a simple IRC bot which only - ## requires one task to be run, i.e. this should not be used if you want a - ## synchronous IRC client implementation, use ``irc`` for that. - - new(result) - result.isAsync = true - result.address = address - result.port = port - result.nick = nick - result.user = user - result.realname = realname - result.serverPass = serverPass - result.lastPing = epochTime() - result.lastPong = -1.0 - result.lag = -1.0 - result.channelsToJoin = joinChans - result.msgLimit = msgLimit - result.messageBuffer = @[] - result.handleEvent = ircEvent - result.asyncSock = AsyncSocket() - -when isMainModule: - #var m = parseMessage("ERROR :Closing Link: dom96.co.cc (Ping timeout: 252 seconds)") - #echo(repr(m)) - - - - var client = irc("amber.tenthbit.net", nick="TestBot1234", - joinChans = @["#flood"]) - client.connect() - while true: - var event: TIRCEvent - if client.poll(event): - case event.typ - of EvConnected: - discard - of EvDisconnected: - break - of EvMsg: - if event.cmd == MPrivMsg: - var msg = event.params[event.params.high] - if msg == "|test": client.privmsg(event.origin, "hello") - if msg == "|excessFlood": - for i in 0..10: - client.privmsg(event.origin, "TEST" & $i) - - #echo( repr(event) ) - #echo("Lag: ", formatFloat(client.getLag())) - - From aa732881422ebd011871217dfe4713bf9dfebf90 Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Sun, 17 Aug 2014 19:19:20 +0100 Subject: [PATCH 164/234] Export `==` from net module for TPort. --- lib/pure/net.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pure/net.nim b/lib/pure/net.nim index f35e0cf63e..6965274671 100644 --- a/lib/pure/net.nim +++ b/lib/pure/net.nim @@ -11,7 +11,7 @@ {.deadCodeElim: on.} import rawsockets, os, strutils, unsigned, parseutils, times -export TPort, `$` +export TPort, `$`, `==` const useWinVersion = defined(Windows) or defined(nimdoc) From 710cbe3f1f5947ec76e517fa9a4f679ec653eefd Mon Sep 17 00:00:00 2001 From: Araq Date: Sun, 17 Aug 2014 21:23:46 +0200 Subject: [PATCH 165/234] fixes #1492 --- compiler/condsyms.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/condsyms.nim b/compiler/condsyms.nim index 5eb951e26d..dc61d2f894 100644 --- a/compiler/condsyms.nim +++ b/compiler/condsyms.nim @@ -57,7 +57,7 @@ const endb profiler executable guiapp consoleapp library dll staticlib - quick nimbabel + quick release debug useWinAnsi useFork useNimRtl useMalloc useRealtimeGC ssl memProfiler nodejs kwin From b5248d9037c4240dccdd6d46eac8b104dea10852 Mon Sep 17 00:00:00 2001 From: Araq Date: Tue, 19 Aug 2014 10:01:46 +0200 Subject: [PATCH 166/234] fixes #1143 --- compiler/astalgo.nim | 27 +++++++++++++++------------ compiler/ccgtypes.nim | 2 +- compiler/ccgutils.nim | 6 +++++- 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/compiler/astalgo.nim b/compiler/astalgo.nim index 3431aaf418..16efbb172e 100644 --- a/compiler/astalgo.nim +++ b/compiler/astalgo.nim @@ -390,29 +390,30 @@ proc symToYaml(n: PSym, indent: int = 0, maxRecDepth: int = - 1): PRope = var marker = initIntSet() result = symToYamlAux(n, marker, indent, maxRecDepth) -proc debugTree(n: PNode, indent: int, maxRecDepth: int): PRope -proc debugType(n: PType): PRope = +proc debugTree(n: PNode, indent: int, maxRecDepth: int; renderType=false): PRope +proc debugType(n: PType, maxRecDepth=100): PRope = if n == nil: result = toRope("null") - else: + else: result = toRope($n.kind) if n.sym != nil: app(result, " ") app(result, n.sym.name.s) - if (n.kind != tyString) and (sonsLen(n) > 0): + if (n.kind != tyString) and (sonsLen(n) > 0) and maxRecDepth != 0: app(result, "(") - for i in countup(0, sonsLen(n) - 1): + for i in countup(0, sonsLen(n) - 1): if i > 0: app(result, ", ") - if n.sons[i] == nil: + if n.sons[i] == nil: app(result, "null") - else: - app(result, debugType(n.sons[i])) - if n.kind == tyObject and n.n != nil: + else: + app(result, debugType(n.sons[i], maxRecDepth-1)) + if n.kind == tyObject and n.n != nil: app(result, ", node: ") - app(result, debugTree(n.n, 2, 100)) + app(result, debugTree(n.n, 2, maxRecDepth-1, renderType=true)) app(result, ")") -proc debugTree(n: PNode, indent: int, maxRecDepth: int): PRope = +proc debugTree(n: PNode, indent: int, maxRecDepth: int; + renderType=false): PRope = if n == nil: result = toRope("null") else: @@ -436,6 +437,8 @@ proc debugTree(n: PNode, indent: int, maxRecDepth: int): PRope = [istr, toRope(n.sym.name.s), toRope(n.sym.id)]) # [istr, symToYaml(n.sym, indent, maxRecDepth), # toRope(n.sym.id)]) + if renderType and n.sym.typ != nil: + appf(result, ",$N$1\"typ\": $2", [istr, debugType(n.sym.typ, 2)]) of nkIdent: if n.ident != nil: appf(result, ",$N$1\"ident\": $2", [istr, makeYamlString(n.ident.s)]) @@ -447,7 +450,7 @@ proc debugTree(n: PNode, indent: int, maxRecDepth: int): PRope = for i in countup(0, sonsLen(n) - 1): if i > 0: app(result, ",") appf(result, "$N$1$2", [spaces(indent + 4), debugTree(n.sons[i], - indent + 4, maxRecDepth - 1)]) + indent + 4, maxRecDepth - 1, renderType)]) appf(result, "$N$1]", [istr]) appf(result, ",$N$1\"info\": $2", [istr, lineInfoToStr(n.info)]) appf(result, "$N$1}", [spaces(indent)]) diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim index 86142995cc..fc6febc6ff 100644 --- a/compiler/ccgtypes.nim +++ b/compiler/ccgtypes.nim @@ -723,7 +723,7 @@ proc discriminatorTableName(m: BModule, objtype: PType, d: PSym): PRope = if objtype.sym == nil: internalError(d.info, "anonymous obj with discriminator") result = ropef("NimDT_$1_$2", [ - toRope(objtype.sym.name.s.mangle), toRope(d.name.s.mangle)]) + toRope(objtype.id), toRope(d.name.s.mangle)]) proc discriminatorTableDecl(m: BModule, objtype: PType, d: PSym): PRope = discard cgsym(m, "TNimNode") diff --git a/compiler/ccgutils.nim b/compiler/ccgutils.nim index 6af6a857c6..65957584a1 100644 --- a/compiler/ccgutils.nim +++ b/compiler/ccgutils.nim @@ -94,6 +94,10 @@ proc getUniqueType*(key: PType): PType = else: result = getUniqueType(lastSon(key)) of tyGenericInst, tyOrdinal, tyMutable, tyConst, tyIter, tyStatic: result = getUniqueType(lastSon(key)) + #let obj = lastSon(key) + #if obj.sym != nil and obj.sym.name.s == "TOption": + # echo "for ", typeToString(key), " I returned " + # debug result of tyArrayConstr, tyGenericInvokation, tyGenericBody, tyOpenArray, tyArray, tySet, tyRange, tyTuple, tyPtr, tyRef, tySequence, tyForward, tyVarargs, tyProxy, tyVar: @@ -126,7 +130,7 @@ proc getUniqueType*(key: PType): PType = if t != nil and sameType(t, key): return t idTablePut(gTypeTable[k], key, key) - result = key + result = key of tyEnum: result = PType(idTableGet(gTypeTable[k], key)) if result == nil: From 4708cebaa29957a59010b56d6c47b04d264f7fd6 Mon Sep 17 00:00:00 2001 From: Araq Date: Tue, 19 Aug 2014 10:07:12 +0200 Subject: [PATCH 167/234] fixes #592 --- tests/overload/toverl4.nim | 77 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 tests/overload/toverl4.nim diff --git a/tests/overload/toverl4.nim b/tests/overload/toverl4.nim new file mode 100644 index 0000000000..6bb3a53d10 --- /dev/null +++ b/tests/overload/toverl4.nim @@ -0,0 +1,77 @@ +discard """ + output: '''true''' +""" + +#bug #592 + +type + ElementKind = enum inner, leaf + TElement[TKey, TData] = object + case kind: ElementKind + of inner: + key: TKey + left, right: ref TElement[Tkey, TData] + of leaf: + data: TData + PElement[TKey, TData] = ref TElement[TKey, TData] + +proc newElement[Tkey, TData](other: PElement[TKey, TData]): PElement[Tkey, TData] = + case other.kind: + of inner: + PElement[TKey, TData](kind: ElementKind.inner, key: other.key, left: other.left, right: other.right) + of leaf: + PElement[TKey, TData](kind: ElementKind.leaf, data: other.data) + +proc newElement[TKey, TData](key: TKey, left: PElement[TKey, TData] = nil, right: PElement[TKey, TData] = nil) : PElement[TKey, TData] = + PElement[TKey, TData](kind: ElementKind.inner, key: key, left: left, right: right) + +proc newElement[Tkey, TData](key: Tkey, data: TData) : PElement[Tkey, TData] = + PElement[TKey, TData](kind: ElementKind.leaf, data: data) + +proc find*[TKey, TData](root: PElement[TKey, TData], key: TKey): TData {.raises: [EInvalidKey].} = + if root.left == nil: + raise newException(EInvalidKey, "key does not exist: " & key) + + var tmp_element = addr(root) + + while tmp_element.kind == inner and tmp_element.right != nil: + tmp_element = if tmp_element.key > key: + addr(tmp_element.left) + else: + addr(tmp_element.right) + + if tmp_element.key == key: + return tmp_element.left.data + else: + raise newException(EInvalidKey, "key does not exist: " & key) + +proc add*[TKey, TData](root: var PElement[TKey, TData], key: TKey, data: TData) : bool = + if root.left == nil: + root.key = key + root.left = newElement[TKey, TData](key, data) + return true + + var tmp_element = addr(root) + + while tmp_element.kind == ElementKind.inner and tmp_element.right != nil: + tmp_element = if tmp_element.key > key: + addr(tmp_element.left) + else: + addr(tmp_element.right) + + if tmp_element.key == key: + return false + + var old_element = newElement[TKey, TData](tmp_element[]) + var new_element = newElement[TKey, TData](key, data) + + tmp_element[] = if tmp_element.key < key: + newElement(key, old_element, new_element) + else: + newElement(tmp_element.key, new_element, old_element) + + return true + +var tree = PElement[int, int](kind: ElementKind.inner, key: 0, left: nil, right: nil) +let result = add(tree, 1, 1) +echo(result) \ No newline at end of file From 5a2bea7408d98bb951b1c3504d19147d0b419f7a Mon Sep 17 00:00:00 2001 From: Araq Date: Tue, 19 Aug 2014 20:18:33 +0200 Subject: [PATCH 168/234] fixes #1445 --- lib/system/assign.nim | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lib/system/assign.nim b/lib/system/assign.nim index 2ae945fb1c..0e27eb57fe 100644 --- a/lib/system/assign.nim +++ b/lib/system/assign.nim @@ -89,14 +89,10 @@ proc genericAssignAux(dest, src: pointer, mt: PNimType, shallow: bool) = copyMem(dest, src, mt.size) # copy raw bits proc genericAssign(dest, src: pointer, mt: PNimType) {.compilerProc.} = - GC_disable() genericAssignAux(dest, src, mt, false) - GC_enable() proc genericShallowAssign(dest, src: pointer, mt: PNimType) {.compilerProc.} = - GC_disable() genericAssignAux(dest, src, mt, true) - GC_enable() when false: proc debugNimType(t: PNimType) = From 1deb9820f5473afc1469064488f4ed45a2aabb55 Mon Sep 17 00:00:00 2001 From: Araq Date: Tue, 19 Aug 2014 20:28:51 +0200 Subject: [PATCH 169/234] fixes #1420 --- compiler/types.nim | 2 +- tests/misc/tunsignedcmp.nim | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 tests/misc/tunsignedcmp.nim diff --git a/compiler/types.nim b/compiler/types.nim index 7559f4d2d6..b25e3f6979 100644 --- a/compiler/types.nim +++ b/compiler/types.nim @@ -99,7 +99,7 @@ proc isPureObject(typ: PType): bool = proc getOrdValue(n: PNode): BiggestInt = case n.kind - of nkCharLit..nkInt64Lit: result = n.intVal + of nkCharLit..nkUInt64Lit: result = n.intVal of nkNilLit: result = 0 of nkHiddenStdConv: result = getOrdValue(n.sons[1]) else: diff --git a/tests/misc/tunsignedcmp.nim b/tests/misc/tunsignedcmp.nim new file mode 100644 index 0000000000..a66fbaae1b --- /dev/null +++ b/tests/misc/tunsignedcmp.nim @@ -0,0 +1,15 @@ +discard """ + output: '''true +true +true''' +""" + +# bug 1420 +import unsigned + +var x = 40'u32 +var y = 30'u32 +echo x > y # works + +echo((40'i32) > (30'i32)) +echo((40'u32) > (30'u32)) # Error: ordinal type expected From e935a35bcf97aaf34d9ef0edb016a9dd3c0894a1 Mon Sep 17 00:00:00 2001 From: Araq Date: Tue, 19 Aug 2014 20:42:48 +0200 Subject: [PATCH 170/234] fixes #1380 --- compiler/semexprs.nim | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index aadcdb2f49..da12ec08cd 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -1374,20 +1374,19 @@ proc lookUpForDefined(c: PContext, n: PNode, onlyCurrentScope: bool): PSym = if onlyCurrentScope: return checkSonsLen(n, 2) var m = lookUpForDefined(c, n.sons[0], onlyCurrentScope) - if (m != nil) and (m.kind == skModule): - if (n.sons[1].kind == nkIdent): - var ident = n.sons[1].ident - if m == c.module: - result = strTableGet(c.topLevelScope.symbols, ident) - else: - result = strTableGet(m.tab, ident) + if m != nil and m.kind == skModule: + let ident = considerQuotedIdent(n[1]) + if m == c.module: + result = strTableGet(c.topLevelScope.symbols, ident) else: - localError(n.sons[1].info, errIdentifierExpected, "") + result = strTableGet(m.tab, ident) of nkAccQuoted: result = lookUpForDefined(c, considerQuotedIdent(n), onlyCurrentScope) of nkSym: result = n.sym - else: + of nkOpenSymChoice, nkClosedSymChoice: + result = n.sons[0].sym + else: localError(n.info, errIdentifierExpected, renderTree(n)) result = nil From 9c0d25dc942d59a88ffcdcc464362ffb70c13ec2 Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Tue, 19 Aug 2014 20:16:27 +0100 Subject: [PATCH 171/234] Fixes docgen. --- web/nimrod.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/nimrod.ini b/web/nimrod.ini index 3277718508..64376cd66e 100644 --- a/web/nimrod.ini +++ b/web/nimrod.ini @@ -57,7 +57,7 @@ srcdoc2: "pure/json;pure/base64;pure/scgi;pure/redis;impure/graphics" srcdoc2: "impure/rdstdin;wrappers/sphinx" srcdoc2: "pure/collections/tables;pure/collections/sets;pure/collections/lists" srcdoc2: "pure/collections/intsets;pure/collections/queues;pure/encodings" -srcdoc2: "pure/events;pure/collections/sequtils;pure/irc;pure/cookies" +srcdoc2: "pure/events;pure/collections/sequtils;pure/cookies" srcdoc2: "pure/ftpclient;pure/memfiles;pure/subexes;pure/collections/critbits" srcdoc2: "pure/asyncio;pure/actors;core/locks;pure/oids;pure/endians;pure/uri" srcdoc2: "pure/nimprof;pure/unittest;packages/docutils/highlite" From a0b2fb5bd7e4fa1578800851cec9736fc30e6ef1 Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Tue, 19 Aug 2014 20:54:12 +0100 Subject: [PATCH 172/234] Implements `or` and `and` for futures. Ref #1487. --- lib/pure/asyncdispatch.nim | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/lib/pure/asyncdispatch.nim b/lib/pure/asyncdispatch.nim index 5597acf6fa..5dfcf4656d 100644 --- a/lib/pure/asyncdispatch.nim +++ b/lib/pure/asyncdispatch.nim @@ -180,6 +180,27 @@ proc asyncCheck*[T](future: PFuture[T]) = echoOriginalStackTrace(future) raise future.error +proc `and`*[T, Y](fut1: PFuture[T], fut2: PFuture[Y]): PFuture[void] = + ## Returns a future which will complete once both ``fut1`` and ``fut2`` + ## complete. + var retFuture = newFuture[void]() + fut1.callback = + proc () = + if fut2.finished: retFuture.complete() + fut2.callback = + proc () = + if fut1.finished: retFuture.complete() + return retFuture + +proc `or`*[T, Y](fut1: PFuture[T], fut2: PFuture[Y]): PFuture[void] = + ## Returns a future which will complete once either ``fut1`` or ``fut2`` + ## complete. + var retFuture = newFuture[void]() + proc cb() = + if not retFuture.finished: retFuture.complete() + fut1.callback = cb + fut2.callback = cb + type PDispatcherBase = ref object of PObject timers: seq[tuple[finishAt: float, fut: PFuture[void]]] From ebe313e627d0184596cc7af6d49fa0814ec407d0 Mon Sep 17 00:00:00 2001 From: Araq Date: Tue, 19 Aug 2014 22:35:16 +0200 Subject: [PATCH 173/234] fixes #1334 --- compiler/astalgo.nim | 12 ------------ compiler/types.nim | 32 ++++++++++++++++++++++++++++++++ tests/misc/tvarious1.nim | 9 ++++++++- 3 files changed, 40 insertions(+), 13 deletions(-) diff --git a/compiler/astalgo.nim b/compiler/astalgo.nim index 16efbb172e..eb7ffc63e7 100644 --- a/compiler/astalgo.nim +++ b/compiler/astalgo.nim @@ -116,14 +116,6 @@ proc iiTablePut*(t: var TIITable, key, val: int) # implementation -proc skipConv*(n: PNode): PNode = - case n.kind - of nkObjUpConv, nkObjDownConv, nkChckRange, nkChckRangeF, nkChckRange64: - result = n.sons[0] - of nkHiddenStdConv, nkHiddenSubConv, nkConv: - result = n.sons[1] - else: result = n - proc skipConvAndClosure*(n: PNode): PNode = result = n while true: @@ -135,10 +127,6 @@ proc skipConvAndClosure*(n: PNode): PNode = result = result.sons[1] else: break -proc skipConvTakeType*(n: PNode): PNode = - result = n.skipConv - result.typ = n.typ - proc sameValue*(a, b: PNode): bool = result = false case a.kind diff --git a/compiler/types.nim b/compiler/types.nim index b25e3f6979..824ca47d09 100644 --- a/compiler/types.nim +++ b/compiler/types.nim @@ -1369,3 +1369,35 @@ proc containsCompileTimeOnly*(t: PType): bool = if t.sons[i] != nil and isCompileTimeOnly(t.sons[i]): return true return false + +type + OrdinalType* = enum + NoneLike, IntLike, FloatLike + +proc classify*(t: PType): OrdinalType = + ## for convenient type checking: + if t == nil: + result = NoneLike + else: + case skipTypes(t, abstractVarRange).kind + of tyFloat..tyFloat128: result = FloatLike + of tyInt..tyInt64, tyUInt..tyUInt64, tyBool, tyChar, tyEnum: + result = IntLike + else: result = NoneLike + +proc skipConv*(n: PNode): PNode = + result = n + case n.kind + of nkObjUpConv, nkObjDownConv, nkChckRange, nkChckRangeF, nkChckRange64: + # only skip the conversion if it doesn't lose too important information + # (see bug # + if n.sons[0].typ.classify == n.typ.classify: + result = n.sons[0] + of nkHiddenStdConv, nkHiddenSubConv, nkConv: + if n.sons[1].typ.classify == n.typ.classify: + result = n.sons[1] + else: discard + +proc skipConvTakeType*(n: PNode): PNode = + result = n.skipConv + result.typ = n.typ diff --git a/tests/misc/tvarious1.nim b/tests/misc/tvarious1.nim index 6e4612ae30..1f2da2ae5d 100644 --- a/tests/misc/tvarious1.nim +++ b/tests/misc/tvarious1.nim @@ -3,7 +3,8 @@ discard """ output: '''1 0 Whopie -12''' +12 +1.7''' """ echo len([1_000_000]) #OUT 1 @@ -39,3 +40,9 @@ var val12 = TSomeRange(hour: 12) value = $(if val12.hour > 12: val12.hour - 12 else: val12.hour) echo value + +# bug #1334 + +var ys = @[4.1, 5.6, 7.2, 1.7, 9.3, 4.4, 3.2] +#var x = int(ys.high / 2) #echo ys[x] # Works +echo ys[int(ys.high / 2)] # Doesn't work From 9ee59da4121ea43a646c373c83844d44c4a574c4 Mon Sep 17 00:00:00 2001 From: Araq Date: Tue, 19 Aug 2014 22:57:49 +0200 Subject: [PATCH 174/234] minor improvements for the FAQ --- web/question.txt | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/web/question.txt b/web/question.txt index 89e242e354..be90cc67a9 100644 --- a/web/question.txt +++ b/web/question.txt @@ -28,6 +28,14 @@ one of the even fewer that produces native binaries that require no runtime or interpreter. +What have been the major influences in the language's design? +------------------------------------------------------------- + +The language borrows heavily from: Modula 3, Delphi, Ada, C++, Python, Lisp, +Oberon. As far as possible the list is sorted by the impact of influence. + + + What is Nimrod's take on concurrency? ------------------------------------- @@ -89,8 +97,8 @@ Why is it named ``proc``? *Procedure* used to be the common term as opposed to a *function* which is a mathematical entity that has no side effects. It was planned to have ``func`` -as syntactic sugar for ``proc {.noSideEffect.}`` but the more fine-grained -effect system makes that unimportant. +as syntactic sugar for ``proc {.noSideEffect.}`` but with the more fine-grained +effect system it is not yet clear what ``func`` should be a shortcut for. Compilation @@ -117,15 +125,16 @@ Change the value of the ``cc`` variable to one of the following: ============== ============================================ Abbreviation C/C++ Compiler ============== ============================================ -``dmc`` Digital Mars C++ ``vcc`` Microsoft's Visual C++ ``gcc`` Gnu C -``tcc`` Tiny C ``llvm_gcc`` LLVM-GCC compiler ``icc`` Intel C++ compiler +``clang`` Clang compiler ``ucc`` Generic UNIX C compiler ============== ============================================ +Other C compilers are not officially supported, but might work too. + If your C compiler is not in the above list, try using the *generic UNIX C compiler* (``ucc``). If the C compiler needs different command line arguments try the ``--passc`` and ``--passl`` switches. From 5b326269c3eb5d268c81152155acfa4e53274cd9 Mon Sep 17 00:00:00 2001 From: Charlie Barto Date: Tue, 19 Aug 2014 18:30:12 -0400 Subject: [PATCH 175/234] fixed #1491 --- lib/system/arithm.nim | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/lib/system/arithm.nim b/lib/system/arithm.nim index bb15360fdb..7672947cdf 100644 --- a/lib/system/arithm.nim +++ b/lib/system/arithm.nim @@ -114,63 +114,69 @@ when asmVersion and not defined(gcc) and not defined(llvm_gcc): proc addInt(a, b: int): int {.compilerProc, asmNoStackFrame.} = # a in eax, and b in edx asm """ - mov eax, `a` - add eax, `b` + mov eax, ecx + add eax, edx jno theEnd call `raiseOverflow` theEnd: + ret """ proc subInt(a, b: int): int {.compilerProc, asmNoStackFrame.} = asm """ - mov eax, `a` - sub eax, `b` + mov eax, ecx + sub eax, edx jno theEnd call `raiseOverflow` theEnd: + ret """ proc negInt(a: int): int {.compilerProc, asmNoStackFrame.} = asm """ - mov eax, `a` + mov eax, ecx neg eax jno theEnd call `raiseOverflow` theEnd: + ret """ proc divInt(a, b: int): int {.compilerProc, asmNoStackFrame.} = asm """ - mov eax, `a` - mov ecx, `b` + mov eax, ecx + mov ecx, edx xor edx, edx idiv ecx jno theEnd call `raiseOverflow` theEnd: + ret """ proc modInt(a, b: int): int {.compilerProc, asmNoStackFrame.} = asm """ - mov eax, `a` - mov ecx, `b` + mov eax, ecx + mov ecx, edx xor edx, edx idiv ecx jno theEnd call `raiseOverflow` theEnd: mov eax, edx + ret """ proc mulInt(a, b: int): int {.compilerProc, asmNoStackFrame.} = asm """ - mov eax, `a` - mov ecx, `b` + mov eax, ecx + mov ecx, edx xor edx, edx imul ecx jno theEnd call `raiseOverflow` theEnd: + ret """ elif false: # asmVersion and (defined(gcc) or defined(llvm_gcc)): From bc2e83fe170bdd01b2f251405702f69366a63107 Mon Sep 17 00:00:00 2001 From: Araq Date: Wed, 20 Aug 2014 01:11:47 +0200 Subject: [PATCH 176/234] documented the JS codegen --- compiler/jsgen.nim | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim index 72fe4ecc59..dfe498e472 100644 --- a/compiler/jsgen.nim +++ b/compiler/jsgen.nim @@ -10,6 +10,25 @@ # This is the JavaScript code generator. # Soon also a Luajit code generator. ;-) +discard """ +The JS code generator contains only 2 tricks: + +Trick 1 +------- +Some locations (for example 'var int') require "fat pointers" (``etyBaseIndex``) +which are pairs (array, index). The derefence operation is then 'array[index]'. +Check ``mapType`` for the details. + +Trick 2 +------- +It is preferable to generate '||' and '&&' if possible since that is more +idiomatic and hence should be friendlier for the JS JIT implementation. However +code like ``foo and (let bar = baz())`` cannot be translated this way. Instead +the expressions need to be transformed into statements. ``isSimpleExpr`` +implements the required case distinction. +""" + + import ast, astalgo, strutils, hashes, trees, platform, magicsys, extccomp, options, nversion, nimsets, msgs, crc, bitsets, idents, lists, types, os, From 15b2d6d351ab96eb2f84e466d1cebd04f70448c8 Mon Sep 17 00:00:00 2001 From: Araq Date: Wed, 20 Aug 2014 02:14:30 +0200 Subject: [PATCH 177/234] fixes #1418 --- compiler/transf.nim | 73 ++++++++++++++++++++++-------------- tests/controlflow/tbreak.nim | 33 ++++++++++++++++ 2 files changed, 77 insertions(+), 29 deletions(-) create mode 100644 tests/controlflow/tbreak.nim diff --git a/compiler/transf.nim b/compiler/transf.nim index dece1ac18f..2b36f01c5c 100644 --- a/compiler/transf.nim +++ b/compiler/transf.nim @@ -1,7 +1,7 @@ # # # The Nimrod Compiler -# (c) Copyright 2013 Andreas Rumpf +# (c) Copyright 2014 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. @@ -13,7 +13,7 @@ # * inlines iterators # * inlines constants # * performes constant folding -# * converts "continue" to "break" +# * converts "continue" to "break"; disambiguates "break" # * introduces method dispatchers # * performs lambda lifting for closure support @@ -44,7 +44,6 @@ type inlining: int # > 0 if we are in inlining context (copy vars) nestedProcs: int # > 0 if we are in a nested proc contSyms, breakSyms: seq[PSym] # to transform 'continue' and 'break' - inLoop: int # > 0 if we are in a loop PTransf = ref TTransfContext proc newTransNode(a: PNode): PTransNode {.inline.} = @@ -213,14 +212,6 @@ proc transformBlock(c: PTransf, n: PNode): PTransNode = discard c.breakSyms.pop result[0] = newSymNode(labl).PTransNode -proc transformBreak(c: PTransf, n: PNode): PTransNode = - if c.inLoop > 0 or n.sons[0].kind != nkEmpty: - result = n.PTransNode - else: - let labl = c.breakSyms[c.breakSyms.high] - result = transformSons(c, n) - result[0] = newSymNode(labl).PTransNode - proc transformLoopBody(c: PTransf, n: PNode): PTransNode = # What if it contains "continue" and "break"? "break" needs # an explicit label too, but not the same! @@ -239,6 +230,27 @@ proc transformLoopBody(c: PTransf, n: PNode): PTransNode = else: result = transform(c, n) +proc transformWhile(c: PTransf; n: PNode): PTransNode = + let labl = newLabel(c, n) + c.breakSyms.add(labl) + result = newTransNode(nkBlockStmt, n.info, 2) + result[0] = newSymNode(labl).PTransNode + + var body = newTransNode(n) + for i in 0..n.len-2: + body[i] = transform(c, n.sons[i]) + body[ Date: Wed, 20 Aug 2014 21:16:06 +0200 Subject: [PATCH 178/234] added bug number to comment --- compiler/types.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/types.nim b/compiler/types.nim index 824ca47d09..ec2271deba 100644 --- a/compiler/types.nim +++ b/compiler/types.nim @@ -1390,7 +1390,7 @@ proc skipConv*(n: PNode): PNode = case n.kind of nkObjUpConv, nkObjDownConv, nkChckRange, nkChckRangeF, nkChckRange64: # only skip the conversion if it doesn't lose too important information - # (see bug # + # (see bug #1334) if n.sons[0].typ.classify == n.typ.classify: result = n.sons[0] of nkHiddenStdConv, nkHiddenSubConv, nkConv: From 5432b2b83aebb139324cf44d1ebd4a88a7c85e39 Mon Sep 17 00:00:00 2001 From: Araq Date: Thu, 21 Aug 2014 09:59:57 +0200 Subject: [PATCH 179/234] fixes recently introduced regression --- compiler/transf.nim | 57 +++++++++++++++++++++++++++--------- tests/controlflow/tbreak.nim | 13 +++++++- 2 files changed, 55 insertions(+), 15 deletions(-) diff --git a/compiler/transf.nim b/compiler/transf.nim index 2b36f01c5c..b9b06675ed 100644 --- a/compiler/transf.nim +++ b/compiler/transf.nim @@ -200,6 +200,18 @@ proc newLabel(c: PTransf, n: PNode): PSym = result = newSym(skLabel, nil, getCurrOwner(c), n.info) result.name = getIdent(genPrefix & $result.id) +proc freshLabels(c: PTransf, n: PNode; symMap: var TIdTable) = + if n.kind in {nkBlockStmt, nkBlockExpr}: + if n.sons[0].kind == nkSym: + let x = newLabel(c, n[0]) + idTablePut(symMap, n[0].sym, x) + n.sons[0].sym = x + if n.kind == nkSym and n.sym.kind == skLabel: + let x = PSym(idTableGet(symMap, n.sym)) + if x != nil: n.sym = x + else: + for i in 0 .. 0: + result = transformSons(c, n) + else: + let labl = newLabel(c, n) + c.breakSyms.add(labl) + result = newTransNode(nkBlockStmt, n.info, 2) + result[0] = newSymNode(labl).PTransNode - var body = newTransNode(n) - for i in 0..n.len-2: - body[i] = transform(c, n.sons[i]) - body[ 0: result = n.PTransNode + when false: + let lablCopy = idNodeTableGet(c.transCon.mapping, n.sons[0].sym) + if lablCopy.isNil: + result = n.PTransNode + else: + result = newTransNode(n.kind, n.info, 1) + result[0] = lablCopy.PTransNode else: let labl = c.breakSyms[c.breakSyms.high] result = transformSons(c, n) @@ -477,9 +499,9 @@ proc transformFor(c: PTransf, n: PNode): PTransNode = var formal = skipTypes(iter.typ, abstractInst).n.sons[i].sym if arg.typ.kind == tyIter: continue case putArgInto(arg, formal.typ) - of paDirectMapping: + of paDirectMapping: idNodeTablePut(newC.mapping, formal, arg) - of paFastAsgn: + of paFastAsgn: # generate a temporary and produce an assignment statement: var temp = newTemp(c, formal.typ, formal.info) addVar(v, newSymNode(temp)) @@ -489,8 +511,13 @@ proc transformFor(c: PTransf, n: PNode): PTransNode = assert(skipTypes(formal.typ, abstractInst).kind == tyVar) idNodeTablePut(newC.mapping, formal, arg) # XXX BUG still not correct if the arg has a side effect! - var body = iter.getBody + var body = iter.getBody.copyTree pushInfoContext(n.info) + # XXX optimize this somehow. But the check "c.inlining" is not correct: + var symMap: TIdTable + initIdTable symMap + freshLabels(c, body, symMap) + inc(c.inlining) add(stmtList, transform(c, body)) #findWrongOwners(c, stmtList.pnode) @@ -755,6 +782,8 @@ proc transformBody*(module: PSym, n: PNode, prc: PSym): PNode = # result = lambdalifting.liftIterator(prc, result) incl(result.flags, nfTransf) when useEffectSystem: trackProc(prc, result) + if prc.name.s == "testbody": + echo renderTree(result) proc transformStmt*(module: PSym, n: PNode): PNode = if nfTransf in n.flags: diff --git a/tests/controlflow/tbreak.nim b/tests/controlflow/tbreak.nim index 3d6bb25f03..7deab4cafc 100644 --- a/tests/controlflow/tbreak.nim +++ b/tests/controlflow/tbreak.nim @@ -1,5 +1,9 @@ discard """ - output: '''10''' + output: '''10 +true true +true false +false true +false false''' """ var @@ -31,3 +35,10 @@ iterator permutations: int = for p in permutations(): break +# regression: +proc main = + for x in [true, false]: + for y in [true, false]: + echo x, " ", y + +main() From 2dff5ef7181a561e4921fe96511ba07414a8afc6 Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Thu, 21 Aug 2014 20:36:27 +0100 Subject: [PATCH 180/234] Fixed gcsafe in asynchttpserver module. --- lib/pure/asynchttpserver.nim | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/pure/asynchttpserver.nim b/lib/pure/asynchttpserver.nim index 26e3a2a7b8..c8bd5cfc13 100644 --- a/lib/pure/asynchttpserver.nim +++ b/lib/pure/asynchttpserver.nim @@ -97,7 +97,8 @@ proc sendStatus(client: PAsyncSocket, status: string): PFuture[void] = client.send("HTTP/1.1 " & status & "\c\L") proc processClient(client: PAsyncSocket, address: string, - callback: proc (request: TRequest): PFuture[void]) {.async.} = + callback: proc (request: TRequest): + PFuture[void] {.closure, gcsafe.}) {.async.} = while true: # GET /path HTTP/1.1 # Header: val @@ -184,7 +185,7 @@ proc processClient(client: PAsyncSocket, address: string, break proc serve*(server: PAsyncHttpServer, port: TPort, - callback: proc (request: TRequest): PFuture[void] {.gcsafe.}, + callback: proc (request: TRequest): PFuture[void] {.closure,gcsafe.}, address = "") {.async.} = ## Starts the process of listening for incoming HTTP connections on the ## specified address and port. From 2525215610c55f97aded12658b5318eea752975f Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Sun, 24 Aug 2014 00:37:27 +0100 Subject: [PATCH 181/234] Ftpclient module now uses generics. --- lib/pure/ftpclient.nim | 182 ++++++++++++++++++++--------------------- 1 file changed, 89 insertions(+), 93 deletions(-) diff --git a/lib/pure/ftpclient.nim b/lib/pure/ftpclient.nim index d4922d1abe..8bbbd01fb2 100644 --- a/lib/pure/ftpclient.nim +++ b/lib/pure/ftpclient.nim @@ -34,15 +34,11 @@ import sockets, strutils, parseutils, times, os, asyncio type - TFTPClient* = object of TObject - case isAsync: bool - of false: - csock: TSocket # Command connection socket - dsock: TSocket # Data connection socket - else: - dummyA, dummyB: pointer # workaround a Nimrod API issue - asyncCSock: PAsyncSocket - asyncDSock: PAsyncSocket + PFtpBase*[SockType] = ref TFtpBase[SockType] + TFtpBase*[SockType] = object + csock: SockType + dsock: SockType + when SockType is PAsyncSocket: handleEvent*: proc (ftp: PAsyncFTPClient, ev: TFTPEvent){.closure,gcsafe.} disp: PDispatcher asyncDSockID: PDelegate @@ -51,17 +47,16 @@ type port: TPort jobInProgress: bool - job: ref TFTPJob + job: PFTPJob[SockType] dsockConnected: bool - PFTPClient* = ref TFTPClient - FTPJobType* = enum JRetrText, JRetr, JStore - TFTPJob = object - prc: proc (ftp: PFTPClient, async: bool): bool {.nimcall, gcsafe.} + PFtpJob[T] = ref TFtpJob[T] + TFTPJob[T] = object + prc: proc (ftp: PFTPBase[T], async: bool): bool {.nimcall, gcsafe.} case typ*: FTPJobType of JRetrText: lines: string @@ -75,8 +70,11 @@ type toStore: string # Data left to upload (Only used with async) else: nil + TFtpClient* = TFtpBase[TSocket] + PFtpClient* = ref TFTPClient + PAsyncFTPClient* = ref TAsyncFTPClient ## Async alternative to TFTPClient. - TAsyncFTPClient* = object of TFTPClient + TAsyncFTPClient* = TFtpBase[PAsyncSocket] FTPEventType* = enum EvTransferProgress, EvLines, EvRetr, EvStore @@ -106,30 +104,30 @@ proc ftpClient*(address: string, port = TPort(21), result.address = address result.port = port - result.isAsync = false result.dsockConnected = false result.csock = socket() if result.csock == InvalidSocket: osError(osLastError()) -proc getDSock(ftp: PFTPClient): TSocket = - if ftp.isAsync: return ftp.asyncDSock else: return ftp.dsock +proc getDSock[T](ftp: PFTPBase[T]): TSocket = + return ftp.dsock -proc getCSock(ftp: PFTPClient): TSocket = - if ftp.isAsync: return ftp.asyncCSock else: return ftp.csock +proc getCSock[T](ftp: PFTPBase[T]): TSocket = + return ftp.csock template blockingOperation(sock: TSocket, body: stmt) {.immediate.} = - if ftp.isAsync: - sock.setBlocking(true) body - if ftp.isAsync: - sock.setBlocking(false) -proc expectReply(ftp: PFTPClient): TaintedString = +template blockingOperation(sock: PAsyncSocket, body: stmt) {.immediate.} = + sock.setBlocking(true) + body + sock.setBlocking(false) + +proc expectReply[T](ftp: PFtpBase[T]): TaintedString = result = TaintedString"" blockingOperation(ftp.getCSock()): ftp.getCSock().readLine(result) -proc send*(ftp: PFTPClient, m: string): TaintedString = +proc send*[T](ftp: PFtpBase[T], m: string): TaintedString = ## Send a message to the server, and wait for a primary reply. ## ``\c\L`` is added for you. blockingOperation(ftp.getCSock()): @@ -149,8 +147,8 @@ proc assertReply(received: TaintedString, expected: varargs[string]) = "Expected reply '$1' got: $2" % [expected.join("' or '"), received.string]) -proc createJob(ftp: PFTPClient, - prc: proc (ftp: PFTPClient, async: bool): bool {. +proc createJob[T](ftp: PFtpBase[T], + prc: proc (ftp: PFtpBase[T], async: bool): bool {. nimcall,gcsafe.}, cmd: FTPJobType) = if ftp.jobInProgress: @@ -165,7 +163,7 @@ proc createJob(ftp: PFTPClient, of JRetr, JStore: ftp.job.toStore = "" -proc deleteJob(ftp: PFTPClient) = +proc deleteJob[T](ftp: PFtpBase[T]) = assert ftp.jobInProgress ftp.jobInProgress = false case ftp.job.typ @@ -173,12 +171,9 @@ proc deleteJob(ftp: PFTPClient) = ftp.job.lines = "" of JRetr, JStore: ftp.job.file.close() - if ftp.isAsync: - ftp.asyncDSock.close() - else: - ftp.dsock.close() + ftp.dsock.close() -proc handleTask(s: PAsyncSocket, ftp: PFTPClient) = +proc handleTask(s: PAsyncSocket, ftp: PAsyncFTPClient) = if ftp.jobInProgress: if ftp.job.typ in {JRetr, JStore}: if epochTime() - ftp.job.lastProgressReport >= 1.0: @@ -193,12 +188,12 @@ proc handleTask(s: PAsyncSocket, ftp: PFTPClient) = ftp.job.oneSecond = 0 ftp.handleEvent(PAsyncFTPClient(ftp), r) -proc handleWrite(s: PAsyncSocket, ftp: PFTPClient) = +proc handleWrite(s: PAsyncSocket, ftp: PAsyncFTPClient) = if ftp.jobInProgress: if ftp.job.typ == JStore: assert (not ftp.job.prc(ftp, true)) -proc handleConnect(s: PAsyncSocket, ftp: PFTPClient) = +proc handleConnect(s: PAsyncSocket, ftp: PAsyncFTPClient) = ftp.dsockConnected = true assert(ftp.jobInProgress) if ftp.job.typ == JStore: @@ -206,30 +201,32 @@ proc handleConnect(s: PAsyncSocket, ftp: PFTPClient) = else: s.delHandleWrite() -proc handleRead(s: PAsyncSocket, ftp: PFTPClient) = +proc handleRead(s: PAsyncSocket, ftp: PAsyncFTPClient) = assert ftp.jobInProgress assert ftp.job.typ != JStore # This can never return true, because it shouldn't check for code # 226 from csock. assert(not ftp.job.prc(ftp, true)) -proc pasv(ftp: PFTPClient) = +proc pasv[T](ftp: PFtpBase[T]) = ## Negotiate a data connection. - if not ftp.isAsync: + when T is TSocket: ftp.dsock = socket() if ftp.dsock == InvalidSocket: osError(osLastError()) - else: - ftp.asyncDSock = AsyncSocket() - ftp.asyncDSock.handleRead = + elif T is PAsyncSocket: + ftp.dsock = AsyncSocket() + ftp.dsock.handleRead = proc (s: PAsyncSocket) = handleRead(s, ftp) - ftp.asyncDSock.handleConnect = + ftp.dsock.handleConnect = proc (s: PAsyncSocket) = handleConnect(s, ftp) - ftp.asyncDSock.handleTask = + ftp.dsock.handleTask = proc (s: PAsyncSocket) = handleTask(s, ftp) - ftp.disp.register(ftp.asyncDSock) + ftp.disp.register(ftp.dsock) + else: + {.fatal: "Incorrect socket instantiation".} var pasvMsg = ftp.send("PASV").string.strip.TaintedString assertReply(pasvMsg, "227") @@ -238,23 +235,24 @@ proc pasv(ftp: PFTPClient) = var ip = nums[0.. -3] var port = nums[-2.. -1] var properPort = port[0].parseInt()*256+port[1].parseInt() - if ftp.isAsync: - ftp.asyncDSock.connect(ip.join("."), TPort(properPort.toU16)) + ftp.dsock.connect(ip.join("."), TPort(properPort.toU16)) + when T is PAsyncSocket: ftp.dsockConnected = False else: - ftp.dsock.connect(ip.join("."), TPort(properPort.toU16)) ftp.dsockConnected = True proc normalizePathSep(path: string): string = return replace(path, '\\', '/') -proc connect*(ftp: PFTPClient) = +proc connect*[T](ftp: PFtpBase[T]) = ## Connect to the FTP server specified by ``ftp``. - if ftp.isAsync: - blockingOperation(ftp.asyncCSock): - ftp.asyncCSock.connect(ftp.address, ftp.port) - else: + when T is PAsyncSocket: + blockingOperation(ftp.csock): + ftp.csock.connect(ftp.address, ftp.port) + elif T is TSocket: ftp.csock.connect(ftp.address, ftp.port) + else: + {.fatal: "Incorrect socket instantiation".} # TODO: Handle 120? or let user handle it. assertReply ftp.expectReply(), "220" @@ -279,25 +277,27 @@ proc cdup*(ftp: PFTPClient) = ## Changes the current directory to the parent of the current directory. assertReply ftp.send("CDUP"), "200" -proc getLines(ftp: PFTPClient, async: bool = false): bool = +proc getLines[T](ftp: PFtpBase[T], async: bool = false): bool = ## Downloads text data in ASCII mode ## Returns true if the download is complete. ## It doesn't if `async` is true, because it doesn't check for 226 then. if ftp.dsockConnected: var r = TaintedString"" - if ftp.isAsync: + when T is PAsyncSocket: if ftp.asyncDSock.readLine(r): if r.string == "": ftp.dsockConnected = false else: ftp.job.lines.add(r.string & "\n") - else: + elif T is TSocket: assert(not async) ftp.dsock.readLine(r) if r.string == "": ftp.dsockConnected = false else: ftp.job.lines.add(r.string & "\n") + else: + {.fatal: "Incorrect socket instantiation".} if not async: var readSocks: seq[TSocket] = @[ftp.getCSock()] @@ -307,14 +307,14 @@ proc getLines(ftp: PFTPClient, async: bool = false): bool = assertReply ftp.expectReply(), "226" return true -proc listDirs*(ftp: PFTPClient, dir: string = "", +proc listDirs*[T](ftp: PFtpBase[T], dir: string = "", async = false): seq[string] = ## Returns a list of filenames in the given directory. If ``dir`` is "", ## the current directory is used. If ``async`` is true, this ## function will return immediately and it will be your job to ## use asyncio's ``poll`` to progress this operation. - ftp.createJob(getLines, JRetrText) + ftp.createJob(getLines[T], JRetrText) ftp.pasv() assertReply ftp.send("NLST " & dir.normalizePathSep), ["125", "150"] @@ -384,12 +384,12 @@ proc chmod*(ftp: PFTPClient, path: string, assertReply ftp.send("SITE CHMOD " & perm & " " & path.normalizePathSep), "200" -proc list*(ftp: PFTPClient, dir: string = "", async = false): string = +proc list*[T](ftp: PFtpBase[T], dir: string = "", async = false): string = ## Lists all files in ``dir``. If ``dir`` is ``""``, uses the current ## working directory. If ``async`` is true, this function will return ## immediately and it will be your job to call asyncio's ## ``poll`` to progress this operation. - ftp.createJob(getLines, JRetrText) + ftp.createJob(getLines[T], JRetrText) ftp.pasv() assertReply(ftp.send("LIST" & " " & dir.normalizePathSep), ["125", "150"]) @@ -401,11 +401,11 @@ proc list*(ftp: PFTPClient, dir: string = "", async = false): string = else: return "" -proc retrText*(ftp: PFTPClient, file: string, async = false): string = +proc retrText*[T](ftp: PFtpBase[T], file: string, async = false): string = ## Retrieves ``file``. File must be ASCII text. ## If ``async`` is true, this function will return immediately and ## it will be your job to call asyncio's ``poll`` to progress this operation. - ftp.createJob(getLines, JRetrText) + ftp.createJob(getLines[T], JRetrText) ftp.pasv() assertReply ftp.send("RETR " & file.normalizePathSep), ["125", "150"] @@ -416,15 +416,17 @@ proc retrText*(ftp: PFTPClient, file: string, async = false): string = else: return "" -proc getFile(ftp: PFTPClient, async = false): bool = +proc getFile[T](ftp: PFtpBase[T], async = false): bool = if ftp.dsockConnected: var r = "".TaintedString var bytesRead = 0 var returned = false if async: - if not ftp.isAsync: raise newException(EFTP, "FTPClient must be async.") - bytesRead = ftp.AsyncDSock.recvAsync(r, BufferSize) - returned = bytesRead != -1 + when T is TSocket: + raise newException(EFTP, "FTPClient must be async.") + else: + bytesRead = ftp.dsock.recvAsync(r, BufferSize) + returned = bytesRead != -1 else: bytesRead = getDSock(ftp).recv(r, BufferSize) returned = true @@ -443,13 +445,13 @@ proc getFile(ftp: PFTPClient, async = false): bool = assertReply ftp.expectReply(), "226" return true -proc retrFile*(ftp: PFTPClient, file, dest: string, async = false) = +proc retrFile*[T](ftp: PFtpBase[T], file, dest: string, async = false) = ## Downloads ``file`` and saves it to ``dest``. Usage of this function ## asynchronously is recommended to view the progress of the download. ## The ``EvRetr`` event is passed to the specified ``handleEvent`` function ## when the download is finished, and the ``filename`` field will be equal ## to ``file``. - ftp.createJob(getFile, JRetr) + ftp.createJob(getFile[T], JRetr) ftp.job.file = open(dest, mode = fmWrite) ftp.pasv() var reply = ftp.send("RETR " & file.normalizePathSep) @@ -468,11 +470,11 @@ proc retrFile*(ftp: PFTPClient, file, dest: string, async = false) = while not ftp.job.prc(ftp, false): discard ftp.deleteJob() -proc doUpload(ftp: PFTPClient, async = false): bool = +proc doUpload[T](ftp: PFtpBase[T], async = false): bool = if ftp.dsockConnected: if ftp.job.toStore.len() > 0: assert(async) - let bytesSent = ftp.asyncDSock.sendAsync(ftp.job.toStore) + let bytesSent = ftp.dsock.sendAsync(ftp.job.toStore) if bytesSent == ftp.job.toStore.len: ftp.job.toStore = "" elif bytesSent != ftp.job.toStore.len and bytesSent != 0: @@ -485,7 +487,7 @@ proc doUpload(ftp: PFTPClient, async = false): bool = setLen(s, len) if len == 0: # File finished uploading. - if ftp.isAsync: ftp.asyncDSock.close() else: ftp.dsock.close() + ftp.dsock.close() ftp.dsockConnected = false if not async: @@ -496,7 +498,7 @@ proc doUpload(ftp: PFTPClient, async = false): bool = if not async: getDSock(ftp).send(s) else: - let bytesSent = ftp.asyncDSock.sendAsync(s) + let bytesSent = ftp.dsock.sendAsync(s) if bytesSent == 0: ftp.job.toStore.add(s) elif bytesSent != s.len: @@ -506,14 +508,14 @@ proc doUpload(ftp: PFTPClient, async = false): bool = ftp.job.progress.inc(len) ftp.job.oneSecond.inc(len) -proc store*(ftp: PFTPClient, file, dest: string, async = false) = +proc store*[T](ftp: PFtpBase[T], file, dest: string, async = false) = ## Uploads ``file`` to ``dest`` on the remote FTP server. Usage of this ## function asynchronously is recommended to view the progress of ## the download. ## The ``EvStore`` event is passed to the specified ``handleEvent`` function ## when the upload is finished, and the ``filename`` field will be ## equal to ``file``. - ftp.createJob(doUpload, JStore) + ftp.createJob(doUpload[T], JStore) ftp.job.file = open(file) ftp.job.total = ftp.job.file.getFileSize() ftp.job.lastProgressReport = epochTime() @@ -526,16 +528,12 @@ proc store*(ftp: PFTPClient, file, dest: string, async = false) = while not ftp.job.prc(ftp, false): discard ftp.deleteJob() -proc close*(ftp: PFTPClient) = +proc close*[T](ftp: PFTPBase[T]) = ## Terminates the connection to the server. assertReply ftp.send("QUIT"), "221" if ftp.jobInProgress: ftp.deleteJob() - if ftp.isAsync: - ftp.asyncCSock.close() - ftp.asyncDSock.close() - else: - ftp.csock.close() - ftp.dsock.close() + ftp.csock.close() + ftp.dsock.close() proc csockHandleRead(s: PAsyncSocket, ftp: PAsyncFTPClient) = if ftp.jobInProgress: @@ -572,20 +570,18 @@ proc asyncFTPClient*(address: string, port = TPort(21), dres.pass = pass dres.address = address dres.port = port - dres.isAsync = true dres.dsockConnected = false dres.handleEvent = handleEvent - dres.asyncCSock = AsyncSocket() - dres.asyncCSock.handleRead = + dres.csock = AsyncSocket() + dres.csock.handleRead = proc (s: PAsyncSocket) = csockHandleRead(s, dres) result = dres proc register*(d: PDispatcher, ftp: PAsyncFTPClient): PDelegate {.discardable.} = ## Registers ``ftp`` with dispatcher ``d``. - assert ftp.isAsync ftp.disp = d - return ftp.disp.register(ftp.asyncCSock) + return ftp.disp.register(ftp.csock) when isMainModule: proc main = @@ -595,7 +591,7 @@ when isMainModule: case event.typ of EvStore: echo("Upload finished!") - ftp.retrFile("payload.JPG", "payload2.JPG", async = true) + ftp.retrFile("payload.jpg", "payload2.jpg", async = true) of EvTransferProgress: var time: int64 = -1 if event.speed != 0: @@ -610,29 +606,29 @@ when isMainModule: ftp.close() echo d.len else: assert(false) - var ftp = asyncFTPClient("picheta.me", user = "test", pass = "asf", handleEvent = hev) + var ftp = asyncFTPClient("example.com", user = "foo", pass = "bar", handleEvent = hev) d.register(ftp) d.len.echo() ftp.connect() echo "connected" - ftp.store("payload.JPG", "payload.JPG", async = true) + ftp.store("payload.jpg", "payload.jpg", async = true) d.len.echo() echo "uploading..." while true: if not d.poll(): break main() -when isMainModule and false: - var ftp = ftpClient("picheta.me", user = "asdasd", pass = "asfwq") +when not isMainModule: + var ftp = ftpClient("example.com", user = "foo", pass = "bar") ftp.connect() echo ftp.pwd() echo ftp.list() echo("uploading") - ftp.store("payload.JPG", "payload.JPG", async = false) + ftp.store("payload.jpg", "payload.jpg", async = false) echo("Upload complete") - ftp.retrFile("payload.JPG", "payload2.JPG", async = false) + ftp.retrFile("payload.jpg", "payload2.jpg", async = false) echo("Download complete") sleep(5000) From 08f1c6100b307e8a6f5eeb8f6647552c10d4481d Mon Sep 17 00:00:00 2001 From: Erwan Ameil Date: Fri, 29 Aug 2014 11:29:19 +0200 Subject: [PATCH 182/234] Add postgresql prepared queries and stop relying on string formatting for sql parameter passing --- lib/impure/db_postgres.nim | 112 +++++++++++++++++++++++++++---------- lib/wrappers/postgres.nim | 2 + 2 files changed, 86 insertions(+), 28 deletions(-) diff --git a/lib/impure/db_postgres.nim b/lib/impure/db_postgres.nim index f6ae933030..c375d91910 100644 --- a/lib/impure/db_postgres.nim +++ b/lib/impure/db_postgres.nim @@ -19,12 +19,13 @@ type EDb* = object of EIO ## exception that is raised if a database error occurs TSqlQuery* = distinct string ## an SQL query string + TSqlPrepared* = distinct string ## a identifier for the prepared queries FDb* = object of FIO ## effect that denotes a database operation FReadDb* = object of FDB ## effect that denotes a read operation FWriteDb* = object of FDB ## effect that denotes a write operation - -proc sql*(query: string): TSqlQuery {.noSideEffect, inline.} = + +proc sql*(query: string): TSqlQuery {.noSideEffect, inline.} = ## constructs a TSqlQuery from the string `query`. This is supposed to be ## used as a raw-string-literal modifier: ## ``sql"update user set counter = counter + 1"`` @@ -33,14 +34,14 @@ proc sql*(query: string): TSqlQuery {.noSideEffect, inline.} = ## on, later versions will check the string for valid syntax. result = TSqlQuery(query) -proc dbError(db: TDbConn) {.noreturn.} = +proc dbError*(db: TDbConn) {.noreturn.} = ## raises an EDb exception. var e: ref EDb new(e) e.msg = $PQerrorMessage(db) raise e -proc dbError*(msg: string) {.noreturn.} = +proc dbError*(msg: string) {.noreturn.} = ## raises an EDb exception with message `msg`. var e: ref EDb new(e) @@ -61,41 +62,70 @@ proc dbFormat(formatstr: TSqlQuery, args: varargs[string]): string = if c == '?': add(result, dbQuote(args[a])) inc(a) - else: + else: add(result, c) -proc tryExec*(db: TDbConn, query: TSqlQuery, +proc tryExec*(db: TDbConn, query: TSqlQuery, args: varargs[string, `$`]): bool {.tags: [FReadDB, FWriteDb].} = ## tries to execute the query and returns true if successful, false otherwise. - var q = dbFormat(query, args) - var res = PQExec(db, q) + var arr = allocCStringArray(args) + var res = PQexecParams(db, query.string, int32(args.len), nil, arr, + nil, nil, 0) + deallocCStringArray(arr) result = PQresultStatus(res) == PGRES_COMMAND_OK PQclear(res) proc exec*(db: TDbConn, query: TSqlQuery, args: varargs[string, `$`]) {. tags: [FReadDB, FWriteDb].} = ## executes the query and raises EDB if not successful. - var q = dbFormat(query, args) - var res = PQExec(db, q) + var arr = allocCStringArray(args) + var res = PQexecParams(db, query.string, int32(args.len), nil, arr, + nil, nil, 0) + deallocCStringArray(arr) if PQresultStatus(res) != PGRES_COMMAND_OK: dbError(db) PQclear(res) - + +proc exec*(db: TDbConn, stmtName: TSqlPrepared, + args: varargs[string]) {.tags: [FReadDB, FWriteDb].} = + var arr = allocCStringArray(args) + var res = PQexecPrepared(db, stmtName.string, int32(args.len), arr, + nil, nil, 0) + deallocCStringArray(arr) + if PQResultStatus(res) != PGRES_COMMAND_OK: dbError(db) + PQclear(res) + proc newRow(L: int): TRow = newSeq(result, L) for i in 0..L-1: result[i] = "" -proc setupQuery(db: TDbConn, query: TSqlQuery, - args: varargs[string]): PPGresult = - var q = dbFormat(query, args) - result = PQExec(db, q) - if PQresultStatus(result) != PGRES_TUPLES_OK: dbError(db) - +proc setupQuery(db: TDbConn, query: TSqlQuery, + args: varargs[string]): PPGresult = + var arr = allocCStringArray(args) + result = PQexecParams(db, query.string, int32(args.len), nil, arr, + nil, nil, 0) + deallocCStringArray(arr) + if PQResultStatus(result) != PGRES_TUPLES_OK: dbError(db) + +proc setupQuery(db: TDbConn, stmtName: TSqlPrepared, + args: varargs[string]): PPGresult = + var arr = allocCStringArray(args) + result = PQexecPrepared(db, stmtName.string, int32(args.len), arr, + nil, nil, 0) + deallocCStringArray(arr) + if PQResultStatus(result) != PGRES_TUPLES_OK: dbError(db) + +proc prepare*(db: TDbConn; stmtName: string, query: TSqlQuery; + nParams: int): TSqlPrepared = + var res = PQprepare(db, stmtName, query.string, int32(nParams), nil) + if PQResultStatus(res) != PGRES_COMMAND_OK: dbError(db) + return TSqlPrepared(stmtName) + proc setRow(res: PPGresult, r: var TRow, line, cols: int32) = for col in 0..cols-1: setLen(r[col], 0) var x = PQgetvalue(res, line, col) add(r[col], x) - + iterator fastRows*(db: TDbConn, query: TSqlQuery, args: varargs[string, `$`]): TRow {.tags: [FReadDB].} = ## executes the query and iterates over the result dataset. This is very @@ -109,6 +139,17 @@ iterator fastRows*(db: TDbConn, query: TSqlQuery, yield result PQclear(res) +iterator fastRows*(db: TDbConn, stmtName: TSqlPrepared, + args: varargs[string, `$`]): TRow {.tags: [FReadDB].} = + ## executes the prepared query and iterates over the result dataset. + var res = setupQuery(db, stmtName, args) + var L = PQnfields(res) + var result = newRow(L) + for i in 0..PQntuples(res)-1: + setRow(res, result, i, L) + yield result + PQclear(res) + proc getRow*(db: TDbConn, query: TSqlQuery, args: varargs[string, `$`]): TRow {.tags: [FReadDB].} = ## retrieves a single row. If the query doesn't return any rows, this proc @@ -119,40 +160,55 @@ proc getRow*(db: TDbConn, query: TSqlQuery, setRow(res, result, 0, L) PQclear(res) -proc getAllRows*(db: TDbConn, query: TSqlQuery, +proc getRow*(db: TDbConn, stmtName: TSqlPrepared, + args: varargs[string, `$`]): TRow {.tags: [FReadDB].} = + var res = setupQuery(db, stmtName, args) + var L = PQnfields(res) + result = newRow(L) + setRow(res, result, 0, L) + PQclear(res) + +proc getAllRows*(db: TDbConn, query: TSqlQuery, args: varargs[string, `$`]): seq[TRow] {.tags: [FReadDB].} = ## executes the query and returns the whole result dataset. result = @[] for r in FastRows(db, query, args): result.add(r) -iterator rows*(db: TDbConn, query: TSqlQuery, +proc getAllRows*(db: TDbConn, stmtName: TSqlPrepared, + args: varargs[string, `$`]): seq[TRow] {.tags: [FReadDB].} = + ## executes the prepared query and returns the whole result dataset. + result = @[] + for r in FastRows(db, stmtName, args): + result.add(r) + +iterator rows*(db: TDbConn, query: TSqlQuery, args: varargs[string, `$`]): TRow {.tags: [FReadDB].} = ## same as `FastRows`, but slower and safe. for r in items(GetAllRows(db, query, args)): yield r -proc getValue*(db: TDbConn, query: TSqlQuery, - args: varargs[string, `$`]): string {.tags: [FReadDB].} = +proc getValue*(db: TDbConn, query: TSqlQuery, + args: varargs[string, `$`]): string {.tags: [FReadDB].} = ## executes the query and returns the first column of the first row of the ## result dataset. Returns "" if the dataset contains no rows or the database ## value is NULL. var x = PQgetvalue(setupQuery(db, query, args), 0, 0) result = if isNil(x): "" else: $x -proc tryInsertID*(db: TDbConn, query: TSqlQuery, +proc tryInsertID*(db: TDbConn, query: TSqlQuery, args: varargs[string, `$`]): int64 {.tags: [FWriteDb].}= ## executes the query (typically "INSERT") and returns the ## generated ID for the row or -1 in case of an error. For Postgre this adds ## ``RETURNING id`` to the query, so it only works if your primary key is ## named ``id``. - var x = PQgetvalue(setupQuery(db, TSqlQuery(string(query) & " RETURNING id"), + var x = PQgetvalue(setupQuery(db, TSqlQuery(string(query) & " RETURNING id"), args), 0, 0) if not isNil(x): result = ParseBiggestInt($x) else: result = -1 -proc insertID*(db: TDbConn, query: TSqlQuery, +proc insertID*(db: TDbConn, query: TSqlQuery, args: varargs[string, `$`]): int64 {.tags: [FWriteDb].} = ## executes the query (typically "INSERT") and returns the ## generated ID for the row. For Postgre this adds @@ -161,9 +217,9 @@ proc insertID*(db: TDbConn, query: TSqlQuery, result = TryInsertID(db, query, args) if result < 0: dbError(db) -proc execAffectedRows*(db: TDbConn, query: TSqlQuery, +proc execAffectedRows*(db: TDbConn, query: TSqlQuery, args: varargs[string, `$`]): int64 {.tags: [ - FReadDB, FWriteDb].} = + FReadDB, FWriteDb].} = ## executes the query (typically "UPDATE") and returns the ## number of affected rows. var q = dbFormat(query, args) @@ -172,7 +228,7 @@ proc execAffectedRows*(db: TDbConn, query: TSqlQuery, result = parseBiggestInt($PQcmdTuples(res)) PQclear(res) -proc close*(db: TDbConn) {.tags: [FDb].} = +proc close*(db: TDbConn) {.tags: [FDb].} = ## closes the database connection. if db != nil: PQfinish(db) diff --git a/lib/wrappers/postgres.nim b/lib/wrappers/postgres.nim index d99e5651c5..ce78d34352 100644 --- a/lib/wrappers/postgres.nim +++ b/lib/wrappers/postgres.nim @@ -213,6 +213,8 @@ proc PQexecParams*(conn: PPGconn, command: cstring, nParams: int32, paramTypes: POid, paramValues: cstringArray, paramLengths, paramFormats: ptr int32, resultFormat: int32): PPGresult{. cdecl, dynlib: dllName, importc: "PQexecParams".} +proc PQprepare*(conn: PPGconn, stmtName, query: cstring, nParams: int32, + paramTypes: POid): PPGresult{.cdecl, dynlib: dllName, importc: "PQprepare".} proc PQexecPrepared*(conn: PPGconn, stmtName: cstring, nParams: int32, paramValues: cstringArray, paramLengths, paramFormats: ptr int32, resultFormat: int32): PPGresult{. From 85107917f06e8fd159923aca2fbf1eaf2c750456 Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Fri, 29 Aug 2014 22:41:52 +0100 Subject: [PATCH 183/234] Async macro fixes. Added waitFor. --- lib/pure/asyncdispatch.nim | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/lib/pure/asyncdispatch.nim b/lib/pure/asyncdispatch.nim index 5dfcf4656d..0ea8ef43b2 100644 --- a/lib/pure/asyncdispatch.nim +++ b/lib/pure/asyncdispatch.nim @@ -32,6 +32,7 @@ export TPort, TSocketFlags # TODO: The effect system (raises: []) has trouble with my try transformation. # TODO: Can't await in a 'except' body # TODO: getCurrentException(Msg) don't work +# TODO: Check if yielded future is nil and throw a more meaningful exception # -- Futures @@ -183,7 +184,7 @@ proc asyncCheck*[T](future: PFuture[T]) = proc `and`*[T, Y](fut1: PFuture[T], fut2: PFuture[Y]): PFuture[void] = ## Returns a future which will complete once both ``fut1`` and ``fut2`` ## complete. - var retFuture = newFuture[void]() + var retFuture = newFuture[void]("asyncdispatch.`and`") fut1.callback = proc () = if fut2.finished: retFuture.complete() @@ -195,11 +196,12 @@ proc `and`*[T, Y](fut1: PFuture[T], fut2: PFuture[Y]): PFuture[void] = proc `or`*[T, Y](fut1: PFuture[T], fut2: PFuture[Y]): PFuture[void] = ## Returns a future which will complete once either ``fut1`` or ``fut2`` ## complete. - var retFuture = newFuture[void]() + var retFuture = newFuture[void]("asyncdispatch.`or`") proc cb() = if not retFuture.finished: retFuture.complete() fut1.callback = cb fut2.callback = cb + return retFuture type PDispatcherBase = ref object of PObject @@ -1017,10 +1019,10 @@ proc processBody(node, retFutureSym: PNimrodNode, result.add newNimNode(nnkReturnStmt, node).add(newNilLit()) return # Don't process the children of this return stmt - of nnkCommand: + of nnkCommand, nnkCall: if node[0].kind == nnkIdent and node[0].ident == !"await": case node[1].kind - of nnkIdent: + of nnkIdent, nnkInfix: # await x result = newNimNode(nnkYieldStmt, node).add(node[1]) # -> yield x of nnkCall, nnkCommand: @@ -1030,8 +1032,8 @@ proc processBody(node, retFutureSym: PNimrodNode, futureValue, node) else: error("Invalid node kind in 'await', got: " & $node[1].kind) - elif node[1].kind == nnkCommand and node[1][0].kind == nnkIdent and - node[1][0].ident == !"await": + elif node.len > 1 and node[1].kind == nnkCommand and + node[1][0].kind == nnkIdent and node[1][0].ident == !"await": # foo await x var newCommand = node result.createVar("future" & $node[0].toStrLit, node[1][1], newCommand[1], @@ -1182,7 +1184,7 @@ macro async*(prc: stmt): stmt {.immediate.} = result[6] = outerProcBody #echo(treeRepr(result)) - #if prc[0].getName == "processClient": + #if prc[0].getName == "getFile": # echo(toStrLit(result)) proc recvLine*(socket: TAsyncFD): PFuture[string] {.async.} = @@ -1224,3 +1226,11 @@ proc runForever*() = ## Begins a never ending global dispatcher poll loop. while true: poll() + +proc waitFor*[T](fut: PFuture[T]) = + ## **Blocks** the current thread until the specified future completes. + while not fut.finished: + poll() + + if fut.failed: + raise fut.error From 3a00692ef88fd7c15c201e52cc376b373ee5d9a0 Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Fri, 29 Aug 2014 22:44:05 +0100 Subject: [PATCH 184/234] Add asyncftpclient module. --- lib/pure/asyncftpclient.nim | 295 ++++++++++++++++++++++++++++++++++++ lib/pure/ftpclient.nim | 31 ++-- lib/pure/httpclient.nim | 3 +- 3 files changed, 315 insertions(+), 14 deletions(-) create mode 100644 lib/pure/asyncftpclient.nim diff --git a/lib/pure/asyncftpclient.nim b/lib/pure/asyncftpclient.nim new file mode 100644 index 0000000000..f1b1d14006 --- /dev/null +++ b/lib/pure/asyncftpclient.nim @@ -0,0 +1,295 @@ +# +# +# Nimrod's Runtime Library +# (c) Copyright 2014 Dominik Picheta +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# + +import asyncdispatch, asyncnet, strutils, parseutils, os, times + +from ftpclient import TFtpBase, EInvalidReply, TFtpEvent +from net import bufferSize + +type + TAsyncFtpClient* = TFtpBase[PAsyncSocket] + PAsyncFtpClient* = ref TAsyncFtpClient + + ProgressChangedProc* = + proc (total, progress: BiggestInt, speed: float): + PFuture[void] {.closure, gcsafe.} + +proc expectReply(ftp: PAsyncFtpClient): PFuture[TaintedString] = + result = ftp.csock.recvLine() + +proc send*(ftp: PAsyncFtpClient, m: string): PFuture[TaintedString] {.async.} = + ## Send a message to the server, and wait for a primary reply. + ## ``\c\L`` is added for you. + await ftp.csock.send(m & "\c\L") + return await ftp.expectReply() + +proc assertReply(received: TaintedString, expected: varargs[string]) = + for i in items(expected): + if received.string.startsWith(i): return + raise newException(EInvalidReply, + "Expected reply '$1' got: $2" % + [expected.join("' or '"), received.string]) + +proc pasv(ftp: PAsyncFtpClient) {.async.} = + ## Negotiate a data connection. + ftp.dsock = newAsyncSocket() + + var pasvMsg = (await ftp.send("PASV")).string.strip.TaintedString + assertReply(pasvMsg, "227") + var betweenParens = captureBetween(pasvMsg.string, '(', ')') + var nums = betweenParens.split(',') + var ip = nums[0.. -3] + var port = nums[-2.. -1] + var properPort = port[0].parseInt()*256+port[1].parseInt() + await ftp.dsock.connect(ip.join("."), TPort(properPort.toU16)) + ftp.dsockConnected = True + +proc normalizePathSep(path: string): string = + return replace(path, '\\', '/') + +proc connect*(ftp: PAsyncFtpClient) {.async.} = + ## Connect to the FTP server specified by ``ftp``. + await ftp.csock.connect(ftp.address, ftp.port) + + var reply = await ftp.expectReply() + if reply.startsWith("120"): + # 120 Service ready in nnn minutes. + # We wait until we receive 220. + reply = await ftp.expectReply() + assertReply(reply, "220") + + if ftp.user != "": + assertReply(await(ftp.send("USER " & ftp.user)), "230", "331") + + if ftp.pass != "": + assertReply(await(ftp.send("PASS " & ftp.pass)), "230") + +proc pwd*(ftp: PAsyncFtpClient): PFuture[TaintedString] {.async.} = + ## Returns the current working directory. + let wd = await ftp.send("PWD") + assertReply wd, "257" + return wd.string.captureBetween('"').TaintedString # " + +proc cd*(ftp: PAsyncFtpClient, dir: string) {.async.} = + ## Changes the current directory on the remote FTP server to ``dir``. + assertReply(await(ftp.send("CWD " & dir.normalizePathSep)), "250") + +proc cdup*(ftp: PAsyncFtpClient) {.async.} = + ## Changes the current directory to the parent of the current directory. + assertReply(await(ftp.send("CDUP")), "200") + +proc getLines(ftp: PAsyncFtpClient): PFuture[string] {.async.} = + ## Downloads text data in ASCII mode + result = "" + assert ftp.dsockConnected + while ftp.dsockConnected: + let r = await ftp.dsock.recvLine() + if r.string == "": + ftp.dsockConnected = false + else: + result.add(r.string & "\n") + + assertReply(await(ftp.expectReply()), "226") + +proc listDirs*(ftp: PAsyncFtpClient, dir = ""): PFuture[seq[string]] {.async.} = + ## Returns a list of filenames in the given directory. If ``dir`` is "", + ## the current directory is used. If ``async`` is true, this + ## function will return immediately and it will be your job to + ## use asyncio's ``poll`` to progress this operation. + await ftp.pasv() + + assertReply(await(ftp.send("NLST " & dir.normalizePathSep)), ["125", "150"]) + + result = splitLines(await ftp.getLines()) + +proc existsFile*(ftp: PAsyncFtpClient, file: string): PFuture[bool] {.async.} = + ## Determines whether ``file`` exists. + var files = await ftp.listDirs() + for f in items(files): + if f.normalizePathSep == file.normalizePathSep: return true + +proc createDir*(ftp: PAsyncFtpClient, dir: string, recursive = false){.async.} = + ## Creates a directory ``dir``. If ``recursive`` is true, the topmost + ## subdirectory of ``dir`` will be created first, following the secondmost... + ## etc. this allows you to give a full path as the ``dir`` without worrying + ## about subdirectories not existing. + if not recursive: + assertReply(await(ftp.send("MKD " & dir.normalizePathSep)), "257") + else: + var reply = TaintedString"" + var previousDirs = "" + for p in split(dir, {os.dirSep, os.altSep}): + if p != "": + previousDirs.add(p) + reply = await ftp.send("MKD " & previousDirs) + previousDirs.add('/') + assertReply reply, "257" + +proc chmod*(ftp: PAsyncFtpClient, path: string, + permissions: set[TFilePermission]) {.async.} = + ## Changes permission of ``path`` to ``permissions``. + var userOctal = 0 + var groupOctal = 0 + var otherOctal = 0 + for i in items(permissions): + case i + of fpUserExec: userOctal.inc(1) + of fpUserWrite: userOctal.inc(2) + of fpUserRead: userOctal.inc(4) + of fpGroupExec: groupOctal.inc(1) + of fpGroupWrite: groupOctal.inc(2) + of fpGroupRead: groupOctal.inc(4) + of fpOthersExec: otherOctal.inc(1) + of fpOthersWrite: otherOctal.inc(2) + of fpOthersRead: otherOctal.inc(4) + + var perm = $userOctal & $groupOctal & $otherOctal + assertReply(await(ftp.send("SITE CHMOD " & perm & + " " & path.normalizePathSep)), "200") + +proc list*(ftp: PAsyncFtpClient, dir = ""): PFuture[string] {.async.} = + ## Lists all files in ``dir``. If ``dir`` is ``""``, uses the current + ## working directory. + await ftp.pasv() + + let reply = await ftp.send("LIST" & " " & dir.normalizePathSep) + assertReply(reply, ["125", "150"]) + + result = await ftp.getLines() + +proc retrText*(ftp: PAsyncFtpClient, file: string): PFuture[string] {.async.} = + ## Retrieves ``file``. File must be ASCII text. + await ftp.pasv() + let reply = await ftp.send("RETR " & file.normalizePathSep) + assertReply(reply, ["125", "150"]) + + result = await ftp.getLines() + +proc getFile(ftp: PAsyncFtpClient, file: TFile, total: BiggestInt, + onProgressChanged: ProgressChangedProc) {.async.} = + assert ftp.dsockConnected + var progress = 0 + var progressInSecond = 0 + var countdownFut = sleepAsync(1000) + var dataFut = ftp.dsock.recv(bufferSize) + while ftp.dsockConnected: + await dataFut or countdownFut + if countdownFut.finished: + asyncCheck onProgressChanged(total, progress, + progressInSecond.float) + progressInSecond = 0 + countdownFut = sleepAsync(1000) + + if dataFut.finished: + let data = dataFut.read + if data != "": + progress.inc(data.len) + progressInSecond.inc(data.len) + file.write(data) + dataFut = ftp.dsock.recv(bufferSize) + else: + ftp.dsockConnected = False + + assertReply(await(ftp.expectReply()), "226") + +proc defaultOnProgressChanged*(total, progress: BiggestInt, + speed: float): PFuture[void] {.nimcall,gcsafe.} = + ## Default FTP ``onProgressChanged`` handler. Does nothing. + result = newFuture[void]() + #echo(total, " ", progress, " ", speed) + result.complete() + +proc retrFile*(ftp: PAsyncFtpClient, file, dest: string, + onProgressChanged = defaultOnProgressChanged) {.async.} = + ## Downloads ``file`` and saves it to ``dest``. + ## The ``EvRetr`` event is passed to the specified ``handleEvent`` function + ## when the download is finished. The event's ``filename`` field will be equal + ## to ``file``. + var destFile = open(dest, mode = fmWrite) + await ftp.pasv() + var reply = await ftp.send("RETR " & file.normalizePathSep) + assertReply reply, ["125", "150"] + if {'(', ')'} notin reply.string: + raise newException(EInvalidReply, "Reply has no file size.") + var fileSize: biggestInt + if reply.string.captureBetween('(', ')').parseBiggestInt(fileSize) == 0: + raise newException(EInvalidReply, "Reply has no file size.") + + await getFile(ftp, destFile, fileSize, onProgressChanged) + +proc doUpload(ftp: PAsyncFtpClient, file: TFile, + onProgressChanged: ProgressChangedProc) {.async.} = + assert ftp.dsockConnected + + let total = file.getFileSize() + var data = newStringOfCap(4000) + var progress = 0 + var progressInSecond = 0 + var countdownFut = sleepAsync(1000) + var sendFut: PFuture[void] = nil + while ftp.dsockConnected: + if sendFut == nil or sendFut.finished: + progress.inc(data.len) + progressInSecond.inc(data.len) + # TODO: Async file reading. + let len = file.readBuffer(addr(data[0]), 4000) + setLen(data, len) + if len == 0: + # File finished uploading. + ftp.dsock.close() + ftp.dsockConnected = false + + assertReply(await(ftp.expectReply()), "226") + else: + sendFut = ftp.dsock.send(data) + + if countdownFut.finished: + asyncCheck onProgressChanged(total, progress, progressInSecond.float) + progressInSecond = 0 + countdownFut = sleepAsync(1000) + + await countdownFut or sendFut + +proc storeFile*(ftp: PAsyncFtpClient, file, dest: string, + onProgressChanged = defaultOnProgressChanged) {.async.} = + ## Uploads ``file`` to ``dest`` on the remote FTP server. Usage of this + ## function asynchronously is recommended to view the progress of + ## the download. + ## The ``EvStore`` event is passed to the specified ``handleEvent`` function + ## when the upload is finished, and the ``filename`` field will be + ## equal to ``file``. + var destFile = open(file) + await ftp.pasv() + + let reply = await ftp.send("STOR " & dest.normalizePathSep) + assertReply reply, ["125", "150"] + + await doUpload(ftp, destFile, onProgressChanged) + +proc newAsyncFtpClient*(address: string, port = TPort(21), + user, pass = ""): PAsyncFtpClient = + ## Creates a new ``PAsyncFtpClient`` object. + new result + result.user = user + result.pass = pass + result.address = address + result.port = port + result.dsockConnected = false + result.csock = newAsyncSocket() + +when isMainModule: + var ftp = newAsyncFtpClient("example.com", user = "test", pass = "test") + proc main(ftp: PAsyncFtpClient) {.async.} = + await ftp.connect() + echo await ftp.pwd() + echo await ftp.listDirs() + await ftp.storeFile("payload.jpg", "payload.jpg") + await ftp.retrFile("payload.jpg", "payload2.jpg") + echo("Finished") + + waitFor main(ftp) diff --git a/lib/pure/ftpclient.nim b/lib/pure/ftpclient.nim index 8bbbd01fb2..e8d3f762ee 100644 --- a/lib/pure/ftpclient.nim +++ b/lib/pure/ftpclient.nim @@ -10,6 +10,10 @@ include "system/inclrtl" import sockets, strutils, parseutils, times, os, asyncio +from asyncnet import nil +from rawsockets import nil +from asyncdispatch import PFuture + ## This module **partially** implements an FTP client as specified ## by `RFC 959 `_. ## @@ -36,20 +40,23 @@ import sockets, strutils, parseutils, times, os, asyncio type PFtpBase*[SockType] = ref TFtpBase[SockType] TFtpBase*[SockType] = object - csock: SockType - dsock: SockType - when SockType is PAsyncSocket: + csock*: SockType + dsock*: SockType + when SockType is asyncio.PAsyncSocket: handleEvent*: proc (ftp: PAsyncFTPClient, ev: TFTPEvent){.closure,gcsafe.} disp: PDispatcher asyncDSockID: PDelegate - user, pass: string - address: string - port: TPort + user*, pass*: string + address*: string + when SockType is asyncnet.PAsyncSocket: + port*: rawsockets.TPort + else: + port*: TPort - jobInProgress: bool - job: PFTPJob[SockType] + jobInProgress*: bool + job*: PFTPJob[SockType] - dsockConnected: bool + dsockConnected*: bool FTPJobType* = enum JRetrText, JRetr, JStore @@ -74,7 +81,7 @@ type PFtpClient* = ref TFTPClient PAsyncFTPClient* = ref TAsyncFTPClient ## Async alternative to TFTPClient. - TAsyncFTPClient* = TFtpBase[PAsyncSocket] + TAsyncFTPClient* = TFtpBase[asyncio.PAsyncSocket] FTPEventType* = enum EvTransferProgress, EvLines, EvRetr, EvStore @@ -117,7 +124,7 @@ proc getCSock[T](ftp: PFTPBase[T]): TSocket = template blockingOperation(sock: TSocket, body: stmt) {.immediate.} = body -template blockingOperation(sock: PAsyncSocket, body: stmt) {.immediate.} = +template blockingOperation(sock: asyncio.PAsyncSocket, body: stmt) {.immediate.} = sock.setBlocking(true) body sock.setBlocking(false) @@ -619,7 +626,7 @@ when isMainModule: if not d.poll(): break main() -when not isMainModule: +when isMainModule and false: var ftp = ftpClient("example.com", user = "foo", pass = "bar") ftp.connect() echo ftp.pwd() diff --git a/lib/pure/httpclient.nim b/lib/pure/httpclient.nim index 9bacc80d62..4db6ac6ed2 100644 --- a/lib/pure/httpclient.nim +++ b/lib/pure/httpclient.nim @@ -654,8 +654,7 @@ when isMainModule: resp = await client.request("http://nimrod-lang.org/download.html") echo("Got response: ", resp.status) - asyncCheck main() - runForever() + waitFor main() else: #downloadFile("http://force7.de/nimrod/index.html", "nimrodindex.html") From 7dac395cb2689b2e529b6e0b9507f2529dc125bb Mon Sep 17 00:00:00 2001 From: Erwan Ameil Date: Sat, 30 Aug 2014 20:42:40 +0200 Subject: [PATCH 185/234] Remove outdated ZeroMQ example (zmq has been moved out of the stdlib) --- examples/0mq/client.nim | 14 -------------- examples/0mq/server.nim | 11 ----------- 2 files changed, 25 deletions(-) delete mode 100644 examples/0mq/client.nim delete mode 100644 examples/0mq/server.nim diff --git a/examples/0mq/client.nim b/examples/0mq/client.nim deleted file mode 100644 index e75e5c7a2d..0000000000 --- a/examples/0mq/client.nim +++ /dev/null @@ -1,14 +0,0 @@ -import zmq - -var connection = zmq.open("tcp://localhost:5555", server=false) - -echo("Connecting...") - -for i in 0..10: - echo("Sending hello...", i) - send(connection, "Hello") - - var reply = receive(connection) - echo("Received ...", reply) - -close(connection) diff --git a/examples/0mq/server.nim b/examples/0mq/server.nim deleted file mode 100644 index 0fadf8b97f..0000000000 --- a/examples/0mq/server.nim +++ /dev/null @@ -1,11 +0,0 @@ -import zmq - -var connection = zmq.open("tcp://*:5555", server=true) - -while True: - var request = receive(connection) - echo("Received: ", request) - send(connection, "World") - -close(connection) - From a249a12da7d1868176788e3bc1627f76aa9977e8 Mon Sep 17 00:00:00 2001 From: Erwan Ameil Date: Sat, 30 Aug 2014 21:38:47 +0200 Subject: [PATCH 186/234] Secure and HttpOnly cookies --- lib/pure/cookies.nim | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/lib/pure/cookies.nim b/lib/pure/cookies.nim index d1cf36a871..49bf929807 100644 --- a/lib/pure/cookies.nim +++ b/lib/pure/cookies.nim @@ -28,8 +28,9 @@ proc parseCookies*(s: string): PStringTable = if s[i] == '\0': break inc(i) # skip ';' -proc setCookie*(key, value: string, domain = "", path = "", - expires = "", noName = false): string = +proc setCookie*(key, value: string, domain = "", path = "", + expires = "", noName = false, + secure = false, httpOnly = false): string = ## Creates a command in the format of ## ``Set-Cookie: key=value; Domain=...; ...`` result = "" @@ -38,16 +39,20 @@ proc setCookie*(key, value: string, domain = "", path = "", if domain != "": result.add("; Domain=" & domain) if path != "": result.add("; Path=" & path) if expires != "": result.add("; Expires=" & expires) + if secure: result.add("; secure") + if httpOnly: result.add("; HttpOnly") proc setCookie*(key, value: string, expires: TTimeInfo, - domain = "", path = "", noName = false): string = + domain = "", path = "", noName = false, + secure = false, httpOnly = false): string = ## Creates a command in the format of ## ``Set-Cookie: key=value; Domain=...; ...`` ## ## **Note:** UTC is assumed as the timezone for ``expires``. return setCookie(key, value, domain, path, - format(expires, "ddd',' dd MMM yyyy HH:mm:ss 'UTC'"), noname) + format(expires, "ddd',' dd MMM yyyy HH:mm:ss 'UTC'"), + noname, secure, httpOnly) when isMainModule: var tim = TTime(int(getTime()) + 76 * (60 * 60 * 24)) @@ -55,5 +60,3 @@ when isMainModule: echo(setCookie("test", "value", tim.getGMTime())) echo parseCookies("uid=1; kp=2") - - \ No newline at end of file From 05c1fb060fce7402541f625fe1dabb6ed30b6d48 Mon Sep 17 00:00:00 2001 From: Erwan Ameil Date: Sat, 30 Aug 2014 22:21:38 +0200 Subject: [PATCH 187/234] Escape ' and / when using escape in xmltree --- lib/pure/xmltree.nim | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/pure/xmltree.nim b/lib/pure/xmltree.nim index 95b48a850d..1af7db7d55 100644 --- a/lib/pure/xmltree.nim +++ b/lib/pure/xmltree.nim @@ -151,6 +151,8 @@ proc addEscaped*(result: var string, s: string) = of '>': result.add(">") of '&': result.add("&") of '"': result.add(""") + of '\'': result.add("'") + of '/': result.add("/") else: result.add(c) proc escape*(s: string): string = @@ -164,6 +166,8 @@ proc escape*(s: string): string = ## ``>`` ``>`` ## ``&`` ``&`` ## ``"`` ``"`` + ## ``'`` ``'`` + ## ``/`` ``/`` ## ------------ ------------------- result = newStringOfCap(s.len) addEscaped(result, s) From 10f6a11cf22ac4be35eb8119b654124f2b58c45f Mon Sep 17 00:00:00 2001 From: fuzzthink Date: Tue, 2 Sep 2014 10:10:18 +0900 Subject: [PATCH 188/234] Pointer -> pointer to fix compile error using --cs:partial --- lib/system/jssys.nim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/system/jssys.nim b/lib/system/jssys.nim index 8766906e3a..423f63e2a8 100644 --- a/lib/system/jssys.nim +++ b/lib/system/jssys.nim @@ -515,7 +515,7 @@ proc isFatPointer(ti: PNimType): bool = proc nimCopy(x: pointer, ti: PNimType): pointer {.compilerproc.} -proc nimCopyAux(dest, src: Pointer, n: ptr TNimNode) {.compilerproc.} = +proc nimCopyAux(dest, src: pointer, n: ptr TNimNode) {.compilerproc.} = case n.kind of nkNone: sysAssert(false, "nimCopyAux") of nkSlot: @@ -566,7 +566,7 @@ proc nimCopy(x: pointer, ti: PNimType): pointer = else: result = x -proc genericReset(x: Pointer, ti: PNimType): pointer {.compilerproc.} = +proc genericReset(x: pointer, ti: PNimType): pointer {.compilerproc.} = case ti.kind of tyPtr, tyRef, tyVar, tyNil: if not isFatPointer(ti): From f9c46b04a61c2ea1362b33e69c6e211f2d225354 Mon Sep 17 00:00:00 2001 From: Reimer Behrends Date: Wed, 10 Sep 2014 01:22:20 +0200 Subject: [PATCH 189/234] Properly handle staticExec() generating large output. A staticExec() invocation that generated more than the internal buffer size worth of output blocked because the compiler waited for the process to terminate before reading the output. --- compiler/vmdeps.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/vmdeps.nim b/compiler/vmdeps.nim index 9a213d8133..fdd8276cc3 100644 --- a/compiler/vmdeps.nim +++ b/compiler/vmdeps.nim @@ -12,11 +12,11 @@ import ast, types, msgs, osproc, streams, options proc readOutput(p: PProcess): string = result = "" var output = p.outputStream - discard p.waitForExit while not output.atEnd: result.add(output.readLine) result.add("\n") result.setLen(result.len - "\n".len) + discard p.waitForExit proc opGorge*(cmd, input: string): string = var p = startCmd(cmd) From 2c99991d169d66d5fd2334cfc783761d1ffe25bc Mon Sep 17 00:00:00 2001 From: Araq Date: Thu, 11 Sep 2014 00:34:59 +0200 Subject: [PATCH 190/234] fixes #1444 --- compiler/semgnrc.nim | 16 ++-- config/nim.cfg | 139 ++++++++++++++++++++++++++++++++++ lib/pure/collections/sets.nim | 2 +- lib/system.nim | 4 +- tests/generics/mdotlookup.nim | 8 ++ tests/generics/tdotlookup.nim | 5 +- 6 files changed, 165 insertions(+), 9 deletions(-) create mode 100644 config/nim.cfg diff --git a/compiler/semgnrc.nim b/compiler/semgnrc.nim index 934434951c..a004d14659 100644 --- a/compiler/semgnrc.nim +++ b/compiler/semgnrc.nim @@ -36,10 +36,11 @@ proc semGenericStmtScope(c: PContext, n: PNode, template macroToExpand(s: expr): expr = s.kind in {skMacro, skTemplate} and (s.typ.len == 1 or sfImmediate in s.flags) -proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym): PNode = +proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym, + ctx: var TIntSet): PNode = incl(s.flags, sfUsed) case s.kind - of skUnknown: + of skUnknown: # Introduced in this pass! Leave it as an identifier. result = n of skProc, skMethod, skIterators, skConverter: @@ -48,11 +49,13 @@ proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym): PNode = if macroToExpand(s): let n = fixImmediateParams(n) result = semTemplateExpr(c, n, s, {efNoSemCheck}) + result = semGenericStmt(c, result, {}, ctx) else: result = symChoice(c, n, s, scOpen) of skMacro: if macroToExpand(s): result = semMacroExpr(c, n, n, s, {efNoSemCheck}) + result = semGenericStmt(c, result, {}, ctx) else: result = symChoice(c, n, s, scOpen) of skGenericParam: @@ -80,7 +83,7 @@ proc lookup(c: PContext, n: PNode, flags: TSemGenericFlags, elif s.name.id in ctx: result = symChoice(c, n, s, scForceOpen) else: - result = semGenericStmtSymbol(c, n, s) + result = semGenericStmtSymbol(c, n, s, ctx) # else: leave as nkIdent proc newDot(n, b: PNode): PNode = @@ -95,8 +98,9 @@ proc fuzzyLookup(c: PContext, n: PNode, flags: TSemGenericFlags, var s = qualifiedLookUp(c, n, luf) if s != nil: - result = semGenericStmtSymbol(c, n, s) + result = semGenericStmtSymbol(c, n, s, ctx) else: + n.sons[0] = semGenericStmt(c, n.sons[0], flags, ctx) result = n let n = n[1] let ident = considerQuotedIdent(n) @@ -107,7 +111,7 @@ proc fuzzyLookup(c: PContext, n: PNode, flags: TSemGenericFlags, elif s.name.id in ctx: result = newDot(result, symChoice(c, n, s, scForceOpen)) else: - let sym = semGenericStmtSymbol(c, n, s) + let sym = semGenericStmtSymbol(c, n, s, ctx) if sym.kind == nkSym: result = newDot(result, symChoice(c, n, s, scForceOpen)) else: @@ -158,6 +162,7 @@ proc semGenericStmt(c: PContext, n: PNode, of skMacro: if macroToExpand(s): result = semMacroExpr(c, n, n, s, {efNoSemCheck}) + result = semGenericStmt(c, result, {}, ctx) else: n.sons[0] = symChoice(c, n.sons[0], s, scOption) result = n @@ -165,6 +170,7 @@ proc semGenericStmt(c: PContext, n: PNode, if macroToExpand(s): let n = fixImmediateParams(n) result = semTemplateExpr(c, n, s, {efNoSemCheck}) + result = semGenericStmt(c, result, {}, ctx) else: n.sons[0] = symChoice(c, n.sons[0], s, scOption) result = n diff --git a/config/nim.cfg b/config/nim.cfg new file mode 100644 index 0000000000..df3835ace7 --- /dev/null +++ b/config/nim.cfg @@ -0,0 +1,139 @@ +# Configuration file for the Nimrod Compiler. +# (c) 2013 Andreas Rumpf + +# Feel free to edit the default values as you need. + +# You may set environment variables with +# @putenv "key" "val" +# Environment variables cannot be used in the options, however! + +cc = gcc + +# example of how to setup a cross-compiler: +arm.linux.gcc.exe = "arm-linux-gcc" +arm.linux.gcc.linkerexe = "arm-linux-gcc" + +path="$lib/core" +path="$lib/pure" +path="$lib/pure/collections" +path="$lib/pure/concurrency" +path="$lib/impure" +path="$lib/wrappers" +# path="$lib/wrappers/cairo" +# path="$lib/wrappers/gtk" +# path="$lib/wrappers/lua" +# path="$lib/wrappers/opengl" +path="$lib/wrappers/pcre" +path="$lib/wrappers/readline" +path="$lib/wrappers/sdl" +# path="$lib/wrappers/x11" +path="$lib/wrappers/zip" +path="$lib/wrappers/libffi" +path="$lib/windows" +path="$lib/posix" +path="$lib/js" +path="$lib/pure/unidecode" + +@if nimbabel: + babelpath="$home/.babel/pkgs/" +@end + +@if release or quick: + obj_checks:off + field_checks:off + range_checks:off + bound_checks:off + overflow_checks:off + assertions:off + stacktrace:off + linetrace:off + debugger:off + line_dir:off + dead_code_elim:on +@end + +@if release: + opt:speed +@end + +# additional options always passed to the compiler: +--parallel_build: "0" # 0 to auto-detect number of processors + +hint[LineTooLong]=off +#hint[XDeclaredButNotUsed]=off + +@if unix: + @if not bsd: + # -fopenmp + gcc.options.linker = "-ldl" + gpp.options.linker = "-ldl" + clang.options.linker = "-ldl" + tcc.options.linker = "-ldl" + @end + @if bsd or haiku: + # BSD got posix_spawn only recently, so we deactivate it for osproc: + define:useFork + # at least NetBSD has problems with thread local storage: + tlsEmulation:on + @end +@end + +# Configuration for the Intel C/C++ compiler: +@if windows: + icl.options.speed = "/Ox /arch:SSE2" + icl.options.always = "/nologo" +@end + +# Configuration for the GNU C/C++ compiler: +@if windows: + #gcc.path = r"$nimrod\dist\mingw\bin" + @if gcc: + tlsEmulation:on + @end +@end + +@if macosx: + cc = clang + tlsEmulation:on + gcc.options.always = "-w -fasm-blocks" + gpp.options.always = "-w -fasm-blocks -fpermissive" +@else: + gcc.options.always = "-w" + gpp.options.always = "-w -fpermissive" +@end + +gcc.options.speed = "-O3 -fno-strict-aliasing" +gcc.options.size = "-Os" +gcc.options.debug = "-g3 -O0" + +gpp.options.speed = "-O3 -fno-strict-aliasing" +gpp.options.size = "-Os" +gpp.options.debug = "-g3 -O0" +#passl = "-pg" + +# Configuration for the LLVM GCC compiler: +llvm_gcc.options.debug = "-g" +llvm_gcc.options.always = "-w" +llvm_gcc.options.speed = "-O2" +llvm_gcc.options.size = "-Os" + +# Configuration for the LLVM CLang compiler: +clang.options.debug = "-g" +clang.options.always = "-w" +clang.options.speed = "-O3" +clang.options.size = "-Os" + +# Configuration for the Visual C/C++ compiler: +vcc.options.linker = "/DEBUG /Zi /Fd\"$projectName.pdb\" /F33554432" # set the stack size to 8 MB +vcc.options.debug = "/Zi /Fd\"$projectName.pdb\"" +vcc.options.always = "/nologo" +vcc.options.speed = "/Ox /arch:SSE2" +vcc.options.size = "/O1" + +# Configuration for the Digital Mars C/C++ compiler: +@if windows: + dmc.path = r"$nimrod\dist\dm\bin" +@end + +# Configuration for the Tiny C Compiler: +tcc.options.always = "-w" diff --git a/lib/pure/collections/sets.nim b/lib/pure/collections/sets.nim index 22eff9c557..ce901963e7 100644 --- a/lib/pure/collections/sets.nim +++ b/lib/pure/collections/sets.nim @@ -128,7 +128,7 @@ proc mget*[A](s: var TSet[A], key: A): var A = ## for sharing. assert s.isValid, "The set needs to be initialized." var index = rawGet(s, key) - if index >= 0: result = t.data[index].key + if index >= 0: result = s.data[index].key else: raise newException(EInvalidKey, "key not found: " & $key) proc contains*[A](s: TSet[A], key: A): bool = diff --git a/lib/system.nim b/lib/system.nim index 0d8f63bd48..0df8849f5a 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -849,13 +849,13 @@ proc contains*[T](s: TSlice[T], value: T): bool {.noSideEffect, inline.} = ## assert((1..3).contains(4) == false) result = s.a <= value and value <= s.b -template `in` * (x, y: expr): expr {.immediate.} = contains(y, x) +template `in` * (x, y: expr): expr {.immediate, dirty.} = contains(y, x) ## Sugar for contains ## ## .. code-block:: Nimrod ## assert(1 in (1..3) == true) ## assert(5 in (1..3) == false) -template `notin` * (x, y: expr): expr {.immediate.} = not contains(y, x) +template `notin` * (x, y: expr): expr {.immediate, dirty.} = not contains(y, x) ## Sugar for not containing ## ## .. code-block:: Nimrod diff --git a/tests/generics/mdotlookup.nim b/tests/generics/mdotlookup.nim index 7a5e0ccbf0..0c4d0c87c7 100644 --- a/tests/generics/mdotlookup.nim +++ b/tests/generics/mdotlookup.nim @@ -6,3 +6,11 @@ type MyObj = object proc foo*(b: any) = var o: MyObj echo b.baz, " ", o.x.baz, " ", b.baz() + +import sets + +var intset = initSet[int]() + +proc func*[T](a: T) = + if a in intset: echo("true") + else: echo("false") diff --git a/tests/generics/tdotlookup.nim b/tests/generics/tdotlookup.nim index b886cd8c91..d3deca7fcb 100644 --- a/tests/generics/tdotlookup.nim +++ b/tests/generics/tdotlookup.nim @@ -1,7 +1,10 @@ discard """ - output: '''5 5 5''' + output: '''5 5 5 +false''' """ import mdotlookup foo(7) +# bug #1444 +func(4) From e766c7c3cd73ee9dc66266a0c1246a262ce51268 Mon Sep 17 00:00:00 2001 From: Araq Date: Thu, 11 Sep 2014 00:36:31 +0200 Subject: [PATCH 191/234] minor bugfix for void .compileTime procs --- compiler/semexprs.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index da12ec08cd..ff445ecd09 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -662,7 +662,7 @@ proc evalAtCompileTime(c: PContext, n: PNode): PNode = # optimization pass: not necessary for correctness of the semantic pass if {sfNoSideEffect, sfCompileTime} * callee.flags != {} and - {sfForward, sfImportc} * callee.flags == {}: + {sfForward, sfImportc} * callee.flags == {} and n.typ != nil: if sfCompileTime notin callee.flags and optImplicitStatic notin gOptions: return From b7f8dbbec2bc01f753100659f3db35b024e0076a Mon Sep 17 00:00:00 2001 From: Araq Date: Thu, 11 Sep 2014 00:45:29 +0200 Subject: [PATCH 192/234] fixes #1511 --- compiler/semstmts.nim | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 5831850487..d394a2ae5c 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -22,20 +22,23 @@ proc semDiscard(c: PContext, n: PNode): PNode = proc semBreakOrContinue(c: PContext, n: PNode): PNode = result = n checkSonsLen(n, 1) - if n.sons[0].kind != nkEmpty: - var s: PSym - case n.sons[0].kind - of nkIdent: s = lookUp(c, n.sons[0]) - of nkSym: s = n.sons[0].sym - else: illFormedAst(n) - if s.kind == skLabel and s.owner.id == c.p.owner.id: - var x = newSymNode(s) - x.info = n.info - incl(s.flags, sfUsed) - n.sons[0] = x - suggestSym(x.info, s) + if n.sons[0].kind != nkEmpty: + if n.kind != nkContinueStmt: + var s: PSym + case n.sons[0].kind + of nkIdent: s = lookUp(c, n.sons[0]) + of nkSym: s = n.sons[0].sym + else: illFormedAst(n) + if s.kind == skLabel and s.owner.id == c.p.owner.id: + var x = newSymNode(s) + x.info = n.info + incl(s.flags, sfUsed) + n.sons[0] = x + suggestSym(x.info, s) + else: + localError(n.info, errInvalidControlFlowX, s.name.s) else: - localError(n.info, errInvalidControlFlowX, s.name.s) + localError(n.info, errGenerated, "'continue' cannot have a label") elif (c.p.nestedLoopCounter <= 0) and (c.p.nestedBlockCounter <= 0): localError(n.info, errInvalidControlFlowX, renderTree(n, {renderNoComments})) From dafa8ccaf39b3fac86a4d782693bd618d1f38e7b Mon Sep 17 00:00:00 2001 From: Araq Date: Thu, 11 Sep 2014 01:45:14 +0200 Subject: [PATCH 193/234] fixes #903, fixess #1513 --- compiler/vmgen.nim | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim index 94afbf008e..a4ddc2e15f 100644 --- a/compiler/vmgen.nim +++ b/compiler/vmgen.nim @@ -43,18 +43,19 @@ type proc debugInfo(info: TLineInfo): string = result = info.toFilename.splitFile.name & ":" & $info.line -proc codeListing(c: PCtx, result: var string, start=0) = +proc codeListing(c: PCtx, result: var string, start=0; last = -1) = # first iteration: compute all necessary labels: var jumpTargets = initIntSet() - for i in start.. < c.code.len: + let last = if last < 0: c.code.len-1 else: min(last, c.code.len-1) + for i in start..last: let x = c.code[i] if x.opcode in relativeJumps: jumpTargets.incl(i+x.regBx-wordExcess) # for debugging purposes var i = start - while i < c.code.len: + while i <= last: if i in jumpTargets: result.addf("L$1:\n", i) let x = c.code[i] @@ -82,9 +83,9 @@ proc codeListing(c: PCtx, result: var string, start=0) = result.add("\n") inc i -proc echoCode*(c: PCtx, start=0) {.deprecated.} = +proc echoCode*(c: PCtx, start=0; last = -1) {.deprecated.} = var buf = "" - codeListing(c, buf, start) + codeListing(c, buf, start, last) echo buf proc gABC(ctx: PCtx; n: PNode; opc: TOpcode; a, b, c: TRegister = 0) = @@ -495,6 +496,7 @@ proc genCall(c: PCtx; n: PNode; dest: var TDest) = c.freeTempRange(x, n.len) template isGlobal(s: PSym): bool = sfGlobal in s.flags and s.kind != skForVar +proc isGlobal(n: PNode): bool = n.kind == nkSym and isGlobal(n.sym) proc needsAsgnPatch(n: PNode): bool = n.kind in {nkBracketExpr, nkDotExpr, nkCheckedFieldExpr, @@ -637,8 +639,10 @@ proc genBinaryStmt(c: PCtx; n: PNode; opc: TOpcode) = c.freeTemp(tmp) proc genBinaryStmtVar(c: PCtx; n: PNode; opc: TOpcode) = + var x = n.sons[1] + if x.kind in {nkAddr, nkHiddenAddr}: x = x.sons[0] let - dest = c.genx(n.sons[1], {gfAddrOf}) + dest = c.genx(x) tmp = c.genx(n.sons[2]) c.gABC(n, opc, dest, tmp, 0) #c.genAsgnPatch(n.sons[1], dest) @@ -1053,6 +1057,8 @@ proc genAddrDeref(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode; # nkAddr we must not use 'unneededIndirection', but for deref we use it. if not isAddr and unneededIndirection(n.sons[0]): gen(c, n.sons[0], dest, newflags) + elif isAddr and isGlobal(n.sons[0]): + gen(c, n.sons[0], dest, flags+{gfAddrOf}) else: let tmp = c.genx(n.sons[0], newflags) if dest < 0: dest = c.getTemp(n.typ) @@ -1247,6 +1253,8 @@ proc genRdVar(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) = c.gABx(n, opcLdGlobal, cc, s.position) c.gABC(n, opcNodeToReg, dest, cc) c.freeTemp(cc) + elif gfAddrOf in flags: + c.gABx(n, opcLdGlobalAddr, dest, s.position) else: c.gABx(n, opcLdGlobal, dest, s.position) else: From 24afab2a95eb761f59ae0f2797e5803c9e2bdd41 Mon Sep 17 00:00:00 2001 From: Araq Date: Thu, 11 Sep 2014 09:36:22 +0200 Subject: [PATCH 194/234] Threads work again --- lib/system/threads.nim | 78 +++++++++++++++++++++++++----------------- 1 file changed, 46 insertions(+), 32 deletions(-) diff --git a/lib/system/threads.nim b/lib/system/threads.nim index 4717659e5f..c30c57fb9e 100644 --- a/lib/system/threads.nim +++ b/lib/system/threads.nim @@ -1,17 +1,17 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2012 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. # -## Thread support for Nimrod. **Note**: This is part of the system module. +## Thread support for Nim. **Note**: This is part of the system module. ## Do not import it directly. To activate thread support you need to compile ## with the ``--threads:on`` command line switch. ## -## Nimrod's memory model for threads is quite different from other common +## Nim's memory model for threads is quite different from other common ## programming languages (C, Pascal): Each thread has its own ## (garbage collected) heap and sharing of memory is restricted. This helps ## to prevent race conditions and improves efficiency. See `the manual for @@ -19,7 +19,7 @@ ## ## Example: ## -## .. code-block:: nimrod +## .. code-block:: Nim ## ## import locks ## @@ -190,7 +190,7 @@ var globalsSlot = threadVarAlloc() when emulatedThreadVars: proc GetThreadLocalVars(): pointer {.compilerRtl, inl.} = - result = addr(cast[PGcThread](ThreadVarGetValue(globalsSlot)).tls) + result = addr(cast[PGcThread](threadVarGetValue(globalsSlot)).tls) when useStackMaskHack: proc maskStackPointer(offset: int): pointer {.compilerRtl, inl.} = @@ -210,7 +210,7 @@ when not defined(useNimRtl): initGC() when emulatedThreadVars: - if NimThreadVarsSize() > sizeof(TThreadLocalStorage): + if nimThreadVarsSize() > sizeof(TThreadLocalStorage): echo "too large thread local storage size requested" quit 1 @@ -245,14 +245,14 @@ when not defined(useNimRtl): # the GC can examine the stacks? proc stopTheWord() = discard -# We jump through some hops here to ensure that Nimrod thread procs can have -# the Nimrod calling convention. This is needed because thread procs are +# We jump through some hops here to ensure that Nim thread procs can have +# the Nim calling convention. This is needed because thread procs are # ``stdcall`` on Windows and ``noconv`` on UNIX. Alternative would be to just # use ``stdcall`` since it is mapped to ``noconv`` on UNIX anyway. type TThread* {.pure, final.}[TArg] = - object of TGcThread ## Nimrod thread. A thread is a heavy object (~14K) + object of TGcThread ## Nim thread. A thread is a heavy object (~14K) ## that **must not** be part of a message! Use ## a ``TThreadId`` for that. when TArg is void: @@ -267,7 +267,7 @@ when not defined(boehmgc) and not hasSharedHeap: proc deallocOsPages() template threadProcWrapperBody(closure: expr) {.immediate.} = - when declared(globalsSlot): ThreadVarSetValue(globalsSlot, closure) + when declared(globalsSlot): threadVarSetValue(globalsSlot, closure) var t = cast[ptr TThread[TArg]](closure) when useStackMaskHack: var tls: TThreadLocalStorage @@ -305,22 +305,26 @@ proc running*[TArg](t: TThread[TArg]): bool {.inline.} = ## returns true if `t` is running. result = t.dataFn != nil -proc joinThread*[TArg](t: TThread[TArg]) {.inline.} = - ## waits for the thread `t` to finish. - when hostOS == "windows": +when hostOS == "windows": + proc joinThread*[TArg](t: TThread[TArg]) {.inline.} = + ## waits for the thread `t` to finish. discard waitForSingleObject(t.sys, -1'i32) - else: - discard pthread_join(t.sys, nil) -proc joinThreads*[TArg](t: varargs[TThread[TArg]]) = - ## waits for every thread in `t` to finish. - when hostOS == "windows": + proc joinThreads*[TArg](t: varargs[TThread[TArg]]) = + ## waits for every thread in `t` to finish. var a: array[0..255, TSysThread] sysAssert a.len >= t.len, "a.len >= t.len" for i in 0..t.high: a[i] = t[i].sys - discard waitForMultipleObjects(t.len.int32, + discard waitForMultipleObjects(t.len.int32, cast[ptr TSysThread](addr(a)), 1, -1) - else: + +else: + proc joinThread*[TArg](t: TThread[TArg]) {.inline.} = + ## waits for the thread `t` to finish. + discard pthread_join(t.sys, nil) + + proc joinThreads*[TArg](t: varargs[TThread[TArg]]) = + ## waits for every thread in `t` to finish. for i in 0..t.high: joinThread(t[i]) when false: @@ -335,22 +339,32 @@ when false: when declared(registerThread): unregisterThread(addr(t)) t.dataFn = nil -proc createThread*[TArg](t: var TThread[TArg], - tp: proc (arg: TArg) {.thread.}, - param: TArg) = - ## creates a new thread `t` and starts its execution. Entry point is the - ## proc `tp`. `param` is passed to `tp`. `TArg` can be ``void`` if you - ## don't need to pass any data to the thread. - when TArg isnot void: t.data = param - t.dataFn = tp - when hasSharedHeap: t.stackSize = ThreadStackSize - when hostOS == "windows": +when hostOS == "windows": + proc createThread*[TArg](t: var TThread[TArg], + tp: proc (arg: TArg) {.thread.}, + param: TArg) = + ## creates a new thread `t` and starts its execution. Entry point is the + ## proc `tp`. `param` is passed to `tp`. `TArg` can be ``void`` if you + ## don't need to pass any data to the thread. + when TArg isnot void: t.data = param + t.dataFn = tp + when hasSharedHeap: t.stackSize = ThreadStackSize var dummyThreadId: int32 t.sys = createThread(nil, ThreadStackSize, threadProcWrapper[TArg], addr(t), 0'i32, dummyThreadId) if t.sys <= 0: raise newException(EResourceExhausted, "cannot create thread") - else: + +else: + proc createThread*[TArg](t: var TThread[TArg], + tp: proc (arg: TArg) {.thread.}, + param: TArg) = + ## creates a new thread `t` and starts its execution. Entry point is the + ## proc `tp`. `param` is passed to `tp`. `TArg` can be ``void`` if you + ## don't need to pass any data to the thread. + when TArg isnot void: t.data = param + t.dataFn = tp + when hasSharedHeap: t.stackSize = ThreadStackSize var a {.noinit.}: Tpthread_attr pthread_attr_init(a) pthread_attr_setstacksize(a, ThreadStackSize) @@ -364,7 +378,7 @@ proc threadId*[TArg](t: var TThread[TArg]): TThreadId[TArg] {.inline.} = proc myThreadId*[TArg](): TThreadId[TArg] = ## returns the thread ID of the thread that calls this proc. This is unsafe ## because the type ``TArg`` is not checked for consistency! - result = cast[TThreadId[TArg]](ThreadVarGetValue(globalsSlot)) + result = cast[TThreadId[TArg]](threadVarGetValue(globalsSlot)) when false: proc mainThreadId*[TArg](): TThreadId[TArg] = From 46bbae47455f5cefdec78251d8078ae07014bef6 Mon Sep 17 00:00:00 2001 From: Araq Date: Thu, 11 Sep 2014 09:53:00 +0200 Subject: [PATCH 195/234] fixes #1366 --- compiler/semmagic.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim index f943e70061..d4aeba32ac 100644 --- a/compiler/semmagic.nim +++ b/compiler/semmagic.nim @@ -126,7 +126,7 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode, result.typ = getSysType(tyString) of mInstantiationInfo: result = semInstantiationInfo(c, n) of mOrd: result = semOrd(c, n) - of mHigh: result = semLowHigh(c, n, mHigh) + of mHigh, mLow: result = semLowHigh(c, n, n[0].sym.magic) of mShallowCopy: result = semShallowCopy(c, n, flags) of mNBindSym: result = semBindSym(c, n) of mLocals: result = semLocals(c, n) From ff55c487b6b550229b6ca3064c0d432134ca3fff Mon Sep 17 00:00:00 2001 From: Araq Date: Thu, 11 Sep 2014 09:57:33 +0200 Subject: [PATCH 196/234] mostly fixes #1339 --- compiler/semtypinst.nim | 8 ++++++-- compiler/types.nim | 4 +++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim index eeaf536499..9f0a4100d2 100644 --- a/compiler/semtypinst.nim +++ b/compiler/semtypinst.nim @@ -216,12 +216,16 @@ proc replaceTypeVarsS(cl: var TReplTypeVars, s: PSym): PSym = result.typ = replaceTypeVarsT(cl, s.typ) result.ast = replaceTypeVarsN(cl, s.ast) -proc lookupTypeVar(cl: TReplTypeVars, t: PType): PType = +proc lookupTypeVar(cl: var TReplTypeVars, t: PType): PType = result = PType(idTableGet(cl.typeMap, t)) if result == nil: if cl.allowMetaTypes or tfRetType in t.flags: return localError(t.sym.info, errCannotInstantiateX, typeToString(t)) result = errorType(cl.c) + # In order to prevent endless recursions, we must remember + # this bad lookup and replace it with errorType everywhere. + # These code paths are only active in nimrod check + idTablePut(cl.typeMap, t, result) elif result.kind == tyGenericParam and not cl.allowMetaTypes: internalError(cl.info, "substitution with generic parameter") @@ -353,7 +357,7 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType = of tyGenericBody: localError(cl.info, errCannotInstantiateX, typeToString(t)) - result = t + result = errorType(cl.c) #result = replaceTypeVarsT(cl, lastSon(t)) of tyFromExpr: diff --git a/compiler/types.nim b/compiler/types.nim index ec2271deba..c04413857d 100644 --- a/compiler/types.nim +++ b/compiler/types.nim @@ -913,9 +913,11 @@ proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool = result = sameTypeAux(a.sons[0], b.sons[0], c) else: result = sameTypeAux(a.sons[0], b.sons[0], c) and sameFlags(a, b) - of tyEnum, tyForward, tyProxy: + of tyEnum, tyForward: # XXX generic enums do not make much sense, but require structural checking result = a.id == b.id and sameFlags(a, b) + of tyError: + result = b.kind == tyError of tyTuple: cycleCheck() result = sameTuple(a, b, c) and sameFlags(a, b) From c73142d8527308850c0d20f1d3a116b5629e93d2 Mon Sep 17 00:00:00 2001 From: Araq Date: Thu, 11 Sep 2014 10:02:45 +0200 Subject: [PATCH 197/234] fixes #1067 --- compiler/ccgstmts.nim | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index eca026e127..3004e353bc 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -37,6 +37,16 @@ proc genVarTuple(p: BProc, n: PNode) = var tup, field: TLoc if n.kind != nkVarTuple: internalError(n.info, "genVarTuple") var L = sonsLen(n) + + # if we have a something that's been captured, use the lowering instead: + var useLowering = false + for i in countup(0, L-3): + if n[i].kind != nkSym: + useLowering = true; break + if useLowering: + genStmts(p, lowerTupleUnpacking(n, p.prc)) + return + genLineDir(p, n) initLocExpr(p, n.sons[L-1], tup) var t = tup.t From 1791ab6385ee697b42d92b9dcd6cfc014d552558 Mon Sep 17 00:00:00 2001 From: Araq Date: Thu, 11 Sep 2014 19:54:49 +0200 Subject: [PATCH 198/234] fixes #665 --- compiler/lambdalifting.nim | 2 +- compiler/lowerings.nim | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/lambdalifting.nim b/compiler/lambdalifting.nim index 6c650eee3b..62e13b9c42 100644 --- a/compiler/lambdalifting.nim +++ b/compiler/lambdalifting.nim @@ -949,7 +949,7 @@ proc liftLambdas*(fn: PSym, body: PNode): PNode = discard transformOuterProcBody(o, body, initIter(fn)) result = ex finishEnvironments(o) - #if fn.name.s == "cbOuter": + #if fn.name.s == "parseLong": # echo rendertree(result, {renderIds}) proc liftLambdasForTopLevel*(module: PSym, body: PNode): PNode = diff --git a/compiler/lowerings.nim b/compiler/lowerings.nim index ddfcb4f011..e1fb09e449 100644 --- a/compiler/lowerings.nim +++ b/compiler/lowerings.nim @@ -56,6 +56,7 @@ proc lowerTupleUnpacking*(n: PNode; owner: PSym): PNode = result.add newAsgnStmt(newSymNode(temp), value) for i in 0 .. n.len-3: + if n.sons[i].kind == nkSym: v.addVar(n.sons[i]) result.add newAsgnStmt(n.sons[i], newTupleAccess(value, i)) proc createObj*(owner: PSym, info: TLineInfo): PType = From 63548f04b2d1793099813cf5ab888c580f8074a0 Mon Sep 17 00:00:00 2001 From: Araq Date: Thu, 11 Sep 2014 20:15:50 +0200 Subject: [PATCH 199/234] manual merge of #1526 --- lib/pure/times.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pure/times.nim b/lib/pure/times.nim index ebc3b9fdb8..8b33d2c738 100644 --- a/lib/pure/times.nim +++ b/lib/pure/times.nim @@ -513,7 +513,7 @@ elif defined(JS): result.setFullYear(timeInfo.year) result.setDate(timeInfo.monthday) - proc `$`(timeInfo: TTimeInfo): string = return $(TimeInfoToTIme(timeInfo)) + proc `$`(timeInfo: TTimeInfo): string = return $(timeInfoToTime(timeInfo)) proc `$`(time: TTime): string = return $time.toLocaleString() proc `-` (a, b: TTime): int64 = From 6a29fbf240e9395588dcf048ddd3037144c52e12 Mon Sep 17 00:00:00 2001 From: Araq Date: Thu, 11 Sep 2014 21:00:25 +0200 Subject: [PATCH 200/234] be explicit about single letter options --- doc/basicopt.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/basicopt.txt b/doc/basicopt.txt index fdb0e36e1c..3906238280 100644 --- a/doc/basicopt.txt +++ b/doc/basicopt.txt @@ -35,3 +35,5 @@ Options: -r, --run run the compiled program with given arguments --advanced show advanced command line switches -h, --help show this help + +Note: Even single letter options require the colon: -p:PATH. From 67525d7c1bd8c0e198f541fe9fc402843ca76df4 Mon Sep 17 00:00:00 2001 From: PavelVozenilek Date: Thu, 18 Sep 2014 17:07:52 +0200 Subject: [PATCH 201/234] more precise word --- doc/manual.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/manual.txt b/doc/manual.txt index 3af41faecf..ddc8c8d935 100644 --- a/doc/manual.txt +++ b/doc/manual.txt @@ -1449,7 +1449,7 @@ Examples: proc forEach(c: proc (x: int) {.cdecl.}) = ... - forEach(printItem) # this will NOT work because calling conventions differ + forEach(printItem) # this will NOT compile because calling conventions differ .. code-block:: nimrod From b11493585c5b677f8b84d83b0facb9ba5a7429cd Mon Sep 17 00:00:00 2001 From: Reimer Behrends Date: Thu, 18 Sep 2014 18:46:23 +0200 Subject: [PATCH 202/234] Various fixes to how the Boehm GC's interface. The Boehm GC interface did not define the getXXXSharedMem() functions that were needed for compilation with --threads:on. It also used `ppointer` instead of `PPointer`, so it failed to compile with --cs:partial. --- lib/system/mmdisp.nim | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/lib/system/mmdisp.nim b/lib/system/mmdisp.nim index a09b6cf934..606743f51a 100644 --- a/lib/system/mmdisp.nim +++ b/lib/system/mmdisp.nim @@ -131,6 +131,14 @@ when defined(boehmgc): if result == nil: raiseOutOfMem() proc deallocShared(p: pointer) = boehmDealloc(p) + when hasThreadSupport: + proc getFreeSharedMem(): int = + boehmGetFreeBytes() + proc getTotalSharedMem(): int = + boehmGetHeapSize() + proc getOccupiedSharedMem(): int = + getTotalSharedMem() - getFreeSharedMem() + #boehmGCincremental() proc GC_disable() = boehmGC_disable() @@ -164,11 +172,11 @@ when defined(boehmgc): proc nimGCref(p: pointer) {.compilerproc, inline.} = discard proc nimGCunref(p: pointer) {.compilerproc, inline.} = discard - proc unsureAsgnRef(dest: ppointer, src: pointer) {.compilerproc, inline.} = + proc unsureAsgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} = dest[] = src - proc asgnRef(dest: ppointer, src: pointer) {.compilerproc, inline.} = + proc asgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} = dest[] = src - proc asgnRefNoCycle(dest: ppointer, src: pointer) {.compilerproc, inline.} = + proc asgnRefNoCycle(dest: PPointer, src: pointer) {.compilerproc, inline.} = dest[] = src type @@ -180,7 +188,7 @@ when defined(boehmgc): proc alloc0(r: var TMemRegion, size: int): pointer = result = alloc(size) zeroMem(result, size) - proc dealloc(r: var TMemRegion, p: Pointer) = boehmDealloc(p) + proc dealloc(r: var TMemRegion, p: pointer) = boehmDealloc(p) proc deallocOsPages(r: var TMemRegion) {.inline.} = discard proc deallocOsPages() {.inline.} = discard @@ -239,11 +247,11 @@ elif defined(nogc) and defined(useMalloc): proc nimGCref(p: pointer) {.compilerproc, inline.} = discard proc nimGCunref(p: pointer) {.compilerproc, inline.} = discard - proc unsureAsgnRef(dest: ppointer, src: pointer) {.compilerproc, inline.} = + proc unsureAsgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} = dest[] = src - proc asgnRef(dest: ppointer, src: pointer) {.compilerproc, inline.} = + proc asgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} = dest[] = src - proc asgnRefNoCycle(dest: ppointer, src: pointer) {.compilerproc, inline.} = + proc asgnRefNoCycle(dest: PPointer, src: pointer) {.compilerproc, inline.} = dest[] = src type @@ -292,11 +300,11 @@ elif defined(nogc): proc nimGCref(p: pointer) {.compilerproc, inline.} = discard proc nimGCunref(p: pointer) {.compilerproc, inline.} = discard - proc unsureAsgnRef(dest: ppointer, src: pointer) {.compilerproc, inline.} = + proc unsureAsgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} = dest[] = src - proc asgnRef(dest: ppointer, src: pointer) {.compilerproc, inline.} = + proc asgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} = dest[] = src - proc asgnRefNoCycle(dest: ppointer, src: pointer) {.compilerproc, inline.} = + proc asgnRefNoCycle(dest: PPointer, src: pointer) {.compilerproc, inline.} = dest[] = src var allocator {.rtlThreadVar.}: TMemRegion From 80356f1cc76250706f23daa0c729c91127c4812b Mon Sep 17 00:00:00 2001 From: Reimer Behrends Date: Fri, 19 Sep 2014 03:34:00 +0200 Subject: [PATCH 203/234] Avoid unnecessary #include triggered by importc vars. When a C variable or macro is imported via an {.importc.} var or let statement, but no definition is needed and the variable does not have an initializer part, then there is also no need to generate an #include for the associated header until and unless the variable is actually used. The header is already generated upon use, but unnecessarily also when the variable is defined. This is an issue with the posix module in particular, where a lot of unnecessary header files are being included because relevant constants are defined via importc vars, and those header files may not even be available on a given system. This patch omits the generation of the #include directive for those definitions where they aren't needed. --- compiler/ccgstmts.nim | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index 3004e353bc..cb9eebb32f 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -171,6 +171,10 @@ proc genSingleVar(p: BProc, a: PNode) = if sfCompileTime in v.flags: return var targetProc = p if sfGlobal in v.flags: + if v.flags * {sfImportc, sfExportc} == {sfImportc} and + a.sons[2].kind == nkEmpty and + v.loc.flags * {lfHeader, lfNoDecl} != {}: + return if sfPure in v.flags: # v.owner.kind != skModule: targetProc = p.module.preInitProc From d0b292b4668e3837c090aefc056867f09fa92ee2 Mon Sep 17 00:00:00 2001 From: Reimer Behrends Date: Mon, 22 Sep 2014 23:18:14 +0200 Subject: [PATCH 204/234] Fix permissions for createDir() on Unix systems. Permissions were set to 0o711 by default; they should be 0o777, with umask being responsible for restricting permissions further. --- lib/pure/os.nim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/pure/os.nim b/lib/pure/os.nim index cfff58eb09..71089494f0 100644 --- a/lib/pure/os.nim +++ b/lib/pure/os.nim @@ -1332,10 +1332,10 @@ proc removeDir*(dir: string) {.rtl, extern: "nos$1", tags: [ proc rawCreateDir(dir: string) = when defined(solaris): - if mkdir(dir, 0o711) != 0'i32 and errno != EEXIST and errno != ENOSYS: + if mkdir(dir, 0o777) != 0'i32 and errno != EEXIST and errno != ENOSYS: osError(osLastError()) elif defined(unix): - if mkdir(dir, 0o711) != 0'i32 and errno != EEXIST: + if mkdir(dir, 0o777) != 0'i32 and errno != EEXIST: osError(osLastError()) else: when useWinUnicode: From f99c40f61bc47f98390aab42f686fcb697dc9ce8 Mon Sep 17 00:00:00 2001 From: Reimer Behrends Date: Thu, 25 Sep 2014 23:29:02 +0200 Subject: [PATCH 205/234] Improve setjmp()/longjmp() performance. Exception handling for the C backend used setjmp()/longjmp() unconditionally. However, on POSIX systems, these functions save and restore the signal mask, adding considerable overhead to exception handling, even where no exceptions are involved. The compiler and library now try to use either _setjmp()/_longjmp() or sigsetjmp()/siglongjmp() where possible, marked by the defines "nimRawSetjmp" and "nimSigSetjmp", respectively. The define "nimStdSetjmp" can be used to revert to setjmp()/longjmp() instead. --- compiler/ccgstmts.nim | 9 ++++++++- compiler/cgen.nim | 2 +- compiler/condsyms.nim | 2 ++ lib/system/ansi_c.nim | 21 +++++++++++++++++---- 4 files changed, 28 insertions(+), 6 deletions(-) diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index cb9eebb32f..8b0a8e9bb5 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -832,7 +832,14 @@ proc genTry(p: BProc, t: PNode, d: var TLoc) = discard cgsym(p.module, "E_Base") linefmt(p, cpsLocals, "#TSafePoint $1;$n", safePoint) linefmt(p, cpsStmts, "#pushSafePoint(&$1);$n", safePoint) - linefmt(p, cpsStmts, "$1.status = setjmp($1.context);$n", safePoint) + if isDefined("nimStdSetjmp"): + linefmt(p, cpsStmts, "$1.status = setjmp($1.context);$n", safePoint) + elif isDefined("nimSigSetjmp"): + linefmt(p, cpsStmts, "$1.status = sigsetjmp($1.context, 0);$n", safePoint) + elif isDefined("nimRawSetjmp"): + linefmt(p, cpsStmts, "$1.status = _setjmp($1.context);$n", safePoint) + else: + linefmt(p, cpsStmts, "$1.status = setjmp($1.context);$n", safePoint) startBlock(p, "if ($1.status == 0) {$n", [safePoint]) var length = sonsLen(t) add(p.nestedTryStmts, t) diff --git a/compiler/cgen.nim b/compiler/cgen.nim index 315b55801c..359fa33098 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -13,7 +13,7 @@ import ast, astalgo, strutils, hashes, trees, platform, magicsys, extccomp, options, intsets, nversion, nimsets, msgs, crc, bitsets, idents, lists, types, ccgutils, os, - times, ropes, math, passes, rodread, wordrecg, treetab, cgmeth, + times, ropes, math, passes, rodread, wordrecg, treetab, cgmeth, condsyms, rodutils, renderer, idgen, cgendata, ccgmerge, semfold, aliases, lowerings, semparallel diff --git a/compiler/condsyms.nim b/compiler/condsyms.nim index dc61d2f894..a2d8b35641 100644 --- a/compiler/condsyms.nim +++ b/compiler/condsyms.nim @@ -136,3 +136,5 @@ proc initDefines*() = declareSymbol("emulatedthreadvars") if platform.OS[targetOS].props.contains(ospLacksThreadVars): defineSymbol("emulatedthreadvars") + if isDefined("posix"): + defineSymbol("nimRawSetjmp") diff --git a/lib/system/ansi_c.nim b/lib/system/ansi_c.nim index e012697ae7..673d55582c 100644 --- a/lib/system/ansi_c.nim +++ b/lib/system/ansi_c.nim @@ -78,10 +78,23 @@ when defined(macosx): else: template SIGBUS: expr = SIGSEGV -proc c_longjmp(jmpb: C_JmpBuf, retval: cint) {. - header: "", importc: "longjmp".} -proc c_setjmp(jmpb: C_JmpBuf): cint {. - header: "", importc: "setjmp".} +when defined(nimSigSetjmp) and not defined(nimStdSetjmp): + proc c_longjmp(jmpb: C_JmpBuf, retval: cint) {. + header: "", importc: "siglongjmp".} + template c_setjmp(jmpb: C_JmpBuf): cint = + proc c_sigsetjmp(jmpb: C_JmpBuf, savemask: cint): cint {. + header: "", importc: "sigsetjmp".} + c_sigsetjmp(jmpb, 0) +elif defined(nimRawSetjmp) and not defined(nimStdSetjmp): + proc c_longjmp(jmpb: C_JmpBuf, retval: cint) {. + header: "", importc: "_longjmp".} + proc c_setjmp(jmpb: C_JmpBuf): cint {. + header: "", importc: "_setjmp".} +else: + proc c_longjmp(jmpb: C_JmpBuf, retval: cint) {. + header: "", importc: "longjmp".} + proc c_setjmp(jmpb: C_JmpBuf): cint {. + header: "", importc: "setjmp".} proc c_signal(sig: cint, handler: proc (a: cint) {.noconv.}) {. importc: "signal", header: "".} From cb6441e73d976dcf59b1e55236887fe5d3a1d6ec Mon Sep 17 00:00:00 2001 From: Reimer Behrends Date: Sat, 27 Sep 2014 18:05:30 +0200 Subject: [PATCH 206/234] Use _setjmp()/_longjmp() only on BSD-like systems for now. --- compiler/condsyms.nim | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/compiler/condsyms.nim b/compiler/condsyms.nim index a2d8b35641..238dbf5c79 100644 --- a/compiler/condsyms.nim +++ b/compiler/condsyms.nim @@ -136,5 +136,7 @@ proc initDefines*() = declareSymbol("emulatedthreadvars") if platform.OS[targetOS].props.contains(ospLacksThreadVars): defineSymbol("emulatedthreadvars") - if isDefined("posix"): + case targetOS + of osSolaris, osNetbsd, osFreebsd, osOpenbsd, osMacosx: defineSymbol("nimRawSetjmp") + else: discard From b234d311d49df927b709891f5f640b90cf982ee4 Mon Sep 17 00:00:00 2001 From: Varriount Date: Sun, 28 Sep 2014 15:35:35 -0400 Subject: [PATCH 207/234] Disable git hashing in the version command --- compiler/commands.nim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/commands.nim b/compiler/commands.nim index c15cc674ca..87e94d9c9d 100644 --- a/compiler/commands.nim +++ b/compiler/commands.nim @@ -80,9 +80,9 @@ proc writeVersionInfo(pass: TCmdLinePass) = platform.OS[platform.hostOS].name, CPU[platform.hostCPU].name])) - const gitHash = gorge("git log -n 1 --format=%H") + discard """const gitHash = gorge("git log -n 1 --format=%H") if gitHash.strip.len == 40: - msgWriteln("git hash: " & gitHash) + msgWriteln("git hash: " & gitHash)""" msgWriteln("active boot switches:" & usedRelease & usedAvoidTimeMachine & usedTinyC & usedGnuReadline & usedNativeStacktrace & usedNoCaas & From 93d55c077ffc9b9df381b4f921a16960c7141f19 Mon Sep 17 00:00:00 2001 From: Varriount Date: Sun, 28 Sep 2014 15:47:09 -0400 Subject: [PATCH 208/234] Updated Version Number --- compiler/nversion.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/nversion.nim b/compiler/nversion.nim index 3c868ed2af..bd1f79ac6b 100644 --- a/compiler/nversion.nim +++ b/compiler/nversion.nim @@ -14,7 +14,7 @@ const MaxSetElements* = 1 shl 16 # (2^16) to support unicode character sets? VersionMajor* = 0 VersionMinor* = 9 - VersionPatch* = 5 + VersionPatch* = 6 VersionAsString* = $VersionMajor & "." & $VersionMinor & "." & $VersionPatch RodFileVersion* = "1215" # modify this if the rod-format changes! From 55c78af9c0a7a63683ee49044ece0667f699adc8 Mon Sep 17 00:00:00 2001 From: Clay Sweetser Date: Wed, 1 Oct 2014 18:14:06 -0400 Subject: [PATCH 209/234] Fixes #1529 --- compiler/procfind.nim | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/compiler/procfind.nim b/compiler/procfind.nim index 0354d585d3..9f52cc117c 100644 --- a/compiler/procfind.nim +++ b/compiler/procfind.nim @@ -70,8 +70,15 @@ proc searchForProcNew(c: PContext, scope: PScope, fn: PSym): PSym = var it: TIdentIter result = initIdentIter(it, scope.symbols, fn.name) while result != nil: - if result.kind in skProcKinds and - sameType(result.typ, fn.typ, flags): return + if result.kind in skProcKinds and sameType(result.typ, fn.typ, flags): + case equalParams(result.typ.n, fn.typ.n) + of paramsEqual: + return + of paramsIncompatible: + localError(fn.info, errNotOverloadable, fn.name.s) + return + of paramsNotEqual: + discard result = nextIdentIter(it, scope.symbols) From 3df37a79237be4ac16c745a1c500d029b7d8ff1b Mon Sep 17 00:00:00 2001 From: Simon Krauter Date: Sun, 5 Oct 2014 00:26:22 +0200 Subject: [PATCH 210/234] Fixed missing color definion --- doc/nimdoc.css | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/nimdoc.css b/doc/nimdoc.css index 6154f0b2eb..e3bab07de3 100644 --- a/doc/nimdoc.css +++ b/doc/nimdoc.css @@ -16,6 +16,11 @@ customize this style sheet. Andreas Rumpf */ +body { + color: black; + background: white; +} + /* used to remove borders from tables and images */ .borderless, table.borderless td, table.borderless th { border: 0 } From 1da251523fb5e09d1edcd1ff37c2c993ec26273b Mon Sep 17 00:00:00 2001 From: Araq Date: Sun, 5 Oct 2014 02:22:48 +0200 Subject: [PATCH 211/234] added 'nim*Setjmp' conditional symbols --- compiler/condsyms.nim | 2 ++ 1 file changed, 2 insertions(+) diff --git a/compiler/condsyms.nim b/compiler/condsyms.nim index 238dbf5c79..2c493c7d01 100644 --- a/compiler/condsyms.nim +++ b/compiler/condsyms.nim @@ -69,6 +69,8 @@ const reportMissedDeadlines avoidTimeMachine useClone ignoreAllocationSize debugExecProcesses pcreDll useLipzipSrc preventDeadlocks UNICODE winUnicode trackGcHeaders posixRealtime + + nimSigSetjmp nimStdSetjmp nimRawSetjmp """.split proc initDefines*() = From 54f6280d7659ce057a64cd9878a17c26065a7321 Mon Sep 17 00:00:00 2001 From: Luis Ricardo Date: Tue, 7 Oct 2014 17:02:50 -0400 Subject: [PATCH 212/234] Update cpuinfo.nim sys/types.h needed for macosx and freebsd sys/param.h needed for openbsd and netbsd --- lib/pure/concurrency/cpuinfo.nim | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/pure/concurrency/cpuinfo.nim b/lib/pure/concurrency/cpuinfo.nim index dfa819f646..cd8e5b14a6 100644 --- a/lib/pure/concurrency/cpuinfo.nim +++ b/lib/pure/concurrency/cpuinfo.nim @@ -18,15 +18,22 @@ when not defined(windows): when defined(linux): import linux + +when defined(freebsd) or defined(macosx): + {.emit:"#include ".} + +when defined(openbsd) or defined(netbsd): + {.emit:"#include ".} when defined(macosx) or defined(bsd): + {.emit:"#include ".} const CTL_HW = 6 HW_AVAILCPU = 25 HW_NCPU = 3 proc sysctl(x: ptr array[0..3, cint], y: cint, z: pointer, a: var csize, b: pointer, c: int): cint {. - importc: "sysctl", header: "".} + importc: "sysctl".} proc countProcessors*(): int {.rtl, extern: "ncpi$1".} = ## returns the numer of the processors/cores the machine has. From fa3545c092522a43517669387ad2a953a4a2fd04 Mon Sep 17 00:00:00 2001 From: Simon Krauter Date: Fri, 10 Oct 2014 23:24:28 +0200 Subject: [PATCH 213/234] Raise exception on adding a non-existent file to a zip archive --- lib/impure/zipfiles.nim | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/impure/zipfiles.nim b/lib/impure/zipfiles.nim index 1726449d8a..63b8a843db 100644 --- a/lib/impure/zipfiles.nim +++ b/lib/impure/zipfiles.nim @@ -56,6 +56,11 @@ proc addFile*(z: var TZipArchive, dest, src: string) = ## Adds the file `src` to the archive `z` with the name `dest`. `dest` ## may contain a path that will be created. assert(z.mode != fmRead) + if not fileExists(src): + var e: ref EIO + new(e) + e.msg = "File does not exist" + raise e var zipsrc = zip_source_file(z.w, src, 0, -1) if zipsrc == nil: #echo("Dest: " & dest) From d526e051c516ced3533f421637ca2ea3c11e03db Mon Sep 17 00:00:00 2001 From: Simon Krauter Date: Sat, 11 Oct 2014 00:20:49 +0200 Subject: [PATCH 214/234] Code more cleaner --- lib/impure/zipfiles.nim | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/impure/zipfiles.nim b/lib/impure/zipfiles.nim index 63b8a843db..b9f89dda08 100644 --- a/lib/impure/zipfiles.nim +++ b/lib/impure/zipfiles.nim @@ -57,10 +57,7 @@ proc addFile*(z: var TZipArchive, dest, src: string) = ## may contain a path that will be created. assert(z.mode != fmRead) if not fileExists(src): - var e: ref EIO - new(e) - e.msg = "File does not exist" - raise e + raise newException(EIO, "File '" & src & "' does not exist") var zipsrc = zip_source_file(z.w, src, 0, -1) if zipsrc == nil: #echo("Dest: " & dest) From 6c9730b3534927ac2bdd4ec7c77e0d37bba7aa2e Mon Sep 17 00:00:00 2001 From: Araq Date: Sat, 11 Oct 2014 12:25:15 +0200 Subject: [PATCH 215/234] fixes #1551 --- compiler/semexprs.nim | 5 +++++ lib/pure/concurrency/threadpool.nim | 6 +++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index ff445ecd09..46e6f1ab3c 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -1614,6 +1614,11 @@ proc instantiateCreateFlowVarCall(c: PContext; t: PType; initIdTable(bindings) bindings.idTablePut(sym.ast[genericParamsPos].sons[0].typ, t) result = c.semGenerateInstance(c, sym, bindings, info) + # since it's an instantiation, we unmark it as a compilerproc. Otherwise + # codegen would fail: + if sfCompilerProc in result.flags: + result.flags = result.flags - {sfCompilerProc, sfExportC, sfImportC} + result.loc.r = nil proc setMs(n: PNode, s: PSym): PNode = result = n diff --git a/lib/pure/concurrency/threadpool.nim b/lib/pure/concurrency/threadpool.nim index e0a2ac6782..f46822d941 100644 --- a/lib/pure/concurrency/threadpool.nim +++ b/lib/pure/concurrency/threadpool.nim @@ -95,7 +95,7 @@ type FlowVarBase* = ref FlowVarBaseObj ## untyped base class for 'FlowVar[T]' FlowVarBaseObj = object of TObject - ready, usesCondVar: bool + ready, usesCondVar, awaited: bool cv: CondVar #\ # for 'awaitAny' support ai: ptr AwaitInfo @@ -129,8 +129,8 @@ type proc await*(fv: FlowVarBase) = ## waits until the value for the flowVar arrives. Usually it is not necessary ## to call this explicitly. - if fv.usesCondVar: - fv.usesCondVar = false + if fv.usesCondVar and not fv.awaited: + fv.awaited = true await(fv.cv) destroyCondVar(fv.cv) From 753d18d66c978b192b5c4fcf9b86c755c3fa9266 Mon Sep 17 00:00:00 2001 From: Araq Date: Sat, 11 Oct 2014 13:16:51 +0200 Subject: [PATCH 216/234] minor cleanup for cpuinfo --- lib/pure/concurrency/cpuinfo.nim | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/pure/concurrency/cpuinfo.nim b/lib/pure/concurrency/cpuinfo.nim index cd8e5b14a6..bd10a416fd 100644 --- a/lib/pure/concurrency/cpuinfo.nim +++ b/lib/pure/concurrency/cpuinfo.nim @@ -26,14 +26,13 @@ when defined(openbsd) or defined(netbsd): {.emit:"#include ".} when defined(macosx) or defined(bsd): - {.emit:"#include ".} const CTL_HW = 6 HW_AVAILCPU = 25 HW_NCPU = 3 proc sysctl(x: ptr array[0..3, cint], y: cint, z: pointer, a: var csize, b: pointer, c: int): cint {. - importc: "sysctl".} + importc: "sysctl", header: "".} proc countProcessors*(): int {.rtl, extern: "ncpi$1".} = ## returns the numer of the processors/cores the machine has. From 028a62e2bae3944a489904ae2d926408fc3f46ec Mon Sep 17 00:00:00 2001 From: Araq Date: Sat, 11 Oct 2014 13:20:00 +0200 Subject: [PATCH 217/234] documentation updates --- doc/manual.txt | 21 +++++++++++++ web/news.txt | 85 +++++++++++++++++++++++++++----------------------- 2 files changed, 67 insertions(+), 39 deletions(-) diff --git a/doc/manual.txt b/doc/manual.txt index 7b713bf939..6aed72ce75 100644 --- a/doc/manual.txt +++ b/doc/manual.txt @@ -5039,6 +5039,27 @@ first implementation to play with a language feature before a nicer syntax to access the feature becomes available. +deprecated pragma +----------------- + +The deprecated pragma is used to mark a symbol as deprecated: + +.. code-block:: nimrod + proc p() {.deprecated.} + var x {.deprecated.}: char + +It can also be used as a statement. Then it takes a list of *renamings*. The +upcoming ``nimfix`` tool can automatically update the code and perform these +renamings: + +.. code-block:: nimrod + type + File = object + Stream = ref object + {.deprecated: [TFile: File, PStream: Stream].} + + + noSideEffect pragma ------------------- The ``noSideEffect`` pragma is used to mark a proc/iterator to have no side diff --git a/web/news.txt b/web/news.txt index 2d7086be6d..efef33e421 100644 --- a/web/news.txt +++ b/web/news.txt @@ -2,51 +2,58 @@ News ==== -.. - 2014-06-29 Version 0.9.6 released - ================================= +2014-10-11 Version 0.9.6 released +================================= - Changes affecting backwards compatibility - ----------------------------------------- +**Note: This is the last release of Nimrod. The language has been renamed to +Nim. Nim slightly breaks compatibility.** - - ``spawn`` now uses an elaborate self-adapting thread pool and as such - has been moved into its own module. So to use it, you now have to import - ``threadpool``. - - The symbol binding rules in generics changed: ``bar`` in ``foo.bar`` is - now considered for implicit early binding. - - ``c2nim`` moved into its own repository and is now a Babel package. - - ``pas2nim`` moved into its own repository and is now a Babel package. - - ``system.$`` for floating point types now produces a human friendly string - representation. - - ``uri.TUrl`` as well as the ``parseurl`` module are now deprecated in favour - of the new ``TUri`` type in the ``uri`` module. - - The ``destructor`` pragma has been deprecated. Use the ``override`` pragma - instead. The destructor's name has to be ``destroy`` now. - - ``lambda`` is not a keyword anymore. - - **system.defined has been split into system.defined and system.declared**. - You have to use ``--symbol`` to declare new conditional symbols that can be - set via ``--define``. - - ``--threadanalysis:on`` is now the default. To make your program compile - you can disable it but this is only a temporary solution as this option - will disappear soon! - +This is a maintenance release. The upcoming 0.10.0 release has all +the new features and exciting developments. - Language Additions - ------------------ - - There is a new ``parallel`` statement for safe fork&join parallel computing. - +Changes affecting backwards compatibility +----------------------------------------- - Library Additions - ----------------- +- ``spawn`` now uses an elaborate self-adapting thread pool and as such + has been moved into its own module. So to use it, you now have to import + ``threadpool``. +- The symbol binding rules in generics changed: ``bar`` in ``foo.bar`` is + now considered for implicit early binding. +- ``c2nim`` moved into its own repository and is now a Babel package. +- ``pas2nim`` moved into its own repository and is now a Babel package. +- ``system.$`` for floating point types now produces a human friendly string + representation. +- ``uri.TUrl`` as well as the ``parseurl`` module are now deprecated in favour + of the new ``TUri`` type in the ``uri`` module. +- The ``destructor`` pragma has been deprecated. Use the ``override`` pragma + instead. The destructor's name has to be ``destroy`` now. +- ``lambda`` is not a keyword anymore. +- **system.defined has been split into system.defined and system.declared**. + You have to use ``--symbol`` to declare new conditional symbols that can be + set via ``--define``. +- ``--threadanalysis:on`` is now the default. To make your program compile + you can disable it but this is only a temporary solution as this option + will disappear soon! - - Added module ``cpuinfo``. - - Added module ``threadpool``. - - ``sequtils.distnct`` has been renamed to ``sequtils.deduplicate``. - - Added ``algorithm.reversed`` - - Added ``uri.combine`` and ``uri.parseUri``. - - Some sockets procedures now support a ``SafeDisconn`` flag which causes - them to handle disconnection errors and not raise them. + +Language Additions +------------------ + +- This version introduces the new ``deprecated`` pragma statement that is used + to handle the upcoming massive amount of symbol renames. + + +Library Additions +----------------- + +- Added module ``cpuinfo``. +- Added module ``threadpool``. +- ``sequtils.distnct`` has been renamed to ``sequtils.deduplicate``. +- Added ``algorithm.reversed`` +- Added ``uri.combine`` and ``uri.parseUri``. +- Some sockets procedures now support a ``SafeDisconn`` flag which causes + them to handle disconnection errors and not raise them. 2014-04-21 Version 0.9.4 released From 661c51682a9a842e6da181a2a52dae0ec40c0002 Mon Sep 17 00:00:00 2001 From: Araq Date: Sat, 11 Oct 2014 20:31:24 +0200 Subject: [PATCH 218/234] backported .deprecated statement --- compiler/ast.nim | 23 ++++--- compiler/condsyms.nim | 7 ++- compiler/lookups.nim | 136 +++++++++++++++++++++++++----------------- compiler/pragmas.nim | 113 ++++++++++++++++++++--------------- compiler/sempass2.nim | 20 +------ compiler/wordrecg.nim | 4 +- 6 files changed, 169 insertions(+), 134 deletions(-) diff --git a/compiler/ast.nim b/compiler/ast.nim index 7ad2946957..0c828a6d9b 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -1,6 +1,6 @@ # # -# The Nimrod Compiler +# The Nim Compiler # (c) Copyright 2013 Andreas Rumpf # # See the file "copying.txt", included in this @@ -291,6 +291,8 @@ const sfNoRoot* = sfBorrow # a local variable is provably no root so it doesn't # require RC ops + sfCompileToCpp* = sfInfixCall # compile the module as C++ code + sfCompileToObjc* = sfNamedParamCall # compile the module as Objective-C code const # getting ready for the future expr/stmt merge @@ -476,7 +478,7 @@ type # and first phase symbol lookup in generics skConditional, # symbol for the preprocessor (may become obsolete) skDynLib, # symbol represents a dynamic library; this is used - # internally; it does not exist in Nimrod code + # internally; it does not exist in Nim code skParam, # a parameter skGenericParam, # a generic parameter; eq in ``proc x[eq=`==`]()`` skTemp, # a temporary variable (introduced by compiler) @@ -501,7 +503,8 @@ type skStub, # symbol is a stub and not yet loaded from the ROD # file (it is loaded on demand, which may # mean: never) - skPackage # symbol is a package (used for canonicalization) + skPackage, # symbol is a package (used for canonicalization) + skAlias # an alias (needs to be resolved immediately) TSymKinds* = set[TSymKind] const @@ -678,7 +681,7 @@ type heapRoot*: PRope # keeps track of the enclosing heap object that # owns this location (required by GC algorithms # employing heap snapshots or sliding views) - a*: int # location's "address", i.e. slot for temporaries + a*: int # ---------------- end of backend information ------------------------------ @@ -731,8 +734,9 @@ type # check for the owner when touching 'usedGenerics'. usedGenerics*: seq[PInstantiation] tab*: TStrTable # interface table for modules + of skLet, skVar, skField: + guard*: PSym else: nil - magic*: TMagic typ*: PType name*: PIdent @@ -872,7 +876,7 @@ const tyProc, tyString, tyError} ExportableSymKinds* = {skVar, skConst, skProc, skMethod, skType, skIterator, skClosureIterator, - skMacro, skTemplate, skConverter, skEnumField, skLet, skStub} + skMacro, skTemplate, skConverter, skEnumField, skLet, skStub, skAlias} PersistentNodeFlags*: TNodeFlags = {nfBase2, nfBase8, nfBase16, nfDotSetter, nfDotField, nfIsRef} @@ -1162,7 +1166,6 @@ proc newProcNode*(kind: TNodeKind, info: TLineInfo, body: PNode, result.sons = @[name, pattern, genericParams, params, pragmas, exceptions, body] - proc newType(kind: TTypeKind, owner: PSym): PType = new(result) result.kind = kind @@ -1172,8 +1175,8 @@ proc newType(kind: TTypeKind, owner: PSym): PType = result.id = getID() when debugIds: registerId(result) - #if result.id < 2000 then - # MessageOut(typeKindToStr[kind] & ' has id: ' & toString(result.id)) + #if result.id < 2000: + # messageOut(typeKindToStr[kind] & ' has id: ' & toString(result.id)) proc mergeLoc(a: var TLoc, b: TLoc) = if a.k == low(a.k): a.k = b.k @@ -1229,6 +1232,8 @@ proc copySym(s: PSym, keepId: bool = false): PSym = result.position = s.position result.loc = s.loc result.annex = s.annex # BUGFIX + if result.kind in {skVar, skLet, skField}: + result.guard = s.guard proc createModuleAlias*(s: PSym, newIdent: PIdent, info: TLineInfo): PSym = result = newSym(s.kind, newIdent, s.owner, info) diff --git a/compiler/condsyms.nim b/compiler/condsyms.nim index 2c493c7d01..6d144ad96e 100644 --- a/compiler/condsyms.nim +++ b/compiler/condsyms.nim @@ -1,6 +1,6 @@ # # -# The Nimrod Compiler +# The Nim Compiler # (c) Copyright 2014 Andreas Rumpf # # See the file "copying.txt", included in this @@ -60,7 +60,7 @@ const quick release debug useWinAnsi useFork useNimRtl useMalloc useRealtimeGC ssl memProfiler - nodejs kwin + nodejs kwin nimfix usesysassert usegcassert tinyC useFFI useStdoutAsStdmsg createNimRtl @@ -70,7 +70,7 @@ const debugExecProcesses pcreDll useLipzipSrc preventDeadlocks UNICODE winUnicode trackGcHeaders posixRealtime - nimSigSetjmp nimStdSetjmp nimRawSetjmp + nimStdSetjmp nimRawSetjmp nimSigSetjmp """.split proc initDefines*() = @@ -87,6 +87,7 @@ proc initDefines*() = defineSymbol("nimnewshared") defineSymbol("nimrequiresnimframe") defineSymbol("nimparsebiggestfloatmagic") + defineSymbol("nimalias") # add platform specific symbols: for c in low(CPU)..high(CPU): diff --git a/compiler/lookups.nim b/compiler/lookups.nim index aee64f52f1..d486585efc 100644 --- a/compiler/lookups.nim +++ b/compiler/lookups.nim @@ -1,6 +1,6 @@ # # -# The Nimrod Compiler +# The Nim Compiler # (c) Copyright 2012 Andreas Rumpf # # See the file "copying.txt", included in this @@ -11,7 +11,7 @@ import intsets, ast, astalgo, idents, semdata, types, msgs, options, rodread, - renderer, wordrecg, idgen + renderer, wordrecg, idgen, nimfix.prettybase proc ensureNoMissingOrUnusedSymbols(scope: PScope) @@ -40,11 +40,8 @@ proc considerQuotedIdent*(n: PNode): PIdent = template addSym*(scope: PScope, s: PSym) = strTableAdd(scope.symbols, s) -proc addUniqueSym*(scope: PScope, s: PSym): TResult = - if strTableIncl(scope.symbols, s): - result = Failure - else: - result = Success +proc addUniqueSym*(scope: PScope, s: PSym): bool = + result = not strTableIncl(scope.symbols, s) proc openScope*(c: PContext): PScope {.discardable.} = result = PScope(parent: c.currentScope, @@ -65,6 +62,17 @@ iterator walkScopes*(scope: PScope): PScope = yield current current = current.parent +proc skipAlias*(s: PSym; n: PNode): PSym = + if s == nil or s.kind != skAlias: + result = s + else: + result = s.owner + if gCmd == cmdPretty: + prettybase.replaceDeprecated(n.info, s, result) + else: + message(n.info, warnDeprecated, "use " & result.name.s & " instead; " & + s.name.s) + proc localSearchInScope*(c: PContext, s: PIdent): PSym = result = strTableGet(c.currentScope.symbols, s) @@ -139,14 +147,14 @@ proc wrongRedefinition*(info: TLineInfo, s: string) = localError(info, errAttemptToRedefine, s) proc addDecl*(c: PContext, sym: PSym) = - if c.currentScope.addUniqueSym(sym) == Failure: + if not c.currentScope.addUniqueSym(sym): wrongRedefinition(sym.info, sym.name.s) proc addPrelimDecl*(c: PContext, sym: PSym) = discard c.currentScope.addUniqueSym(sym) proc addDeclAt*(scope: PScope, sym: PSym) = - if scope.addUniqueSym(sym) == Failure: + if not scope.addUniqueSym(sym): wrongRedefinition(sym.info, sym.name.s) proc addInterfaceDeclAux(c: PContext, sym: PSym) = @@ -163,7 +171,7 @@ proc addOverloadableSymAt*(scope: PScope, fn: PSym) = if fn.kind notin OverloadableSyms: internalError(fn.info, "addOverloadableSymAt") return - var check = strTableGet(scope.symbols, fn.name) + let check = strTableGet(scope.symbols, fn.name) if check != nil and check.kind notin OverloadableSyms: wrongRedefinition(fn.info, fn.name.s) else: @@ -179,20 +187,41 @@ proc addInterfaceOverloadableSymAt*(c: PContext, scope: PScope, sym: PSym) = addOverloadableSymAt(scope, sym) addInterfaceDeclAux(c, sym) +when defined(nimfix): + import strutils + + # when we cannot find the identifier, retry with a changed identifer: + proc altSpelling(x: PIdent): PIdent = + case x.s[0] + of 'A'..'Z': result = getIdent(toLower(x.s[0]) & x.s.substr(1)) + of 'a'..'z': result = getIdent(toLower(x.s[0]) & x.s.substr(1)) + else: result = x + + template fixSpelling(n: PNode; ident: PIdent; op: expr) = + let alt = ident.altSpelling + result = op(c, alt).skipAlias(n) + if result != nil: + prettybase.replaceDeprecated(n.info, ident, alt) + return result +else: + template fixSpelling(n: PNode; ident: PIdent; op: expr) = discard + proc lookUp*(c: PContext, n: PNode): PSym = # Looks up a symbol. Generates an error in case of nil. case n.kind of nkIdent: - result = searchInScopes(c, n.ident) - if result == nil: + result = searchInScopes(c, n.ident).skipAlias(n) + if result == nil: + fixSpelling(n, n.ident, searchInScopes) localError(n.info, errUndeclaredIdentifier, n.ident.s) result = errorSym(c, n) of nkSym: result = n.sym of nkAccQuoted: var ident = considerQuotedIdent(n) - result = searchInScopes(c, ident) + result = searchInScopes(c, ident).skipAlias(n) if result == nil: + fixSpelling(n, ident, searchInScopes) localError(n.info, errUndeclaredIdentifier, ident.s) result = errorSym(c, n) else: @@ -206,36 +235,38 @@ type TLookupFlag* = enum checkAmbiguity, checkUndeclared -proc qualifiedLookUp*(c: PContext, n: PNode, flags = {checkUndeclared}): PSym = +proc qualifiedLookUp*(c: PContext, n: PNode, flags = {checkUndeclared}): PSym = case n.kind of nkIdent, nkAccQuoted: var ident = considerQuotedIdent(n) - result = searchInScopes(c, ident) - if result == nil and checkUndeclared in flags: + result = searchInScopes(c, ident).skipAlias(n) + if result == nil and checkUndeclared in flags: + fixSpelling(n, ident, searchInScopes) localError(n.info, errUndeclaredIdentifier, ident.s) result = errorSym(c, n) - elif checkAmbiguity in flags and result != nil and - contains(c.ambiguousSymbols, result.id): + elif checkAmbiguity in flags and result != nil and + contains(c.ambiguousSymbols, result.id): localError(n.info, errUseQualifier, ident.s) of nkSym: result = n.sym - if checkAmbiguity in flags and contains(c.ambiguousSymbols, result.id): + if checkAmbiguity in flags and contains(c.ambiguousSymbols, result.id): localError(n.info, errUseQualifier, n.sym.name.s) - of nkDotExpr: + of nkDotExpr: result = nil var m = qualifiedLookUp(c, n.sons[0], flags*{checkUndeclared}) - if (m != nil) and (m.kind == skModule): + if m != nil and m.kind == skModule: var ident: PIdent = nil - if n.sons[1].kind == nkIdent: + if n.sons[1].kind == nkIdent: ident = n.sons[1].ident - elif n.sons[1].kind == nkAccQuoted: + elif n.sons[1].kind == nkAccQuoted: ident = considerQuotedIdent(n.sons[1]) - if ident != nil: - if m == c.module: - result = strTableGet(c.topLevelScope.symbols, ident) - else: - result = strTableGet(m.tab, ident) - if result == nil and checkUndeclared in flags: + if ident != nil: + if m == c.module: + result = strTableGet(c.topLevelScope.symbols, ident).skipAlias(n) + else: + result = strTableGet(m.tab, ident).skipAlias(n) + if result == nil and checkUndeclared in flags: + fixSpelling(n.sons[1], ident, searchInScopes) localError(n.sons[1].info, errUndeclaredIdentifier, ident.s) result = errorSym(c, n.sons[1]) elif n.sons[1].kind == nkSym: @@ -256,7 +287,7 @@ proc initOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym = o.scope = c.currentScope o.mode = oimNoQualifier while true: - result = initIdentIter(o.it, o.scope.symbols, ident) + result = initIdentIter(o.it, o.scope.symbols, ident).skipAlias(n) if result != nil: break else: @@ -277,11 +308,12 @@ proc initOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym = if ident != nil: if o.m == c.module: # a module may access its private members: - result = initIdentIter(o.it, c.topLevelScope.symbols, ident) + result = initIdentIter(o.it, c.topLevelScope.symbols, + ident).skipAlias(n) o.mode = oimSelfModule - else: - result = initIdentIter(o.it, o.m.tab, ident) - else: + else: + result = initIdentIter(o.it, o.m.tab, ident).skipAlias(n) + else: localError(n.sons[1].info, errIdentifierExpected, renderTree(n.sons[1])) result = errorSym(c, n.sons[1]) @@ -307,18 +339,18 @@ proc nextOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym = result = nil of oimNoQualifier: if o.scope != nil: - result = nextIdentIter(o.it, o.scope.symbols) + result = nextIdentIter(o.it, o.scope.symbols).skipAlias(n) while result == nil: o.scope = o.scope.parent if o.scope == nil: break - result = initIdentIter(o.it, o.scope.symbols, o.it.name) + result = initIdentIter(o.it, o.scope.symbols, o.it.name).skipAlias(n) # BUGFIX: o.it.name <-> n.ident else: result = nil of oimSelfModule: - result = nextIdentIter(o.it, c.topLevelScope.symbols) + result = nextIdentIter(o.it, c.topLevelScope.symbols).skipAlias(n) of oimOtherModule: - result = nextIdentIter(o.it, o.m.tab) + result = nextIdentIter(o.it, o.m.tab).skipAlias(n) of oimSymChoice: if o.symChoiceIndex < sonsLen(n): result = n.sons[o.symChoiceIndex].sym @@ -329,31 +361,27 @@ proc nextOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym = o.mode = oimSymChoiceLocalLookup o.scope = c.currentScope result = firstIdentExcluding(o.it, o.scope.symbols, - n.sons[0].sym.name, o.inSymChoice) + n.sons[0].sym.name, o.inSymChoice).skipAlias(n) while result == nil: o.scope = o.scope.parent if o.scope == nil: break result = firstIdentExcluding(o.it, o.scope.symbols, - n.sons[0].sym.name, o.inSymChoice) + n.sons[0].sym.name, o.inSymChoice).skipAlias(n) of oimSymChoiceLocalLookup: - result = nextIdentExcluding(o.it, o.scope.symbols, o.inSymChoice) + result = nextIdentExcluding(o.it, o.scope.symbols, o.inSymChoice).skipAlias(n) while result == nil: o.scope = o.scope.parent if o.scope == nil: break result = firstIdentExcluding(o.it, o.scope.symbols, - n.sons[0].sym.name, o.inSymChoice) + n.sons[0].sym.name, o.inSymChoice).skipAlias(n) if result != nil and result.kind == skStub: loadStub(result) -when false: - proc qualifiedLookUpPreferImmediate*(c: PContext, n: PNode, - flags = {checkUndeclared}): PSym = - var o: TOverloadIter - result = initOverloadIter(o, c, n) - var a = result - while a != nil: - if sfImmediate in a.flags: return a - a = nextOverloadIter(o, c, n) - if result == nil and checkUndeclared in flags: - localError(n.info, errUndeclaredIdentifier, n.considerQuotedIdent.s) - result = errorSym(c, n) +proc pickSym*(c: PContext, n: PNode; kind: TSymKind; + flags: TSymFlags = {}): PSym = + var o: TOverloadIter + var a = initOverloadIter(o, c, n) + while a != nil: + if a.kind == kind and flags <= a.flags: + return a + a = nextOverloadIter(o, c, n) diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index 024401b863..d73494c6e0 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -1,6 +1,6 @@ # # -# The Nimrod Compiler +# The Nim Compiler # (c) Copyright 2014 Andreas Rumpf # # See the file "copying.txt", included in this @@ -24,7 +24,7 @@ const wCompilerproc, wProcVar, wDeprecated, wVarargs, wCompileTime, wMerge, wBorrow, wExtern, wImportCompilerProc, wThread, wImportCpp, wImportObjC, wAsmNoStackFrame, wError, wDiscardable, wNoInit, wDestructor, wCodegenDecl, - wGensym, wInject, wRaises, wTags, wUses, wOperator, wDelegator, wGcSafe, + wGensym, wInject, wRaises, wTags, wLocks, wDelegator, wGcSafe, wOverride} converterPragmas* = procPragmas methodPragmas* = procPragmas @@ -36,8 +36,8 @@ const iteratorPragmas* = {FirstCallConv..LastCallConv, wNosideeffect, wSideeffect, wImportc, wExportc, wNodecl, wMagic, wDeprecated, wBorrow, wExtern, wImportCpp, wImportObjC, wError, wDiscardable, wGensym, wInject, wRaises, - wTags, wUses, wOperator, wGcSafe} - exprPragmas* = {wLine} + wTags, wLocks, wGcSafe} + exprPragmas* = {wLine, wLocks} stmtPragmas* = {wChecks, wObjChecks, wFieldChecks, wRangechecks, wBoundchecks, wOverflowchecks, wNilchecks, wAssertions, wWarnings, wHints, wLinedir, wStacktrace, wLinetrace, wOptimization, wHint, wWarning, wError, @@ -45,27 +45,27 @@ const wBreakpoint, wWatchPoint, wPassl, wPassc, wDeadCodeElim, wDeprecated, wFloatchecks, wInfChecks, wNanChecks, wPragma, wEmit, wUnroll, wLinearScanEnd, wPatterns, wEffects, wNoForward, wComputedGoto, - wInjectStmt} + wInjectStmt, wDeprecated} lambdaPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl, wNosideeffect, wSideeffect, wNoreturn, wDynlib, wHeader, wDeprecated, wExtern, wThread, wImportCpp, wImportObjC, wAsmNoStackFrame, - wRaises, wUses, wTags, wGcSafe} + wRaises, wLocks, wTags, wGcSafe} typePragmas* = {wImportc, wExportc, wDeprecated, wMagic, wAcyclic, wNodecl, wPure, wHeader, wCompilerproc, wFinal, wSize, wExtern, wShallow, wImportCpp, wImportObjC, wError, wIncompleteStruct, wByCopy, wByRef, wInheritable, wGensym, wInject, wRequiresInit, wUnchecked, wUnion, wPacked, wBorrow, wGcSafe} fieldPragmas* = {wImportc, wExportc, wDeprecated, wExtern, - wImportCpp, wImportObjC, wError} + wImportCpp, wImportObjC, wError, wGuard} varPragmas* = {wImportc, wExportc, wVolatile, wRegister, wThreadVar, wNodecl, wMagic, wHeader, wDeprecated, wCompilerproc, wDynlib, wExtern, wImportCpp, wImportObjC, wError, wNoInit, wCompileTime, wGlobal, - wGensym, wInject, wCodegenDecl} + wGensym, wInject, wCodegenDecl, wGuard} constPragmas* = {wImportc, wExportc, wHeader, wDeprecated, wMagic, wNodecl, wExtern, wImportCpp, wImportObjC, wError, wGensym, wInject} letPragmas* = varPragmas procTypePragmas* = {FirstCallConv..LastCallConv, wVarargs, wNosideeffect, - wThread, wRaises, wUses, wTags, wGcSafe} + wThread, wRaises, wLocks, wTags, wGcSafe} allRoutinePragmas* = procPragmas + iteratorPragmas + lambdaPragmas proc pragma*(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) @@ -128,12 +128,16 @@ proc processImportCpp(s: PSym, extname: string) = incl(s.flags, sfImportc) incl(s.flags, sfInfixCall) excl(s.flags, sfForward) + let m = s.getModule() + incl(m.flags, sfCompileToCpp) proc processImportObjC(s: PSym, extname: string) = setExternName(s, extname) incl(s.flags, sfImportc) incl(s.flags, sfNamedParamCall) excl(s.flags, sfForward) + let m = s.getModule() + incl(m.flags, sfCompileToObjC) proc newEmptyStrNode(n: PNode): PNode {.noinline.} = result = newNodeIT(nkStrLit, n.info, getSysType(tyString)) @@ -514,27 +518,6 @@ proc pragmaRaisesOrTags(c: PContext, n: PNode) = else: invalidPragma(n) -proc pragmaUses(c: PContext, n: PNode) = - proc processExc(c: PContext, x: PNode): PNode = - if x.kind in {nkAccQuoted, nkIdent, nkSym, - nkOpenSymChoice, nkClosedSymChoice}: - if considerQuotedIdent(x).s == "*": - return newSymNode(ast.anyGlobal) - result = c.semExpr(c, x) - if result.kind != nkSym or sfGlobal notin result.sym.flags: - localError(x.info, "'$1' is not a global variable" % result.renderTree) - result = newSymNode(ast.anyGlobal) - - if n.kind == nkExprColonExpr: - let it = n.sons[1] - if it.kind notin {nkCurly, nkBracket}: - n.sons[1] = processExc(c, it) - else: - for i in 0 .. % high(int16): localError(it.info, errPowerOfTwoExpected) else: - sym.typ.align = align - of wSize: + sym.typ.align = align.int16 + of wSize: if sym.typ == nil: invalidPragma(it) var size = expectIntLit(c, it) if not isPowerOfTwo(size) or size <= 0 or size > 8: @@ -648,17 +670,13 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int, processDynLib(c, it, sym) of wCompilerproc: noVal(it) # compilerproc may not get a string! - if sfFromGeneric notin sym.flags: - makeExternExport(sym, "$1", it.info) - incl(sym.flags, sfCompilerProc) - incl(sym.flags, sfUsed) # suppress all those stupid warnings - registerCompilerProc(sym) - of wProcVar: + if sfFromGeneric notin sym.flags: markCompilerProc(sym) + of wProcVar: noVal(it) incl(sym.flags, sfProcvar) - of wDeprecated: - noVal(it) - if sym != nil: incl(sym.flags, sfDeprecated) + of wDeprecated: + if it.kind == nkExprColonExpr: deprecatedStmt(c, it) + elif sym != nil: incl(sym.flags, sfDeprecated) else: incl(c.module.flags, sfDeprecated) of wVarargs: noVal(it) @@ -789,10 +807,11 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int, if sym == nil: invalidPragma(it) of wLine: pragmaLine(c, it) of wRaises, wTags: pragmaRaisesOrTags(c, it) - of wUses: pragmaUses(c, it) - of wOperator: - if sym == nil: invalidPragma(it) - else: sym.position = expectIntLit(c, it) + of wGuard: + if sym == nil or sym.kind notin {skVar, skLet, skField}: + invalidPragma(it) + else: + sym.guard = pragmaGuard(c, it, sym.kind) of wInjectStmt: if it.kind != nkExprColonExpr: localError(it.info, errExprExpected) diff --git a/compiler/sempass2.nim b/compiler/sempass2.nim index acc2425f14..da4adcf49d 100644 --- a/compiler/sempass2.nim +++ b/compiler/sempass2.nim @@ -315,7 +315,6 @@ proc documentRaises*(n: PNode) = if n.sons[namePos].kind != nkSym: return documentEffect(n, n.sons[pragmasPos], wRaises, exceptionEffects) documentEffect(n, n.sons[pragmasPos], wTags, tagEffects) - documentEffect(n, n.sons[pragmasPos], wUses, usesEffects) template notGcSafe(t): expr = {tfGcSafe, tfNoSideEffect} * t.flags == {} @@ -335,10 +334,6 @@ proc propagateEffects(tracked: PEffects, n: PNode, s: PSym) = if warnGcUnsafe in gNotes: message(n.info, warnGcUnsafe, renderTree(n)) tracked.gcUnsafe = true - when trackGlobals: - let usesSpec = effectSpec(pragma, wUses) - mergeUses(tracked, usesSpec, n) - proc notNilCheck(tracked: PEffects, n: PNode, paramType: PType) = let n = n.skipConv if paramType != nil and tfNotNil in paramType.flags and @@ -641,10 +636,6 @@ proc checkMethodEffects*(disp, branch: PSym) = if not isNil(tagsSpec): checkRaisesSpec(tagsSpec, actual.sons[tagEffects], "can have an unlisted effect: ", hints=off, subtypeRelation) - let usesSpec = effectSpec(p, wUses) - if not isNil(usesSpec): - checkRaisesSpec(usesSpec, actual.sons[usesEffects], - "may use an unlisted global variable: ", hints=off, symbolPredicate) if sfThread in disp.flags and notGcSafe(branch.typ): localError(branch.info, "base method is GC-safe, but '$1' is not" % branch.name.s) @@ -656,16 +647,13 @@ proc setEffectsForProcType*(t: PType, n: PNode) = let raisesSpec = effectSpec(n, wRaises) tagsSpec = effectSpec(n, wTags) - usesSpec = effectSpec(n, wUses) - if not isNil(raisesSpec) or not isNil(tagsSpec) or not isNil(usesSpec): + if not isNil(raisesSpec) or not isNil(tagsSpec): internalAssert effects.len == 0 newSeq(effects.sons, effectListLen) if not isNil(raisesSpec): effects.sons[exceptionEffects] = raisesSpec if not isNil(tagsSpec): effects.sons[tagEffects] = tagsSpec - if not isNil(usesSpec): - effects.sons[usesEffects] = usesSpec proc initEffects(effects: PNode; s: PSym; t: var TEffects) = newSeq(effects.sons, effectListLen) @@ -710,12 +698,6 @@ proc trackProc*(s: PSym, body: PNode) = # after the check, use the formal spec: effects.sons[tagEffects] = tagsSpec - when trackGlobals: - let usesSpec = effectSpec(p, wUses) - if not isNil(usesSpec): - checkRaisesSpec(usesSpec, t.uses, - "uses an unlisted global variable: ", hints=on, symbolPredicate) - effects.sons[usesEffects] = usesSpec if optThreadAnalysis in gGlobalOptions: if sfThread in s.flags and t.gcUnsafe: #localError(s.info, warnGcUnsafe2, s.name.s) diff --git a/compiler/wordrecg.nim b/compiler/wordrecg.nim index 96056eb6f3..d810319177 100644 --- a/compiler/wordrecg.nim +++ b/compiler/wordrecg.nim @@ -64,7 +64,7 @@ type wAcyclic, wShallow, wUnroll, wLinearScanEnd, wComputedGoto, wInjectStmt, wWrite, wGensym, wInject, wDirty, wInheritable, wThreadVar, wEmit, wAsmNoStackFrame, - wImplicitStatic, wGlobal, wCodegenDecl, wUnchecked, wGuard, wUses, + wImplicitStatic, wGlobal, wCodegenDecl, wUnchecked, wGuard, wLocks, wAuto, wBool, wCatch, wChar, wClass, wConst_cast, wDefault, wDelete, wDouble, wDynamic_cast, @@ -147,7 +147,7 @@ const "computedgoto", "injectstmt", "write", "gensym", "inject", "dirty", "inheritable", "threadvar", "emit", "asmnostackframe", "implicitstatic", "global", "codegendecl", "unchecked", - "guard", "uses", + "guard", "locks", "auto", "bool", "catch", "char", "class", "const_cast", "default", "delete", "double", From 34e96e37a12083e64be3842f5fc76fd795328e4a Mon Sep 17 00:00:00 2001 From: Araq Date: Sat, 11 Oct 2014 20:51:41 +0200 Subject: [PATCH 219/234] added missing nimfix files --- compiler/nimfix/nimfix.nim | 106 +++++++++++++++++++++++ compiler/nimfix/nimfix.nim.cfg | 17 ++++ compiler/nimfix/pretty.nim | 152 +++++++++++++++++++++++++++++++++ compiler/nimfix/prettybase.nim | 93 ++++++++++++++++++++ 4 files changed, 368 insertions(+) create mode 100644 compiler/nimfix/nimfix.nim create mode 100644 compiler/nimfix/nimfix.nim.cfg create mode 100644 compiler/nimfix/pretty.nim create mode 100644 compiler/nimfix/prettybase.nim diff --git a/compiler/nimfix/nimfix.nim b/compiler/nimfix/nimfix.nim new file mode 100644 index 0000000000..e561b6d4de --- /dev/null +++ b/compiler/nimfix/nimfix.nim @@ -0,0 +1,106 @@ +# +# +# The Nim Compiler +# (c) Copyright 2014 Andreas Rumpf +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# + +## Nimfix is a tool that helps to convert old-style Nimrod code to Nim code. + +import strutils, os, parseopt +import options, commands, modules, sem, passes, passaux, pretty, msgs, nimconf, + extccomp, condsyms, lists + +const Usage = """ +Nimfix - Tool to patch Nim code +Usage: + nimfix [options] projectflie.nim + +Options: + --overwriteFiles:on|off overwrite the original nim files. + DEFAULT is ON! + --wholeProject overwrite every processed file. + --checkExtern:on|off style check also extern names + --styleCheck:on|off|auto performs style checking for identifiers + and suggests an alternative spelling; + 'auto' corrects the spelling. + +In addition, all command line options of Nim are supported. +""" + +proc mainCommand = + #msgs.gErrorMax = high(int) # do not stop after first error + registerPass verbosePass + registerPass semPass + gCmd = cmdPretty + appendStr(searchPaths, options.libpath) + if gProjectFull.len != 0: + # current path is always looked first for modules + prependStr(searchPaths, gProjectPath) + + compileProject() + pretty.overwriteFiles() + +proc processCmdLine*(pass: TCmdLinePass, cmd: string) = + var p = parseopt.initOptParser(cmd) + var argsCount = 0 + gOnlyMainfile = true + while true: + parseopt.next(p) + case p.kind + of cmdEnd: break + of cmdLongoption, cmdShortOption: + case p.key.normalize + of "overwritefiles": + case p.val.normalize + of "on": gOverWrite = true + of "off": gOverWrite = false + else: localError(gCmdLineInfo, errOnOrOffExpected) + of "checkextern": + case p.val.normalize + of "on": gCheckExtern = true + of "off": gCheckExtern = false + else: localError(gCmdLineInfo, errOnOrOffExpected) + of "stylecheck": + case p.val.normalize + of "off": gStyleCheck = StyleCheck.None + of "on": gStyleCheck = StyleCheck.Warn + of "auto": gStyleCheck = StyleCheck.Auto + else: localError(gCmdLineInfo, errOnOrOffExpected) + of "wholeproject": gOnlyMainfile = false + else: + processSwitch(pass, p) + of cmdArgument: + options.gProjectName = unixToNativePath(p.key) + # if processArgument(pass, p, argsCount): break + +proc handleCmdLine() = + if paramCount() == 0: + stdout.writeln(Usage) + else: + processCmdLine(passCmd1, "") + if gProjectName != "": + try: + gProjectFull = canonicalizePath(gProjectName) + except OSError: + gProjectFull = gProjectName + var p = splitFile(gProjectFull) + gProjectPath = p.dir + gProjectName = p.name + else: + gProjectPath = getCurrentDir() + loadConfigs(DefaultConfig) # load all config files + # now process command line arguments again, because some options in the + # command line can overwite the config file's settings + extccomp.initVars() + processCmdLine(passCmd2, "") + mainCommand() + +when compileOption("gc", "v2") or compileOption("gc", "refc"): + GC_disableMarkAndSweep() + +condsyms.initDefines() +defineSymbol "nimfix" +handleCmdline() diff --git a/compiler/nimfix/nimfix.nim.cfg b/compiler/nimfix/nimfix.nim.cfg new file mode 100644 index 0000000000..31a41e080c --- /dev/null +++ b/compiler/nimfix/nimfix.nim.cfg @@ -0,0 +1,17 @@ +# Special configuration file for the Nim project +# gc:markAndSweep + +hint[XDeclaredButNotUsed]:off +path:"$projectPath/../.." + +path:"$lib/packages/docutils" +path:"$nim/compiler" + +define:useStdoutAsStdmsg +symbol:nimfix +define:nimfix + +cs:partial +#define:useNodeIds +define:booting +define:noDocgen diff --git a/compiler/nimfix/pretty.nim b/compiler/nimfix/pretty.nim new file mode 100644 index 0000000000..acac574af3 --- /dev/null +++ b/compiler/nimfix/pretty.nim @@ -0,0 +1,152 @@ +# +# +# The Nim Compiler +# (c) Copyright 2014 Andreas Rumpf +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# + +## This module implements the code "prettifier". This is part of the toolchain +## to convert Nim code into a consistent style. + +import + strutils, os, options, ast, astalgo, msgs, ropes, idents, + intsets, strtabs, semdata, prettybase + +type + StyleCheck* {.pure.} = enum None, Warn, Auto + +var + gOverWrite* = true + gStyleCheck*: StyleCheck + gCheckExtern*, gOnlyMainfile*: bool + +proc overwriteFiles*() = + let doStrip = options.getConfigVar("pretty.strip").normalize == "on" + for i in 0 .. high(gSourceFiles): + if gSourceFiles[i].dirty and not gSourceFiles[i].isNimfixFile and + (not gOnlyMainfile or gSourceFiles[i].fileIdx == gProjectMainIdx): + let newFile = if gOverWrite: gSourceFiles[i].fullpath + else: gSourceFiles[i].fullpath.changeFileExt(".pretty.nim") + try: + var f = open(newFile, fmWrite) + for line in gSourceFiles[i].lines: + if doStrip: + f.write line.strip(leading = false, trailing = true) + else: + f.write line + f.write(gSourceFiles[i].newline) + f.close + except IOError: + rawMessage(errCannotOpenFile, newFile) + +proc `=~`(s: string, a: openArray[string]): bool = + for x in a: + if s.startsWith(x): return true + +proc beautifyName(s: string, k: TSymKind): string = + # minimal set of rules here for transition: + # GC_ is allowed + + let allUpper = allCharsInSet(s, {'A'..'Z', '0'..'9', '_'}) + if allUpper and k in {skConst, skEnumField, skType}: return s + result = newStringOfCap(s.len) + var i = 0 + case k + of skType, skGenericParam: + # Types should start with a capital unless builtins like 'int' etc.: + if s =~ ["int", "uint", "cint", "cuint", "clong", "cstring", "string", + "char", "byte", "bool", "openArray", "seq", "array", "void", + "pointer", "float", "csize", "cdouble", "cchar", "cschar", + "cshort", "cu", "nil", "expr", "stmt", "typedesc", "auto", "any", + "range", "openarray", "varargs", "set", "cfloat" + ]: + result.add s[i] + else: + result.add toUpper(s[i]) + of skConst, skEnumField: + # for 'const' we keep how it's spelt; either upper case or lower case: + result.add s[0] + else: + # as a special rule, don't transform 'L' to 'l' + if s.len == 1 and s[0] == 'L': result.add 'L' + elif '_' in s: result.add(s[i]) + else: result.add toLower(s[0]) + inc i + while i < s.len: + if s[i] == '_': + if i > 0 and s[i-1] in {'A'..'Z'}: + # don't skip '_' as it's essential for e.g. 'GC_disable' + result.add('_') + inc i + result.add s[i] + else: + inc i + result.add toUpper(s[i]) + elif allUpper: + result.add toLower(s[i]) + else: + result.add s[i] + inc i + +proc replaceInFile(info: TLineInfo; newName: string) = + loadFile(info) + + let line = gSourceFiles[info.fileIndex].lines[info.line-1] + var first = min(info.col.int, line.len) + if first < 0: return + #inc first, skipIgnoreCase(line, "proc ", first) + while first > 0 and line[first-1] in prettybase.Letters: dec first + if first < 0: return + if line[first] == '`': inc first + + let last = first+identLen(line, first)-1 + if differ(line, first, last, newName): + # last-first+1 != newName.len or + var x = line.substr(0, first-1) & newName & line.substr(last+1) + system.shallowCopy(gSourceFiles[info.fileIndex].lines[info.line-1], x) + gSourceFiles[info.fileIndex].dirty = true + +proc checkStyle(info: TLineInfo, s: string, k: TSymKind; sym: PSym) = + let beau = beautifyName(s, k) + if s != beau: + if gStyleCheck == StyleCheck.Auto: + sym.name = getIdent(beau) + replaceInFile(info, beau) + else: + message(info, hintName, beau) + +proc styleCheckDefImpl(info: TLineInfo; s: PSym; k: TSymKind) = + # operators stay as they are: + if k in {skResult, skTemp} or s.name.s[0] notin prettybase.Letters: return + if k in {skType, skGenericParam} and sfAnon in s.flags: return + if {sfImportc, sfExportc} * s.flags == {} or gCheckExtern: + checkStyle(info, s.name.s, k, s) + +template styleCheckDef*(info: TLineInfo; s: PSym; k: TSymKind) = + when defined(nimfix): + if gStyleCheck != StyleCheck.None: styleCheckDefImpl(info, s, k) + +template styleCheckDef*(info: TLineInfo; s: PSym) = + styleCheckDef(info, s, s.kind) +template styleCheckDef*(s: PSym) = + styleCheckDef(s.info, s, s.kind) + +proc styleCheckUseImpl(info: TLineInfo; s: PSym) = + if info.fileIndex < 0: return + # we simply convert it to what it looks like in the definition + # for consistency + + # operators stay as they are: + if s.kind in {skResult, skTemp} or s.name.s[0] notin prettybase.Letters: + return + if s.kind in {skType, skGenericParam} and sfAnon in s.flags: return + let newName = s.name.s + + replaceInFile(info, newName) + #if newName == "File": writeStackTrace() + +template styleCheckUse*(info: TLineInfo; s: PSym) = + when defined(nimfix): + if gStyleCheck != StyleCheck.None: styleCheckUseImpl(info, s) diff --git a/compiler/nimfix/prettybase.nim b/compiler/nimfix/prettybase.nim new file mode 100644 index 0000000000..8e0f5db6d8 --- /dev/null +++ b/compiler/nimfix/prettybase.nim @@ -0,0 +1,93 @@ +# +# +# The Nim Compiler +# (c) Copyright 2014 Andreas Rumpf +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# + +import ast, msgs, strutils, idents, lexbase, streams +from os import splitFile + +type + TSourceFile* = object + lines*: seq[string] + dirty*, isNimfixFile*: bool + fullpath*, newline*: string + fileIdx*: int32 + +var + gSourceFiles*: seq[TSourceFile] = @[] + +proc loadFile*(info: TLineInfo) = + let i = info.fileIndex + if i >= gSourceFiles.len: + gSourceFiles.setLen(i+1) + if gSourceFiles[i].lines.isNil: + gSourceFiles[i].fileIdx = info.fileIndex + gSourceFiles[i].lines = @[] + let path = info.toFullPath + gSourceFiles[i].fullpath = path + gSourceFiles[i].isNimfixFile = path.splitFile.ext == ".nimfix" + # we want to die here for IOError: + for line in lines(path): + gSourceFiles[i].lines.add(line) + # extract line ending of the file: + var lex: TBaseLexer + open(lex, newFileStream(path, fmRead)) + var pos = lex.bufpos + while true: + case lex.buf[pos] + of '\c': + gSourceFiles[i].newline = "\c\L" + break + of '\L', '\0': + gSourceFiles[i].newline = "\L" + break + else: discard + inc pos + close(lex) + +const + Letters* = {'a'..'z', 'A'..'Z', '0'..'9', '\x80'..'\xFF', '_'} + +proc identLen*(line: string, start: int): int = + while start+result < line.len and line[start+result] in Letters: + inc result + +proc differ*(line: string, a, b: int, x: string): bool = + let y = line[a..b] + result = cmpIgnoreStyle(y, x) == 0 and y != x + +proc replaceDeprecated*(info: TLineInfo; oldSym, newSym: PIdent) = + loadFile(info) + + let line = gSourceFiles[info.fileIndex].lines[info.line-1] + var first = min(info.col.int, line.len) + if first < 0: return + #inc first, skipIgnoreCase(line, "proc ", first) + while first > 0 and line[first-1] in Letters: dec first + if first < 0: return + if line[first] == '`': inc first + + let last = first+identLen(line, first)-1 + if cmpIgnoreStyle(line[first..last], oldSym.s) == 0: + var x = line.substr(0, first-1) & newSym.s & line.substr(last+1) + system.shallowCopy(gSourceFiles[info.fileIndex].lines[info.line-1], x) + gSourceFiles[info.fileIndex].dirty = true + #if newSym.s == "File": writeStackTrace() + +proc replaceDeprecated*(info: TLineInfo; oldSym, newSym: PSym) = + replaceDeprecated(info, oldSym.name, newSym.name) + +proc replaceComment*(info: TLineInfo) = + loadFile(info) + + let line = gSourceFiles[info.fileIndex].lines[info.line-1] + var first = info.col.int + if line[first] != '#': inc first + + var x = line.substr(0, first-1) & "discard " & line.substr(first+1).escape + system.shallowCopy(gSourceFiles[info.fileIndex].lines[info.line-1], x) + gSourceFiles[info.fileIndex].dirty = true From 399c985b62b35e7d81149ceef5d9a51fdeac35ed Mon Sep 17 00:00:00 2001 From: Araq Date: Sat, 11 Oct 2014 21:44:35 +0200 Subject: [PATCH 220/234] fixes recent regression --- lib/pure/concurrency/cpuinfo.nim | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/pure/concurrency/cpuinfo.nim b/lib/pure/concurrency/cpuinfo.nim index bd10a416fd..8d7f28f8ef 100644 --- a/lib/pure/concurrency/cpuinfo.nim +++ b/lib/pure/concurrency/cpuinfo.nim @@ -26,13 +26,16 @@ when defined(openbsd) or defined(netbsd): {.emit:"#include ".} when defined(macosx) or defined(bsd): + # we HAVE to emit param.h before sysctl.h so we cannot use .header here + # either. The amount of archaic bullshit in Poonix based OSes is just insane. + {.emit:"#include ".} const CTL_HW = 6 HW_AVAILCPU = 25 HW_NCPU = 3 proc sysctl(x: ptr array[0..3, cint], y: cint, z: pointer, a: var csize, b: pointer, c: int): cint {. - importc: "sysctl", header: "".} + importc: "sysctl", nodecl.} proc countProcessors*(): int {.rtl, extern: "ncpi$1".} = ## returns the numer of the processors/cores the machine has. From ca4c64dd72646abec1b9683bb422f8cb2ca81ad7 Mon Sep 17 00:00:00 2001 From: Araq Date: Sun, 12 Oct 2014 03:13:12 +0200 Subject: [PATCH 221/234] zipfile generation works again --- koch.nim | 6 ++++-- tools/niminst/niminst.nim | 8 ++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/koch.nim b/koch.nim index dff6ede989..b7cf65ff7e 100644 --- a/koch.nim +++ b/koch.nim @@ -84,9 +84,11 @@ proc csource(args: string) = exec("$4 cc $1 -r $3 --var:version=$2 csource compiler/nimrod.ini $1" % [args, NimrodVersion, compileNimInst, findNim()]) -proc zip(args: string) = - exec("$3 cc -r $2 --var:version=$1 zip compiler/nimrod.ini" % +proc zip(args: string) = + exec("$3 cc -r $2 --var:version=$1 scripts compiler/nimrod.ini" % [NimrodVersion, compileNimInst, findNim()]) + exec("$# --var:version=$# zip compiler/nimrod.ini" % + ["tools/niminst/niminst".exe, NimrodVersion]) proc buildTool(toolname, args: string) = exec("$# cc $# $#" % [findNim(), args, toolname]) diff --git a/tools/niminst/niminst.nim b/tools/niminst/niminst.nim index bf8a7a84ff..50b3dacc37 100644 --- a/tools/niminst/niminst.nim +++ b/tools/niminst/niminst.nim @@ -503,9 +503,9 @@ when haveZipLib: else: n = c.outdir / n var z: TZipArchive if open(z, n, fmWrite): - addFile(z, proj / buildBatFile32, buildBatFile32) - addFile(z, proj / buildBatFile64, buildBatFile64) - addFile(z, proj / buildShFile, buildShFile) + addFile(z, proj / buildBatFile32, "build" / buildBatFile32) + addFile(z, proj / buildBatFile64, "build" / buildBatFile64) + addFile(z, proj / buildShFile, "build" / buildShFile) addFile(z, proj / installShFile, installShFile) addFile(z, proj / deinstallShFile, deinstallShFile) for f in walkFiles(c.libpath / "lib/*.h"): @@ -513,7 +513,7 @@ when haveZipLib: for osA in 1..c.oses.len: for cpuA in 1..c.cpus.len: var dir = buildDir(osA, cpuA) - for k, f in walkDir(dir): + for k, f in walkDir("build" / dir): if k == pcFile: addFile(z, proj / dir / extractFilename(f), f) for cat in items({fcConfig..fcOther, fcUnix}): From b7befd69ba0051c1db44a37c8c3e06c48990a9b1 Mon Sep 17 00:00:00 2001 From: Araq Date: Sun, 12 Oct 2014 14:18:17 +0200 Subject: [PATCH 222/234] updated news.txt slightly --- web/news.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/news.txt b/web/news.txt index efef33e421..27262309ee 100644 --- a/web/news.txt +++ b/web/news.txt @@ -2,13 +2,13 @@ News ==== -2014-10-11 Version 0.9.6 released +2014-10-12 Version 0.9.6 released ================================= **Note: This is the last release of Nimrod. The language has been renamed to Nim. Nim slightly breaks compatibility.** -This is a maintenance release. The upcoming 0.10.0 release has all +This is a maintenance release. The upcoming 0.10.0 release has the new features and exciting developments. From 55d8e71ab10f5cb1c4e554f2dbe372c47308231d Mon Sep 17 00:00:00 2001 From: Araq Date: Fri, 17 Oct 2014 00:53:33 +0200 Subject: [PATCH 223/234] niminst supports NSIS --- compiler/nimrod.ini | 20 +++++++++++------ tools/niminst/inno.tmpl | 6 ++--- tools/niminst/niminst.nim | 47 ++++++++++++++++++++++++++++++--------- 3 files changed, 53 insertions(+), 20 deletions(-) diff --git a/compiler/nimrod.ini b/compiler/nimrod.ini index 44e16cec85..697ad6e500 100644 --- a/compiler/nimrod.ini +++ b/compiler/nimrod.ini @@ -34,11 +34,11 @@ Files: "config/nimdoc.cfg" Files: "config/nimdoc.tex.cfg" [Documentation] -Files: "doc/*.txt" -Files: "doc/*.html" -Files: "doc/*.cfg" -Files: "doc/*.pdf" -Files: "doc/*.ini" +; Files: "doc/*.txt" +; Files: "doc/*.html" +; Files: "doc/*.cfg" +; Files: "doc/*.pdf" +; Files: "doc/*.ini" Start: "doc/overview.html" @@ -121,11 +121,14 @@ Files: "bin/nimgrep.exe" Files: "dist/*.dll" Files: "koch.exe" -Files: "dist/mingw" +; Files: "dist/mingw" Files: "start.bat" BinPath: r"bin;dist\mingw\bin;dist" -InnoSetup: "Yes" +; Section | dir | zipFile | size hint (in KB) | url +Download: r"Documentation|doc|docs.zip|13824|http://nim-lang.org/download/docs-${version}.zip" +Download: r"C compiler (mingw)|dist|mingw.zip|82944|http://nim-lang.org/download/${mingw}.zip" +; for now only NSIS supports optional downloads [UnixBin] Files: "bin/nimrod" @@ -140,6 +143,9 @@ UninstallScript: "yes" path = r"c:\Program Files (x86)\Inno Setup 5\iscc.exe" flags = "/Q" +[NSIS] +path = r"c:\Program Files (x86)\NSIS\makensis.exe" +flags = "" [C_Compiler] path = r"" diff --git a/tools/niminst/inno.tmpl b/tools/niminst/inno.tmpl index b9d04755ee..3460c22a29 100644 --- a/tools/niminst/inno.tmpl +++ b/tools/niminst/inno.tmpl @@ -44,9 +44,9 @@ Name: modifypath; Description: &Add $c.displayName to your system path (if not i [Code] function GiveMeAPath(const DefaultPathName: string): string; begin - if IsAdminLoggedOn then Result := ExpandConstant('{pf}') - else Result := ExpandConstant('{userdocs}'); - Result := Result + '\' + DefaultPathName; + if IsAdminLoggedOn then result := ExpandConstant('{pf}') + else result := ExpandConstant('{userdocs}'); + result := result + '\' + DefaultPathName; end; #if c.binPaths.len > 0: diff --git a/tools/niminst/niminst.nim b/tools/niminst/niminst.nim index 50b3dacc37..a8dfb664e2 100644 --- a/tools/niminst/niminst.nim +++ b/tools/niminst/niminst.nim @@ -31,6 +31,7 @@ type actionNone, # action not yet known actionCSource # action: create C sources actionInno, # action: create Inno Setup installer + actionNsis, # action: create NSIS installer actionScripts # action: create install and deinstall scripts actionZip, # action: create zip file actionDeb # action: prepare deb package @@ -50,10 +51,10 @@ type TConfigData = object of TObject actions: set[TAction] cat: array[TFileCategory, seq[string]] - binPaths, authors, oses, cpus: seq[string] + binPaths, authors, oses, cpus, downloads: seq[string] cfiles: array[1..maxOS, array[1..maxCPU, seq[string]]] platforms: array[1..maxOS, array[1..maxCPU, bool]] - ccompiler, linker, innosetup: tuple[path, flags: string] + ccompiler, linker, innosetup, nsisSetup: tuple[path, flags: string] name, displayName, version, description, license, infile, outdir: string libpath: string innoSetupFlag, installScript, uninstallScript: bool @@ -75,9 +76,11 @@ proc initConfigData(c: var TConfigData) = c.authors = @[] c.oses = @[] c.cpus = @[] + c.downloads = @[] c.ccompiler = ("", "") c.linker = ("", "") c.innosetup = ("", "") + c.nsisSetup = ("", "") c.name = "" c.displayName = "" c.version = "" @@ -117,6 +120,7 @@ proc skipRoot(f: string): string = if result.len == 0: result = f include "inno.tmpl" +include "nsis.tmpl" include "buildsh.tmpl" include "buildbat.tmpl" include "install.tmpl" @@ -125,10 +129,10 @@ include "deinstall.tmpl" # ------------------------- configuration file ------------------------------- const - Version = "0.9" + Version = "1.0" Usage = "niminst - Nimrod Installation Generator Version " & Version & """ - (c) 2013 Andreas Rumpf + (c) 2014 Andreas Rumpf Usage: niminst [options] command[;command2...] ini-file[.ini] [compile_options] Command: @@ -136,6 +140,7 @@ Command: scripts build install and deinstall scripts zip build the ZIP file inno build the Inno Setup installer + nsis build the NSIS Setup installer deb create files for debhelper Options: -o, --output:dir set the output directory @@ -162,6 +167,7 @@ proc parseCmdLine(c: var TConfigData) = of "scripts": incl(c.actions, actionScripts) of "zip": incl(c.actions, actionZip) of "inno": incl(c.actions, actionInno) + of "nsis": incl(c.actions, actionNsis) of "deb": incl(c.actions, actionDeb) else: quit(Usage) else: @@ -190,7 +196,7 @@ proc walkDirRecursively(s: var seq[string], root: string) = case k of pcFile, pcLinkToFile: add(s, unixToNativePath(f)) of pcDir: walkDirRecursively(s, f) - of pcLinkToDir: nil + of pcLinkToDir: discard proc addFiles(s: var seq[string], patterns: seq[string]) = for p in items(patterns): @@ -288,7 +294,7 @@ proc parseIniFile(c: var TConfigData) = else: quit(errorStr(p, "expected: console or gui")) of "license": c.license = unixToNativePath(k.value) else: quit(errorStr(p, "unknown variable: " & k.key)) - of "var": nil + of "var": discard of "winbin": filesOnly(p, k.key, v, c.cat[fcWinBin]) of "config": filesOnly(p, k.key, v, c.cat[fcConfig]) of "data": filesOnly(p, k.key, v, c.cat[fcData]) @@ -304,6 +310,7 @@ proc parseIniFile(c: var TConfigData) = of "files": addFiles(c.cat[fcWindows], split(v, {';'})) of "binpath": c.binPaths = split(v, {';'}) of "innosetup": c.innoSetupFlag = yesno(p, v) + of "download": c.downloads.add(v) else: quit(errorStr(p, "unknown variable: " & k.key)) of "unix": case normalize(k.key) @@ -313,6 +320,7 @@ proc parseIniFile(c: var TConfigData) = else: quit(errorStr(p, "unknown variable: " & k.key)) of "unixbin": filesOnly(p, k.key, v, c.cat[fcUnixBin]) of "innosetup": pathFlags(p, k.key, v, c.innosetup) + of "nsis": pathFlags(p, k.key, v, c.nsisSetup) of "ccompiler": pathFlags(p, k.key, v, c.ccompiler) of "linker": pathFlags(p, k.key, v, c.linker) of "deb": @@ -479,14 +487,14 @@ proc srcdist(c: var TConfigData) = # --------------------- generate inno setup ----------------------------------- proc setupDist(c: var TConfigData) = - var scrpt = generateInnoSetup(c) - var n = "build" / "install_$#_$#.iss" % [toLower(c.name), c.version] + let scrpt = generateInnoSetup(c) + let n = "build" / "install_$#_$#.iss" % [toLower(c.name), c.version] writeFile(n, scrpt, "\13\10") when defined(windows): if c.innosetup.path.len == 0: c.innosetup.path = "iscc.exe" - var outcmd = if c.outdir.len == 0: "build" else: c.outdir - var cmd = "$# $# /O$# $#" % [quoteShell(c.innosetup.path), + let outcmd = if c.outdir.len == 0: "build" else: c.outdir + let cmd = "$# $# /O$# $#" % [quoteShell(c.innosetup.path), c.innosetup.flags, outcmd, n] echo(cmd) if execShellCmd(cmd) == 0: @@ -494,6 +502,23 @@ proc setupDist(c: var TConfigData) = else: quit("External program failed") +# --------------------- generate NSIS setup ----------------------------------- +proc setupDist2(c: var TConfigData) = + let scrpt = generateNsisSetup(c) + let n = "build" / "install_$#_$#.nsi" % [toLower(c.name), c.version] + writeFile(n, scrpt, "\13\10") + when defined(windows): + if c.nsisSetup.path.len == 0: + c.nsisSetup.path = "makensis.exe" + let outcmd = if c.outdir.len == 0: "build" else: c.outdir + let cmd = "$# $# /O$# $#" % [quoteShell(c.nsisSetup.path), + c.nsisSetup.flags, outcmd, n] + echo(cmd) + if execShellCmd(cmd) == 0: + removeFile(n) + else: + quit("External program failed") + # ------------------ generate ZIP file --------------------------------------- when haveZipLib: proc zipDist(c: var TConfigData) = @@ -576,6 +601,8 @@ parseCmdLine(c) parseIniFile(c) if actionInno in c.actions: setupDist(c) +if actionNsis in c.actions: + setupDist2(c) if actionCSource in c.actions: srcdist(c) if actionScripts in c.actions: From bd54c44239ae34b8b8e756e6acfc5dc82f49edb5 Mon Sep 17 00:00:00 2001 From: Araq Date: Fri, 17 Oct 2014 03:15:28 +0200 Subject: [PATCH 224/234] improvements for niminst --- compiler/nimrod.ini | 6 ++---- copying.txt | 8 ++++---- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/compiler/nimrod.ini b/compiler/nimrod.ini index 697ad6e500..934ef3988a 100644 --- a/compiler/nimrod.ini +++ b/compiler/nimrod.ini @@ -39,6 +39,7 @@ Files: "config/nimdoc.tex.cfg" ; Files: "doc/*.cfg" ; Files: "doc/*.pdf" ; Files: "doc/*.ini" +Files: "doc/overview.html" Start: "doc/overview.html" @@ -66,9 +67,6 @@ Files: "compiler/c2nim/*.cfg" Files: "compiler/pas2nim/*.nim" Files: "compiler/pas2nim/*.cfg" -Files: "build/empty.txt" -Files: "bin/empty.txt" - [Lib] Files: "lib/nimbase.h" @@ -145,7 +143,7 @@ flags = "/Q" [NSIS] path = r"c:\Program Files (x86)\NSIS\makensis.exe" -flags = "" +flags = "/V0" [C_Compiler] path = r"" diff --git a/copying.txt b/copying.txt index 4041ca0272..254b91c774 100644 --- a/copying.txt +++ b/copying.txt @@ -1,7 +1,7 @@ -=============================================================================== -Nimrod -- a Compiler for Nimrod. http://nimrod-code.org/ - -Copyright (C) 2004-2014 Andreas Rumpf. All rights reserved. +===================================================== +Nimrod -- a Compiler for Nimrod. http://nimrod-lang.org/ + +Copyright (C) 2006-2014 Andreas Rumpf. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From 4accf4292997bda0e9746a152ba202c646e01e11 Mon Sep 17 00:00:00 2001 From: Araq Date: Fri, 17 Oct 2014 03:27:04 +0200 Subject: [PATCH 225/234] added missing template file --- tools/niminst/nsis.tmpl | 166 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 166 insertions(+) create mode 100644 tools/niminst/nsis.tmpl diff --git a/tools/niminst/nsis.tmpl b/tools/niminst/nsis.tmpl new file mode 100644 index 0000000000..cea7e06830 --- /dev/null +++ b/tools/niminst/nsis.tmpl @@ -0,0 +1,166 @@ +#! stdtmpl(subsChar='?') | standard +#proc generateNsisSetup(c: TConfigData): string = +# result = "; NSIS script generated by niminst\n" & +# "; To regenerate run ``niminst nsis`` or ``koch nsis``\n" + +!define PRODUCT_NAME "?c.displayName" +!define PRODUCT_VERSION "?c.version" +!define PRODUCT_PUBLISHER "?c.authors" +!define PRODUCT_DIR_REGKEY "Software\Microsoft\Windows\CurrentVersion\App Paths\?{c.name}.exe" +!define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" +!define PRODUCT_UNINST_ROOT_KEY "HKCU" +!define PRODUCT_STARTMENU_REGVAL "NSIS:StartMenuDir" + +; MUI 1.67 compatible ------ +!include "MUI.nsh" +!define MULTIUSER_EXECUTIONLEVEL Standard +!include "MultiUser.nsh" +!include "zipdll.nsh" + +InstallDir "$LOCALAPPDATA\?{c.name}" + +; MUI Settings +!define MUI_ABORTWARNING +!define MUI_ICON "${NSISDIR}\Contrib\Graphics\Icons\modern-install.ico" +!define MUI_UNICON "${NSISDIR}\Contrib\Graphics\Icons\modern-uninstall.ico" + +; Welcome page +!insertmacro MUI_PAGE_WELCOME +; License page +!insertmacro MUI_PAGE_LICENSE "?{expandFilename(c.license)}" +; Components page +!insertmacro MUI_PAGE_COMPONENTS +; Directory page +!insertmacro MUI_PAGE_DIRECTORY +; Start menu page +var ICONS_GROUP +!define MUI_STARTMENUPAGE_NODISABLE +!define MUI_STARTMENUPAGE_DEFAULTFOLDER "?c.displayName" +!define MUI_STARTMENUPAGE_REGISTRY_ROOT "${PRODUCT_UNINST_ROOT_KEY}" +!define MUI_STARTMENUPAGE_REGISTRY_KEY "${PRODUCT_UNINST_KEY}" +!define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "${PRODUCT_STARTMENU_REGVAL}" +!insertmacro MUI_PAGE_STARTMENU Application $ICONS_GROUP +; Instfiles page +!insertmacro MUI_PAGE_INSTFILES +; Finish page +; !define MUI_FINISHPAGE_RUN "$INSTDIR\start.bat" +!insertmacro MUI_PAGE_FINISH + +; Uninstaller pages +!insertmacro MUI_UNPAGE_INSTFILES + +; Language files +!insertmacro MUI_LANGUAGE "English" + +; MUI end ------ + +Name "${PRODUCT_NAME} ${PRODUCT_VERSION}" +OutFile "?{c.name}_?{c.version}.exe" +; InstallDir "$PROGRAMFILES\?c.displayName" +InstallDirRegKey HKCU "${PRODUCT_DIR_REGKEY}" "" +ShowInstDetails show +ShowUnInstDetails show + +Section "Core" SEC0 + SetOverwrite ifnewer + SetOutPath "$INSTDIR" + #for i in low(TFileCategory)..fcWindows: + # for f in items(c.cat[i]): + SetOutPath "$INSTDIR\?{splitFile(f).dir.toWin}" + File "?{expandFilename(f).toWin}" + # end for + #end for + + +; Shortcuts + !insertmacro MUI_STARTMENU_WRITE_BEGIN Application + CreateDirectory "$SMPROGRAMS\$ICONS_GROUP" + + #if c.app == appConsole: + CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\?{c.displayName}.lnk" "$INSTDIR\start.bat" + CreateShortCut "$DESKTOP\?{c.displayName}.lnk" "$INSTDIR\start.bat" + #else: + CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\?{c.displayName}.lnk" "$INSTDIR\?{c.name}.exe" + CreateShortCut "$DESKTOP\?{c.displayName}.lnk" "$INSTDIR\?{c.name}.exe" + #end if + #for f in items(c.cat[fcDocStart]): + CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\?{splitFile(f).name}.lnk" "$INSTDIR\?{f.toWin}" + #end for + + !insertmacro MUI_STARTMENU_WRITE_END +SectionEnd + +#var i = 0 +#for download in c.downloads: +# inc i +# let d = download.split('|') +# if d.len != 5: +# quit("download string needs 5 parts: " & download) +# end if +# let sectionName = d[0] +# let dir = d[1] +# let zipName = d[2] +# let size = d[3] +# let url = d[4] + Section /o "?sectionName" SEC?i + + AddSize ?size + + NSISdl::download "?url" "$INSTDIR\?zipName" + Pop $0 + ${If} $0 == "success" + ZipDLL::extractall "$INSTDIR\?zipName" "$INSTDIR\?dir" + Delete "$INSTDIR\?zipName" + ${Else} + MessageBox mb_iconstop "Error: $0" ;Show cancel/error message + ${EndIf} + +; Shortcuts + !insertmacro MUI_STARTMENU_WRITE_BEGIN Application + !insertmacro MUI_STARTMENU_WRITE_END + SectionEnd +#end + +Section -AdditionalIcons + SetOutPath $INSTDIR + !insertmacro MUI_STARTMENU_WRITE_BEGIN Application + CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\Uninstall.lnk" "$INSTDIR\uninst.exe" + !insertmacro MUI_STARTMENU_WRITE_END +SectionEnd + +Section -Post + WriteUninstaller "$INSTDIR\uninst.exe" + WriteRegStr HKCU "${PRODUCT_DIR_REGKEY}" "" "$INSTDIR\bin\?{c.name}.exe" + WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "$(^Name)" + WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\uninst.exe" + WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayIcon" "$INSTDIR\bin\?{c.name}.exe" + WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayVersion" "${PRODUCT_VERSION}" + WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "Publisher" "${PRODUCT_PUBLISHER}" +SectionEnd + +Function .onInit + !insertmacro MULTIUSER_INIT +FunctionEnd + +Function un.onUninstSuccess + HideWindow + MessageBox MB_ICONINFORMATION|MB_OK "Uninstall was completed successfully." +FunctionEnd + +Function un.onInit + MessageBox MB_ICONQUESTION|MB_YESNO|MB_DEFBUTTON2 "Remove $(^Name) from your computer." IDYES +2 + !insertmacro MULTIUSER_UNINIT + Abort +FunctionEnd + +Section Uninstall + !insertmacro MUI_STARTMENU_GETFOLDER "Application" $ICONS_GROUP + Delete "$DESKTOP\?{c.displayName}.lnk" + + RMDir /r "$SMPROGRAMS\$ICONS_GROUP" + RMDir /r "$INSTDIR" + + DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" + DeleteRegKey HKCU "${PRODUCT_DIR_REGKEY}" + SetAutoClose true +SectionEnd \ No newline at end of file From 56f1f3d4bce3e9e52e15e3569668d3dacc1c5f77 Mon Sep 17 00:00:00 2001 From: Araq Date: Fri, 17 Oct 2014 18:18:46 +0200 Subject: [PATCH 226/234] more improvements for the NSIS installer --- compiler/nimrod.ini | 3 ++- tools/niminst/nsis.tmpl | 12 +++++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/compiler/nimrod.ini b/compiler/nimrod.ini index 934ef3988a..82d5ea2aed 100644 --- a/compiler/nimrod.ini +++ b/compiler/nimrod.ini @@ -123,9 +123,10 @@ Files: "koch.exe" Files: "start.bat" BinPath: r"bin;dist\mingw\bin;dist" -; Section | dir | zipFile | size hint (in KB) | url +; Section | dir | zipFile | size hint (in KB) | url | exe start menu entry Download: r"Documentation|doc|docs.zip|13824|http://nim-lang.org/download/docs-${version}.zip" Download: r"C compiler (mingw)|dist|mingw.zip|82944|http://nim-lang.org/download/${mingw}.zip" +Download: r"Aporia IDE|dist|aporia.zip|97997|http://nim-lang.org/download/aporia-0.1.3.zip|aporia\bin\aporia.exe" ; for now only NSIS supports optional downloads [UnixBin] diff --git a/tools/niminst/nsis.tmpl b/tools/niminst/nsis.tmpl index cea7e06830..7249dca638 100644 --- a/tools/niminst/nsis.tmpl +++ b/tools/niminst/nsis.tmpl @@ -94,8 +94,8 @@ SectionEnd #for download in c.downloads: # inc i # let d = download.split('|') -# if d.len != 5: -# quit("download string needs 5 parts: " & download) +# if d.len != 5 and d.len != 6: +# quit("download string needs 5..6 parts: " & download) # end if # let sectionName = d[0] # let dir = d[1] @@ -115,6 +115,12 @@ SectionEnd MessageBox mb_iconstop "Error: $0" ;Show cancel/error message ${EndIf} +# if d.len >= 6: +# let startMenuEntry = d[5] +# let e = splitFile(startMenuEntry).name.capitalize + CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\?{e}.lnk" "$INSTDIR\?dir\?{startMenuEntry.toWin}" +# end if + ; Shortcuts !insertmacro MUI_STARTMENU_WRITE_BEGIN Application !insertmacro MUI_STARTMENU_WRITE_END @@ -149,8 +155,8 @@ FunctionEnd Function un.onInit MessageBox MB_ICONQUESTION|MB_YESNO|MB_DEFBUTTON2 "Remove $(^Name) from your computer." IDYES +2 - !insertmacro MULTIUSER_UNINIT Abort + !insertmacro MULTIUSER_UNINIT FunctionEnd Section Uninstall From 32444e47a0532b7badf4af133165145e03d906a6 Mon Sep 17 00:00:00 2001 From: Araq Date: Sat, 18 Oct 2014 13:57:06 +0200 Subject: [PATCH 227/234] niminst: source based installation works again --- tools/niminst/niminst.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/niminst/niminst.nim b/tools/niminst/niminst.nim index a8dfb664e2..53de52f0a4 100644 --- a/tools/niminst/niminst.nim +++ b/tools/niminst/niminst.nim @@ -534,7 +534,7 @@ when haveZipLib: addFile(z, proj / installShFile, installShFile) addFile(z, proj / deinstallShFile, deinstallShFile) for f in walkFiles(c.libpath / "lib/*.h"): - addFile(z, proj / "build" / extractFilename(f), f) + addFile(z, proj / "c_code" / extractFilename(f), f) for osA in 1..c.oses.len: for cpuA in 1..c.cpus.len: var dir = buildDir(osA, cpuA) From d3e9d0fa3a7feaf1d7d16e8a4c6b2f9f4e43902f Mon Sep 17 00:00:00 2001 From: Araq Date: Sat, 18 Oct 2014 20:26:51 +0200 Subject: [PATCH 228/234] niminst: 'doc/*.txt' required for bootstrapping --- compiler/nimrod.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/nimrod.ini b/compiler/nimrod.ini index 82d5ea2aed..b4db10c11e 100644 --- a/compiler/nimrod.ini +++ b/compiler/nimrod.ini @@ -34,7 +34,7 @@ Files: "config/nimdoc.cfg" Files: "config/nimdoc.tex.cfg" [Documentation] -; Files: "doc/*.txt" +Files: "doc/*.txt" ; Files: "doc/*.html" ; Files: "doc/*.cfg" ; Files: "doc/*.pdf" From d73d752187ce108f0501810e1574f91533499ff4 Mon Sep 17 00:00:00 2001 From: Clay Sweetser Date: Sun, 19 Oct 2014 02:14:24 -0400 Subject: [PATCH 229/234] Update and clarify the purpose of the nimrod.ini file --- compiler/nimrod.ini | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/compiler/nimrod.ini b/compiler/nimrod.ini index b4db10c11e..61e09b9f14 100644 --- a/compiler/nimrod.ini +++ b/compiler/nimrod.ini @@ -1,3 +1,6 @@ +; This config file holds configuration information about the Nim compiler +; and project. + [Project] Name: "Nimrod" Version: "$version" @@ -34,7 +37,7 @@ Files: "config/nimdoc.cfg" Files: "config/nimdoc.tex.cfg" [Documentation] -Files: "doc/*.txt" +; Files: "doc/*.txt" ; Files: "doc/*.html" ; Files: "doc/*.cfg" ; Files: "doc/*.pdf" @@ -113,6 +116,7 @@ Files: "examples/*.tmpl" [Windows] Files: "bin/nimrod.exe" +Files: "bin/nimrod_debug.exe" Files: "bin/c2nim.exe" Files: "bin/niminst.exe" Files: "bin/nimgrep.exe" @@ -125,7 +129,7 @@ BinPath: r"bin;dist\mingw\bin;dist" ; Section | dir | zipFile | size hint (in KB) | url | exe start menu entry Download: r"Documentation|doc|docs.zip|13824|http://nim-lang.org/download/docs-${version}.zip" -Download: r"C compiler (mingw)|dist|mingw.zip|82944|http://nim-lang.org/download/${mingw}.zip" +Download: r"C Compiler (MingW)|dist|mingw.zip|82944|http://nim-lang.org/download/${mingw}.zip" Download: r"Aporia IDE|dist|aporia.zip|97997|http://nim-lang.org/download/aporia-0.1.3.zip|aporia\bin\aporia.exe" ; for now only NSIS supports optional downloads From cdd5b503b40f46d006913f52186bf91dee8ac965 Mon Sep 17 00:00:00 2001 From: Clay Sweetser Date: Sun, 19 Oct 2014 02:20:44 -0400 Subject: [PATCH 230/234] Update the NSIS Installer Script --- tools/niminst/EnvVarUpdate.nsh | 346 ++++++++++++++++++++++++++++++ tools/niminst/nsis.tmpl | 375 ++++++++++++++++++++------------- 2 files changed, 575 insertions(+), 146 deletions(-) create mode 100644 tools/niminst/EnvVarUpdate.nsh diff --git a/tools/niminst/EnvVarUpdate.nsh b/tools/niminst/EnvVarUpdate.nsh new file mode 100644 index 0000000000..4340b8f3c1 --- /dev/null +++ b/tools/niminst/EnvVarUpdate.nsh @@ -0,0 +1,346 @@ +/** + * EnvVarUpdate.nsh + * : Environmental Variables: append, prepend, and remove entries + * + * WARNING: If you use StrFunc.nsh header then include it before this file + * with all required definitions. This is to avoid conflicts + * + * Usage: + * ${EnvVarUpdate} "ResultVar" "EnvVarName" "Action" "RegLoc" "PathString" + * + * Credits: + * Version 1.0 + * * Cal Turney (turnec2) + * * Amir Szekely (KiCHiK) and e-circ for developing the forerunners of this + * function: AddToPath, un.RemoveFromPath, AddToEnvVar, un.RemoveFromEnvVar, + * WriteEnvStr, and un.DeleteEnvStr + * * Diego Pedroso (deguix) for StrTok + * * Kevin English (kenglish_hi) for StrContains + * * Hendri Adriaens (Smile2Me), Diego Pedroso (deguix), and Dan Fuhry + * (dandaman32) for StrReplace + * + * Version 1.1 (compatibility with StrFunc.nsh) + * * techtonik + * + * http://nsis.sourceforge.net/Environmental_Variables:_append%2C_prepend%2C_and_remove_entries + * + */ + + +!ifndef ENVVARUPDATE_FUNCTION +!define ENVVARUPDATE_FUNCTION +!verbose push +!verbose 3 +!include "LogicLib.nsh" +!include "WinMessages.NSH" +!include "StrFunc.nsh" + +; ---- Fix for conflict if StrFunc.nsh is already includes in main file ----------------------- +!macro _IncludeStrFunction StrFuncName + !ifndef ${StrFuncName}_INCLUDED + ${${StrFuncName}} + !endif + !ifndef Un${StrFuncName}_INCLUDED + ${Un${StrFuncName}} + !endif + !define un.${StrFuncName} "${Un${StrFuncName}}" +!macroend + +!insertmacro _IncludeStrFunction StrTok +!insertmacro _IncludeStrFunction StrStr +!insertmacro _IncludeStrFunction StrRep + +; ---------------------------------- Macro Definitions ---------------------------------------- +!macro _EnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString + Push "${EnvVarName}" + Push "${Action}" + Push "${RegLoc}" + Push "${PathString}" + Call EnvVarUpdate + Pop "${ResultVar}" +!macroend +!define EnvVarUpdate '!insertmacro "_EnvVarUpdateConstructor"' + +!macro _unEnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString + Push "${EnvVarName}" + Push "${Action}" + Push "${RegLoc}" + Push "${PathString}" + Call un.EnvVarUpdate + Pop "${ResultVar}" +!macroend +!define un.EnvVarUpdate '!insertmacro "_unEnvVarUpdateConstructor"' +; ---------------------------------- Macro Definitions end------------------------------------- + +;----------------------------------- EnvVarUpdate start---------------------------------------- +!define hklm_all_users 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"' +!define hkcu_current_user 'HKCU "Environment"' + +!macro EnvVarUpdate UN + +Function ${UN}EnvVarUpdate + + Push $0 + Exch 4 + Exch $1 + Exch 3 + Exch $2 + Exch 2 + Exch $3 + Exch + Exch $4 + Push $5 + Push $6 + Push $7 + Push $8 + Push $9 + Push $R0 + + /* After this point: + ------------------------- + $0 = ResultVar (returned) + $1 = EnvVarName (input) + $2 = Action (input) + $3 = RegLoc (input) + $4 = PathString (input) + $5 = Orig EnvVar (read from registry) + $6 = Len of $0 (temp) + $7 = tempstr1 (temp) + $8 = Entry counter (temp) + $9 = tempstr2 (temp) + $R0 = tempChar (temp) */ + + ; Step 1: Read contents of EnvVarName from RegLoc + ; + ; Check for empty EnvVarName + ${If} $1 == "" + SetErrors + DetailPrint "ERROR: EnvVarName is blank" + Goto EnvVarUpdate_Restore_Vars + ${EndIf} + + ; Check for valid Action + ${If} $2 != "A" + ${AndIf} $2 != "P" + ${AndIf} $2 != "R" + SetErrors + DetailPrint "ERROR: Invalid Action - must be A, P, or R" + Goto EnvVarUpdate_Restore_Vars + ${EndIf} + + ${If} $3 == HKLM + ReadRegStr $5 ${hklm_all_users} $1 ; Get EnvVarName from all users into $5 + ${ElseIf} $3 == HKCU + ReadRegStr $5 ${hkcu_current_user} $1 ; Read EnvVarName from current user into $5 + ${Else} + SetErrors + DetailPrint 'ERROR: Action is [$3] but must be "HKLM" or HKCU"' + Goto EnvVarUpdate_Restore_Vars + ${EndIf} + + ; Check for empty PathString + ${If} $4 == "" + SetErrors + DetailPrint "ERROR: PathString is blank" + Goto EnvVarUpdate_Restore_Vars + ${EndIf} + + Push $6 + Push $7 + Push $8 + StrLen $7 $4 + StrLen $6 $5 + IntOp $8 $6 + $7 + ${If} $5 == "" + ${OrIf} $8 >= ${NSIS_MAX_STRLEN} + SetErrors + DetailPrint "Current $1 length ($6) too long to modify in NSIS; set manually if needed" + Pop $8 + Pop $7 + Pop $6 + Goto EnvVarUpdate_Restore_Vars + ${EndIf} + Pop $8 + Pop $7 + Pop $6 + + ; Make sure we've got some work to do + ${If} $5 == "" + ${AndIf} $2 == "R" + SetErrors + DetailPrint "$1 is empty - Nothing to remove" + Goto EnvVarUpdate_Restore_Vars + ${EndIf} + + ; Step 2: Scrub EnvVar + ; + StrCpy $0 $5 ; Copy the contents to $0 + ; Remove spaces around semicolons (NOTE: spaces before the 1st entry or + ; after the last one are not removed here but instead in Step 3) + ${If} $0 != "" ; If EnvVar is not empty ... + ${Do} + ${${UN}StrStr} $7 $0 " ;" + ${If} $7 == "" + ${ExitDo} + ${EndIf} + ${${UN}StrRep} $0 $0 " ;" ";" ; Remove ';' + ${Loop} + ${Do} + ${${UN}StrStr} $7 $0 "; " + ${If} $7 == "" + ${ExitDo} + ${EndIf} + ${${UN}StrRep} $0 $0 "; " ";" ; Remove ';' + ${Loop} + ${Do} + ${${UN}StrStr} $7 $0 ";;" + ${If} $7 == "" + ${ExitDo} + ${EndIf} + ${${UN}StrRep} $0 $0 ";;" ";" + ${Loop} + + ; Remove a leading or trailing semicolon from EnvVar + StrCpy $7 $0 1 0 + ${If} $7 == ";" + StrCpy $0 $0 "" 1 ; Change ';' to '' + ${EndIf} + StrLen $6 $0 + IntOp $6 $6 - 1 + StrCpy $7 $0 1 $6 + ${If} $7 == ";" + StrCpy $0 $0 $6 ; Change ';' to '' + ${EndIf} + ; DetailPrint "Scrubbed $1: [$0]" ; Uncomment to debug + ${EndIf} + + /* Step 3. Remove all instances of the target path/string (even if "A" or "P") + $6 = bool flag (1 = found and removed PathString) + $7 = a string (e.g. path) delimited by semicolon(s) + $8 = entry counter starting at 0 + $9 = copy of $0 + $R0 = tempChar */ + + ${If} $5 != "" ; If EnvVar is not empty ... + StrCpy $9 $0 + StrCpy $0 "" + StrCpy $8 0 + StrCpy $6 0 + + ${Do} + ${${UN}StrTok} $7 $9 ";" $8 "0" ; $7 = next entry, $8 = entry counter + + ${If} $7 == "" ; If we've run out of entries, + ${ExitDo} ; were done + ${EndIf} ; + + ; Remove leading and trailing spaces from this entry (critical step for Action=Remove) + ${Do} + StrCpy $R0 $7 1 + ${If} $R0 != " " + ${ExitDo} + ${EndIf} + StrCpy $7 $7 "" 1 ; Remove leading space + ${Loop} + ${Do} + StrCpy $R0 $7 1 -1 + ${If} $R0 != " " + ${ExitDo} + ${EndIf} + StrCpy $7 $7 -1 ; Remove trailing space + ${Loop} + ${If} $7 == $4 ; If string matches, remove it by not appending it + StrCpy $6 1 ; Set 'found' flag + ${ElseIf} $7 != $4 ; If string does NOT match + ${AndIf} $0 == "" ; and the 1st string being added to $0, + StrCpy $0 $7 ; copy it to $0 without a prepended semicolon + ${ElseIf} $7 != $4 ; If string does NOT match + ${AndIf} $0 != "" ; and this is NOT the 1st string to be added to $0, + StrCpy $0 $0;$7 ; append path to $0 with a prepended semicolon + ${EndIf} ; + + IntOp $8 $8 + 1 ; Bump counter + ${Loop} ; Check for duplicates until we run out of paths + ${EndIf} + + ; Step 4: Perform the requested Action + ; + ${If} $2 != "R" ; If Append or Prepend + ${If} $6 == 1 ; And if we found the target + DetailPrint "Target is already present in $1. It will be removed and" + ${EndIf} + ${If} $0 == "" ; If EnvVar is (now) empty + StrCpy $0 $4 ; just copy PathString to EnvVar + ${If} $6 == 0 ; If found flag is either 0 + ${OrIf} $6 == "" ; or blank (if EnvVarName is empty) + DetailPrint "$1 was empty and has been updated with the target" + ${EndIf} + ${ElseIf} $2 == "A" ; If Append (and EnvVar is not empty), + StrCpy $0 $0;$4 ; append PathString + ${If} $6 == 1 + DetailPrint "appended to $1" + ${Else} + DetailPrint "Target was appended to $1" + ${EndIf} + ${Else} ; If Prepend (and EnvVar is not empty), + StrCpy $0 $4;$0 ; prepend PathString + ${If} $6 == 1 + DetailPrint "prepended to $1" + ${Else} + DetailPrint "Target was prepended to $1" + ${EndIf} + ${EndIf} + ${Else} ; If Action = Remove + ${If} $6 == 1 ; and we found the target + DetailPrint "Target was found and removed from $1" + ${Else} + DetailPrint "Target was NOT found in $1 (nothing to remove)" + ${EndIf} + ${If} $0 == "" + DetailPrint "$1 is now empty" + ${EndIf} + ${EndIf} + + ; Step 5: Update the registry at RegLoc with the updated EnvVar and announce the change + ; + ClearErrors + ${If} $3 == HKLM + WriteRegExpandStr ${hklm_all_users} $1 $0 ; Write it in all users section + ${ElseIf} $3 == HKCU + WriteRegExpandStr ${hkcu_current_user} $1 $0 ; Write it to current user section + ${EndIf} + + IfErrors 0 +4 + MessageBox MB_OK|MB_ICONEXCLAMATION "Could not write updated $1 to $3" + DetailPrint "Could not write updated $1 to $3" + Goto EnvVarUpdate_Restore_Vars + + ; "Export" our change + SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000 + + EnvVarUpdate_Restore_Vars: + ; + ; Restore the user's variables and return ResultVar + Pop $R0 + Pop $9 + Pop $8 + Pop $7 + Pop $6 + Pop $5 + Pop $4 + Pop $3 + Pop $2 + Pop $1 + Push $0 ; Push my $0 (ResultVar) + Exch + Pop $0 ; Restore his $0 + +FunctionEnd + +!macroend ; EnvVarUpdate UN +!insertmacro EnvVarUpdate "" +!insertmacro EnvVarUpdate "un." +;----------------------------------- EnvVarUpdate end---------------------------------------- + +!verbose pop +!endif diff --git a/tools/niminst/nsis.tmpl b/tools/niminst/nsis.tmpl index 7249dca638..c4270081e2 100644 --- a/tools/niminst/nsis.tmpl +++ b/tools/niminst/nsis.tmpl @@ -3,170 +3,253 @@ # result = "; NSIS script generated by niminst\n" & # "; To regenerate run ``niminst nsis`` or ``koch nsis``\n" -!define PRODUCT_NAME "?c.displayName" -!define PRODUCT_VERSION "?c.version" -!define PRODUCT_PUBLISHER "?c.authors" -!define PRODUCT_DIR_REGKEY "Software\Microsoft\Windows\CurrentVersion\App Paths\?{c.name}.exe" -!define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" -!define PRODUCT_UNINST_ROOT_KEY "HKCU" -!define PRODUCT_STARTMENU_REGVAL "NSIS:StartMenuDir" +;-------------------------------- +; Included headers + ; Modern User Interface 2.0 Header + !include "MUI2.nsh" -; MUI 1.67 compatible ------ -!include "MUI.nsh" -!define MULTIUSER_EXECUTIONLEVEL Standard -!include "MultiUser.nsh" -!include "zipdll.nsh" + ; File Functions Header, used to get the current drive root. + !include "FileFunc.nsh" -InstallDir "$LOCALAPPDATA\?{c.name}" + ; *Patched* Environment Variable Manipulation Header, used to add + ; tools to the user's PATH environment variable. + !include "EnvVarUpdate.nsh" -; MUI Settings -!define MUI_ABORTWARNING -!define MUI_ICON "${NSISDIR}\Contrib\Graphics\Icons\modern-install.ico" -!define MUI_UNICON "${NSISDIR}\Contrib\Graphics\Icons\modern-uninstall.ico" - -; Welcome page -!insertmacro MUI_PAGE_WELCOME -; License page -!insertmacro MUI_PAGE_LICENSE "?{expandFilename(c.license)}" -; Components page -!insertmacro MUI_PAGE_COMPONENTS -; Directory page -!insertmacro MUI_PAGE_DIRECTORY -; Start menu page -var ICONS_GROUP -!define MUI_STARTMENUPAGE_NODISABLE -!define MUI_STARTMENUPAGE_DEFAULTFOLDER "?c.displayName" -!define MUI_STARTMENUPAGE_REGISTRY_ROOT "${PRODUCT_UNINST_ROOT_KEY}" -!define MUI_STARTMENUPAGE_REGISTRY_KEY "${PRODUCT_UNINST_KEY}" -!define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "${PRODUCT_STARTMENU_REGVAL}" -!insertmacro MUI_PAGE_STARTMENU Application $ICONS_GROUP -; Instfiles page -!insertmacro MUI_PAGE_INSTFILES -; Finish page -; !define MUI_FINISHPAGE_RUN "$INSTDIR\start.bat" -!insertmacro MUI_PAGE_FINISH - -; Uninstaller pages -!insertmacro MUI_UNPAGE_INSTFILES - -; Language files -!insertmacro MUI_LANGUAGE "English" - -; MUI end ------ - -Name "${PRODUCT_NAME} ${PRODUCT_VERSION}" -OutFile "?{c.name}_?{c.version}.exe" -; InstallDir "$PROGRAMFILES\?c.displayName" -InstallDirRegKey HKCU "${PRODUCT_DIR_REGKEY}" "" -ShowInstDetails show -ShowUnInstDetails show - -Section "Core" SEC0 - SetOverwrite ifnewer - SetOutPath "$INSTDIR" - #for i in low(TFileCategory)..fcWindows: - # for f in items(c.cat[i]): - SetOutPath "$INSTDIR\?{splitFile(f).dir.toWin}" - File "?{expandFilename(f).toWin}" - # end for - #end for +;-------------------------------- +; Global variables and defines + !define PRODUCT_NAME "?c.displayName" + !define PRODUCT_VERSION "?c.version" + !define PRODUCT_PUBLISHER "?c.authors" + !define PRODUCT_DIR_REGKEY "Software\Microsoft\Windows\CurrentVersion\App Paths\?{c.name}.exe" + !define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" + !define PRODUCT_UNINST_ROOT_KEY "HKCU" + !define PRODUCT_STARTMENU_REGVAL "NSIS:StartMenuDir" -; Shortcuts - !insertmacro MUI_STARTMENU_WRITE_BEGIN Application - CreateDirectory "$SMPROGRAMS\$ICONS_GROUP" +;-------------------------------- +; General Setup Information - #if c.app == appConsole: - CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\?{c.displayName}.lnk" "$INSTDIR\start.bat" - CreateShortCut "$DESKTOP\?{c.displayName}.lnk" "$INSTDIR\start.bat" - #else: - CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\?{c.displayName}.lnk" "$INSTDIR\?{c.name}.exe" - CreateShortCut "$DESKTOP\?{c.displayName}.lnk" "$INSTDIR\?{c.name}.exe" - #end if - #for f in items(c.cat[fcDocStart]): - CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\?{splitFile(f).name}.lnk" "$INSTDIR\?{f.toWin}" - #end for + ; Name and output file + Name "?{c.name} ?{c.version}" + OutFile "?{c.name}_?{c.version}.exe" - !insertmacro MUI_STARTMENU_WRITE_END -SectionEnd + ; Default installation folder + ; This is changed later (in .onInit) to the root directory, if possible. + InstallDir "$LOCALAPPDATA\?{c.name}" + + ; Get installation folder from registry if available + InstallDirRegKey HKCU "Software\c.name\c.version" "" -#var i = 0 -#for download in c.downloads: -# inc i -# let d = download.split('|') -# if d.len != 5 and d.len != 6: -# quit("download string needs 5..6 parts: " & download) -# end if -# let sectionName = d[0] -# let dir = d[1] -# let zipName = d[2] -# let size = d[3] -# let url = d[4] - Section /o "?sectionName" SEC?i + ; Request user level application privileges. + RequestExecutionLevel user - AddSize ?size + ; Allow installation to the root drive directory. + AllowRootDirInstall true - NSISdl::download "?url" "$INSTDIR\?zipName" - Pop $0 - ${If} $0 == "success" - ZipDLL::extractall "$INSTDIR\?zipName" "$INSTDIR\?dir" - Delete "$INSTDIR\?zipName" - ${Else} - MessageBox mb_iconstop "Error: $0" ;Show cancel/error message - ${EndIf} + ; Maximum compression! + SetCompressor /SOLID /FINAL lzma -# if d.len >= 6: -# let startMenuEntry = d[5] -# let e = splitFile(startMenuEntry).name.capitalize - CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\?{e}.lnk" "$INSTDIR\?dir\?{startMenuEntry.toWin}" -# end if + ; Installer and Uninstaller Icons + ; Icon "nimrod.ico" + ; UninstallIcon "nimrod.ico" -; Shortcuts - !insertmacro MUI_STARTMENU_WRITE_BEGIN Application - !insertmacro MUI_STARTMENU_WRITE_END + ; Set installation details to be shown by default + ShowInstDetails show + ShowUnInstDetails show + +;-------------------------------- +; Interface Settings + + ; Warn the user if aborting during installation/uninstallation + !define MUI_ABORTWARNING + !define MUI_UNABORTWARNING + + ; Don't show a description for sections + !define MUI_COMPONENTSPAGE_NODESC + +;-------------------------------- +; Pages + + ; Setup the installer pages + !insertmacro MUI_PAGE_WELCOME + !insertmacro MUI_PAGE_LICENSE "?{expandFilename(c.license)}" + !insertmacro MUI_PAGE_COMPONENTS + !insertmacro MUI_PAGE_DIRECTORY + + ; Setup the start menu entry page + var ICONS_GROUP + !define MUI_STARTMENUPAGE_DEFAULTFOLDER "?{c.displayName}" + !define MUI_STARTMENUPAGE_REGISTRY_ROOT "${PRODUCT_UNINST_ROOT_KEY}" + !define MUI_STARTMENUPAGE_REGISTRY_KEY "${PRODUCT_UNINST_KEY}" + !define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "${PRODUCT_STARTMENU_REGVAL}" + !insertmacro MUI_PAGE_STARTMENU Application $ICONS_GROUP + + !insertmacro MUI_PAGE_INSTFILES + !insertmacro MUI_PAGE_FINISH + + ; Setup the uninstaller pages + !insertmacro MUI_UNPAGE_CONFIRM + !insertmacro MUI_UNPAGE_INSTFILES + +;-------------------------------- +;Languages + + !insertmacro MUI_LANGUAGE "English" + +;-------------------------------- +;Installer Sections + + ; The core section. This is comprised of a base Nim installation, + ; such as what would be retrieved via git, and an already bootstrapped + ; Nim binary. + Section "Core Files" CoreSection + ; This is a mandotory section + SectionIn RO + + ; Output files to the base installation directory + SetOutPath "$INSTDIR" + + ; Only overwrite newer files + SetOverwrite ifnewer + + ; Write all the files to the output directory. + #for i in low(TFileCategory)..fcWindows: + # for f in items(c.cat[i]): + SetOutPath "$INSTDIR\?{splitFile(f).dir.toWin}" + File "?{expandFilename(f).toWin}" + # end for + #end for + + ; Write out the uninstaller + WriteUninstaller "$INSTDIR\uninstaller.exe" SectionEnd -#end -Section -AdditionalIcons - SetOutPath $INSTDIR - !insertmacro MUI_STARTMENU_WRITE_BEGIN Application - CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\Uninstall.lnk" "$INSTDIR\uninst.exe" - !insertmacro MUI_STARTMENU_WRITE_END -SectionEnd + Section "-Add Registry Keys" RegistrySection + ; Write application registry keys + WriteRegStr HKCU "${PRODUCT_DIR_REGKEY}" "" "$INSTDIR\bin\?{c.name}.exe" + WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "$(^Name)" + WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\uninst.exe" + WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayIcon" "$INSTDIR\bin\?{c.name}.exe" + WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayVersion" "${PRODUCT_VERSION}" + WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "Publisher" "${PRODUCT_PUBLISHER}" + ; Reset the output path + SetOutPath "$INSTDIR" + SectionEnd -Section -Post - WriteUninstaller "$INSTDIR\uninst.exe" - WriteRegStr HKCU "${PRODUCT_DIR_REGKEY}" "" "$INSTDIR\bin\?{c.name}.exe" - WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "$(^Name)" - WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\uninst.exe" - WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayIcon" "$INSTDIR\bin\?{c.name}.exe" - WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayVersion" "${PRODUCT_VERSION}" - WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "Publisher" "${PRODUCT_PUBLISHER}" -SectionEnd + ; Section for adding the shortcuts related to files and applications + Section "-Setup Shortcuts" ShortcutsSection + !insertmacro MUI_STARTMENU_WRITE_BEGIN Application + CreateDirectory "$SMPROGRAMS\$ICONS_GROUP" -Function .onInit - !insertmacro MULTIUSER_INIT -FunctionEnd + #if c.app == appConsole: + CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\?{c.displayName}.lnk" "$INSTDIR\start.bat" + CreateShortCut "$DESKTOP\?{c.displayName}.lnk" "$INSTDIR\start.bat" + #else: + CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\?{c.displayName}.lnk" "$INSTDIR\?{c.name}.exe" + CreateShortCut "$DESKTOP\?{c.displayName}.lnk" "$INSTDIR\?{c.name}.exe" + #end if -Function un.onUninstSuccess - HideWindow - MessageBox MB_ICONINFORMATION|MB_OK "Uninstall was completed successfully." -FunctionEnd + ; Add shortcuts for the documentation + #for f in items(c.cat[fcDocStart]): + CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\?{splitFile(f).name}.lnk" "$INSTDIR\?{f.toWin}" + #end for -Function un.onInit - MessageBox MB_ICONQUESTION|MB_YESNO|MB_DEFBUTTON2 "Remove $(^Name) from your computer." IDYES +2 - Abort - !insertmacro MULTIUSER_UNINIT -FunctionEnd + ; Write the shortcut to the uninstaller + CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\Uninstall.lnk" "$INSTDIR\uninstaller.exe" + !insertmacro MUI_STARTMENU_WRITE_END + SectionEnd -Section Uninstall - !insertmacro MUI_STARTMENU_GETFOLDER "Application" $ICONS_GROUP - Delete "$DESKTOP\?{c.displayName}.lnk" + ; Section for adding tools to the PATH variable + Section "Setup Path Environment" PathSection + ${EnvVarUpdate} $R0 "PATH" "A" "HKCU" "$INSTDIR\dist\mingw" + ${EnvVarUpdate} $R0 "PATH" "A" "HKCU" "$INSTDIR\bin" + ${EnvVarUpdate} $R0 "PATH" "A" "HKCU" "$INSTDIR\dist\babel" + SectionEnd - RMDir /r "$SMPROGRAMS\$ICONS_GROUP" - RMDir /r "$INSTDIR" + ; The downloadable sections. These sections are automatically generated by + ; niminst and the template filters. + #var i = 0 + #for download in c.downloads: + # inc i + # let d = download.split('|') + # if d.len != 5 and d.len != 6: + # quit("download string needs 5..6 parts: " & download) + # end if + # let sectionName = d[0] + # let dir = d[1] + # let zipName = d[2] + # let size = d[3] + # let url = d[4] + Section /o "?sectionName" ?{i}Section + ; Add the section size to the total size. + AddSize ?size - DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" - DeleteRegKey HKCU "${PRODUCT_DIR_REGKEY}" - SetAutoClose true -SectionEnd \ No newline at end of file + ; Download the file, and if successful, extract it to the given directory + ; otherwise, + retry: + NSISdl::download "?url" "$TEMP\?zipName" + Pop $0 + ${If} $0 == "success" + ZipDLL::extractall "$TEMP\?zipName" "$INSTDIR\?dir" + Delete "$TEMP\?zipName" + ${Else} + MessageBox MB_ICONSTOP|MB_ABORTRETRYIGNORE "Error: $0" IDRETRY retry IDIGNORE ignore + abort + ${EndIf} + + # if d.len >= 6: + # let startMenuEntry = d[5] + # let e = splitFile(startMenuEntry).name.capitalize + CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\?{e}.lnk" "$INSTDIR\?dir\?{startMenuEntry.toWin}" + # end if + + ; Shortcuts + !insertmacro MUI_STARTMENU_WRITE_BEGIN Application + !insertmacro MUI_STARTMENU_WRITE_END + ignore: + SectionEnd + #end + +;-------------------------------- +; Section Descriptions + ; Series of strings describing each section + ; LangString DESC_CoreSection ${LANG_ENGLISH} "Core Nim files" + + ; The macros to actually insert the descriptions into the sections. + ; Each description above should have a corresponding MUI_DESCRIPTION_TEXT + ; macro linking the section to the description. + ; !insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN + ; !insertmacro MUI_DESCRIPTION_TEXT ${CoreSection} $(DESC_CoreSection) + ; !insertmacro MUI_FUNCTION_DESCRIPTION_END + + +;-------------------------------- +; Uninstaller Sections + + Section "Uninstall" + ; Remove previously created shortcuts + !insertmacro MUI_STARTMENU_GETFOLDER "Application" $ICONS_GROUP + Delete "$DESKTOP\?{c.displayName}.lnk" + + ; Remove installed application files + RMDir /r "$SMPROGRAMS\$ICONS_GROUP" + RMDir /r "$INSTDIR" + + ; Remove the previously created registry key + DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" + DeleteRegKey HKCU "${PRODUCT_DIR_REGKEY}" + SetAutoClose true + + ; Remove entries from the PATH environment variable + ${un.EnvVarUpdate} $R0 "PATH" "R" "HKCU" "$INSTDIR\dist\mingw" + ${un.EnvVarUpdate} $R0 "PATH" "R" "HKCU" "$INSTDIR\bin" + ${un.EnvVarUpdate} $R0 "PATH" "R" "HKCU" "$INSTDIR\dist\babel" + SectionEnd + +;-------------------------------- +; Function hooks + + Function .onInit + ${GetRoot} "$EXEDIR" $R0 + strCpy $INSTDIR "$R0\?{c.name}" + FunctionEnd \ No newline at end of file From 6f1b33e11c03dfa7dfcbccaf9b7fe2265d4eca26 Mon Sep 17 00:00:00 2001 From: Araq Date: Sun, 19 Oct 2014 10:49:56 +0200 Subject: [PATCH 231/234] readme.txt is not readme.md --- compiler/nimrod.ini | 6 ++--- readme.txt | 60 +++++---------------------------------------- 2 files changed, 8 insertions(+), 58 deletions(-) diff --git a/compiler/nimrod.ini b/compiler/nimrod.ini index 82d5ea2aed..c182f82759 100644 --- a/compiler/nimrod.ini +++ b/compiler/nimrod.ini @@ -62,10 +62,8 @@ Files: "compiler/readme.txt" Files: "compiler/nimrod.ini" Files: "compiler/nimrod.cfg" Files: "compiler/*.nim" -Files: "compiler/c2nim/*.nim" -Files: "compiler/c2nim/*.cfg" -Files: "compiler/pas2nim/*.nim" -Files: "compiler/pas2nim/*.cfg" +Files: "compiler/nimfix/*.nim" +Files: "compiler/nimfix/*.cfg" [Lib] diff --git a/readme.txt b/readme.txt index 3f6aef05cd..f9e5054fe7 100644 --- a/readme.txt +++ b/readme.txt @@ -1,60 +1,12 @@ -# Nimrod Compiler -This repo contains the Nimrod compiler, Nimrod's stdlib, tools and +This package contains the Nimrod compiler, Nimrod's stdlib, tools and documentation. -## Compiling -Compiling the Nimrod compiler is quite straightforward. Because -the Nimrod compiler itself is written in the Nimrod programming language -the C source of an older version of the compiler are needed to bootstrap the -latest version. The C sources are available in a separate repo [here](http://github.com/nimrod-code/csources). +Nimrod is a compiled, garbage-collected systems programming language which has +an excellent productivity/performance ratio. Nimrod's design focuses on +efficiency, expressiveness, elegance (in the order of priority). -Pre-compiled snapshots of the compiler are also available on -[Nimbuild](http://build.nimrod-lang.org/). Your platform however may not -currently be built for. +Read install.txt for instructions of how to build and install it. -The compiler currently supports the following platform and architecture -combinations: - - * Windows (Windows XP or greater) - x86 and x86_64 - * Linux (most, if not all, distributions) - x86, x86_64, ppc64 and armv6l - * Mac OS X 10.04 or higher - x86, x86_64 and ppc64 - -In reality a lot more are supported, however they are not tested regularly. - -To build from source you will need: - - * gcc 3.x or later recommended. Other alternatives which may work - are: clang, Visual C++, Intel's C++ compiler - * git or wget - -If you are on a fairly modern *nix system, the following steps should work: - -``` -$ git clone git://github.com/Araq/Nimrod.git -$ cd Nimrod -$ git clone --depth 1 git://github.com/nimrod-code/csources -$ cd csources && ./build.sh -$ cd .. -$ bin/nimrod c koch -$ ./koch boot -d:release -``` - -``koch install [dir]`` may then be used to install Nimrod, or you can simply -add it to your PATH. More ``koch`` related options are documented in -[doc/koch.txt](doc/koch.txt). - -The above steps can be performed on Windows in a similar fashion, the -``build.bat`` and ``build64.bat`` (for x86_64 systems) are provided to be used -instead of ``build.sh``. - -## Getting help -A [forum](http://forum.nimrod-lang.org/) is available if you have any -questions, and you can also get help in the IRC channel on -[Freenode](irc://irc.freenode.net/nimrod) in #nimrod. If you ask questions on -[StackOverflow use the nimrod -tag](http://stackoverflow.com/questions/tagged/nimrod). - -## License The compiler and the standard library are licensed under the MIT license, except for some modules where the documentation suggests otherwise. This means that you can use any license for your own programs developed with Nimrod, @@ -62,5 +14,5 @@ allowing you to create commercial applications. Read copying.txt for more details. -Copyright (c) 2004-2014 Andreas Rumpf. +Copyright (c) 2006-2014 Andreas Rumpf. All rights reserved. From dc8d8ebb79027b1414354cdd02ad90737e195501 Mon Sep 17 00:00:00 2001 From: Araq Date: Sun, 19 Oct 2014 16:07:14 +0200 Subject: [PATCH 232/234] website updates for 0.9.6 --- compiler/nimrod.ini | 2 +- config/nimrod.cfg | 5 -- install.txt | 2 - koch.nim | 29 +++++----- web/download.txt | 125 +++++++------------------------------------- web/news.txt | 8 +-- web/ticker.txt | 5 ++ 7 files changed, 45 insertions(+), 131 deletions(-) diff --git a/compiler/nimrod.ini b/compiler/nimrod.ini index bc7549da0e..ae1c6053f1 100644 --- a/compiler/nimrod.ini +++ b/compiler/nimrod.ini @@ -37,7 +37,6 @@ Files: "config/nimdoc.cfg" Files: "config/nimdoc.tex.cfg" [Documentation] -; Files: "doc/*.txt" ; Files: "doc/*.html" ; Files: "doc/*.cfg" ; Files: "doc/*.pdf" @@ -65,6 +64,7 @@ Files: "compiler/readme.txt" Files: "compiler/nimrod.ini" Files: "compiler/nimrod.cfg" Files: "compiler/*.nim" +Files: "doc/*.txt" Files: "compiler/nimfix/*.nim" Files: "compiler/nimfix/*.cfg" diff --git a/config/nimrod.cfg b/config/nimrod.cfg index df3835ace7..075b65d631 100644 --- a/config/nimrod.cfg +++ b/config/nimrod.cfg @@ -130,10 +130,5 @@ vcc.options.always = "/nologo" vcc.options.speed = "/Ox /arch:SSE2" vcc.options.size = "/O1" -# Configuration for the Digital Mars C/C++ compiler: -@if windows: - dmc.path = r"$nimrod\dist\dm\bin" -@end - # Configuration for the Tiny C Compiler: tcc.options.always = "-w" diff --git a/install.txt b/install.txt index 2883c8495d..4543e4ecee 100644 --- a/install.txt +++ b/install.txt @@ -58,8 +58,6 @@ Currently, the following C compilers are supported under Windows: | http://www.mingw.org/download.shtml - | LLVM with Clang or GNU C/C++ frontend | http://llvm.org/releases/download.html -- | Digital Mars C++ - | http://www.digitalmars.com/download/freecompiler.html However, most testing is done with GCC. diff --git a/koch.nim b/koch.nim index b7cf65ff7e..f05b9203a4 100644 --- a/koch.nim +++ b/koch.nim @@ -43,7 +43,7 @@ Possible Commands: web generates the website csource [options] builds the C sources for installation zip builds the installation ZIP package - inno [options] builds the Inno Setup installer (for Windows) + nsis [options] builds the NSIS Setup installer (for Windows) tests [options] run the testsuite update updates nimrod to the latest version from github (compile koch with -d:withUpdate to enable) @@ -77,6 +77,14 @@ proc tryExec(cmd: string): bool = echo(cmd) result = execShellCmd(cmd) == 0 +proc safeRemove(filename: string) = + if existsFile(filename): removeFile(filename) + +proc copyExe(source, dest: string) = + safeRemove(dest) + copyFile(dest=dest, source=source) + inclFilePermissions(dest, {fpUserExec}) + const compileNimInst = "-d:useLibzipSrc tools/niminst/niminst" @@ -94,12 +102,15 @@ proc buildTool(toolname, args: string) = exec("$# cc $# $#" % [findNim(), args, toolname]) copyFile(dest="bin"/ splitFile(toolname).name.exe, source=toolname.exe) -proc inno(args: string) = +proc nsis(args: string) = # make sure we have generated the niminst executables: buildTool("tools/niminst/niminst", args) buildTool("tools/nimgrep", args) - exec("tools" / "niminst" / "niminst --var:version=$# inno compiler/nimrod" % - NimrodVersion) + # produce 'nimrod_debug.exe': + exec "nimrod c compiler" / "nimrod.nim" + copyExe("compiler/nimrod".exe, "bin/nimrod_debug".exe) + exec(("tools" / "niminst" / "niminst --var:version=$# --var:mingw=mingw32" & + " nsis compiler/nimrod") % NimrodVersion) proc install(args: string) = exec("$# cc -r $# --var:version=$# scripts compiler/nimrod.ini" % @@ -137,16 +148,8 @@ proc findStartNimrod: string = echo("Found no nimrod compiler and every attempt to build one failed!") quit("FAILURE") -proc safeRemove(filename: string) = - if existsFile(filename): removeFile(filename) - proc thVersion(i: int): string = result = ("compiler" / "nimrod" & $i).exe - -proc copyExe(source, dest: string) = - safeRemove(dest) - copyFile(dest=dest, source=source) - inclFilePermissions(dest, {fpUserExec}) proc boot(args: string) = var output = "compiler" / "nimrod".exe @@ -304,7 +307,7 @@ of cmdArgument: of "web": web(op.cmdLineRest) of "csource", "csources": csource(op.cmdLineRest) of "zip": zip(op.cmdLineRest) - of "inno": inno(op.cmdLineRest) + of "nsis": nsis(op.cmdLineRest) of "install": install(op.cmdLineRest) of "test", "tests": tests(op.cmdLineRest) of "update": diff --git a/web/download.txt b/web/download.txt index 5577882174..31777fad00 100644 --- a/web/download.txt +++ b/web/download.txt @@ -1,127 +1,39 @@ -You can download the latest version of the Nimrod compiler here. You can -use the binaries provided or build from source. - -Binaries -======== - -All installers and archives contain the html documentation and tools -(nimgrep, c2nim and babel). +You can download the latest version of the Nimrod compiler here. **Note:** The Nimrod compiler requires a C compiler to compile software. On Windows we recommend that you use `Mingw-w64 `_. GCC is recommended on Linux and clang on Mac OS X. -Installers ----------- -The "full" version includes a full mingw distribution which includes a C -compiler. The "slim" version lacks this. +Binaries +======== -* Full (i386, 32bit): ``_ +Unfortunately for now we only provide 32 bit builds for +Windows: `nimrod_0.9.6.exe `_ - .. raw:: html -

- SHA256: dca7c63d0c1861d2d7c51b2e7a29fa98371750a10ab282d5df9de22a07719c24 -

-* Slim (i386, 32bit): ``_ +Installation based on generated C code +====================================== - .. raw:: html -

- SHA256: c0fcd1201bd20fad1e14b9d2cc2529494057068de1dd01f871cf129f088a8242 -

+This installation method is the preferred way for Linux, Mac OS X, and other Unix +like systems. Binary packages may be provided later. -* Full (amd64, 64bit): ``_ - .. raw:: html -

- SHA256: af9d478c2f3361e0f238fcb07fa8e7ae5821938c0f9063c6670e925c9ae9d16e -

+Download `nimrod_0.9.6.zip `_, extract it and follow +these instructions: -* Slim (amd64, 64bit): ``_ +* sh build.sh +* Add ``$your_install_dir/bin`` to your PATH. - .. raw:: html -

- SHA256: 90c380721a46be2b9b8d5437187f701940aefc2e1fb9722dbc543f5c5a3bb85e -

+There are other ways to install Nimrod (like using the ``install.sh`` script), +but these tend to cause more problems. -Archives --------- -Windows -~~~~~~~ +Installation from github +======================== -The "full" version includes a full mingw distribution which includes a C -compiler. The "slim" version lacks this. - -* Full (i386, 32bit): ``_ - - .. raw:: html -

- SHA256: 8ee18faaa3a3d5df482c7abd6aa7ea87a350d7328b80ce1e2d486b59a7a93956 -

- -* Slim (i386, 32bit): ``_ - - .. raw:: html -

- SHA256: 7024fb8ad8f98c0bd4949ae36ed11b52b4e401754bbd62a11199d6dc8628d857 -

- -* Full (amd64, 64bit): ``_ - - .. raw:: html -

- SHA256: cb33cacc1a84fec771323d24cb6d9795f4803882466a9f417b424990aa49e18a -

- -* Slim (amd64, 64bit): ``_ - - .. raw:: html -

- SHA256: fcf877e4bd1ebfa214749af6e4811cd8539af19f1d7b23017e4bd7f6cbfb3eba -

- -Linux -~~~~~ - -* Linux (i386, 32bit): ``_ - - .. raw:: html -

- SHA256: 79DD337A77AC4313A75F2C5EED8252F00BBBDEB1E0C3504660D4A52EA63DBA92 -

-* Linux (amd64, 64bit): ``_ - - .. raw:: html -

- SHA256: 6F6CB3C727BA8059B7605C02942AE7910C20C2A3DC6A8A600D90D50FE61F0D8C -

-* Linux (ppc64, 64bit): ``_ - - .. raw:: html -

- SHA256: 5DAC2D9F7F545929E04540E6E2594C68FC3126A3B2F7B1FA7DBA5E295B4A7D31 -

- -Mac OS X -~~~~~~~~ - -* Mac OS X (amd64, 64bit): ``_ - - .. raw:: html -

- SHA256: E6F3A8E434DF3E89686F043954C6DFC09ABEBC0FC09D3B9A6B35C2B3102F7C3C -

- -If a binary for your platform is not available then you must build from source. -Bleeding edge binaries are available from the `Nimrod build farm `_. - -Source -====== - -Starting with 0.9.4 we now advise people to build directly from the +It is also possible to build directly from the github `master `_ branch:: git clone -b master git://github.com/Araq/Nimrod.git @@ -135,4 +47,3 @@ github `master `_ branch:: The ``master`` branch always contains the latest stable version of the compiler. If you want bleeding edge then switch to the ``devel`` branch and follow the same instructions outlined above. - diff --git a/web/news.txt b/web/news.txt index 27262309ee..acf1930888 100644 --- a/web/news.txt +++ b/web/news.txt @@ -2,10 +2,10 @@ News ==== -2014-10-12 Version 0.9.6 released -================================= +2014-10-19 Nimrod version 0.9.6 released +======================================== -**Note: This is the last release of Nimrod. The language has been renamed to +**Note: 0.9.6 is the last release of Nimrod. The language has been renamed to Nim. Nim slightly breaks compatibility.** This is a maintenance release. The upcoming 0.10.0 release has @@ -42,6 +42,8 @@ Language Additions - This version introduces the new ``deprecated`` pragma statement that is used to handle the upcoming massive amount of symbol renames. +- ``spawn`` can now wrap proc that have a return value. It then returns a flow + variable of the wrapped return type. Library Additions diff --git a/web/ticker.txt b/web/ticker.txt index f06b005727..98ad25905b 100644 --- a/web/ticker.txt +++ b/web/ticker.txt @@ -1,3 +1,8 @@ + +

Oct 19, 2014

+

Nimrod version 0.9.6 has been released!

+
+

Apr 21, 2014

Nimrod version 0.9.4 has been released!

From 4cca562c4a5386656c85008ba17865b67b479fc5 Mon Sep 17 00:00:00 2001 From: Araq Date: Sun, 19 Oct 2014 16:40:42 +0200 Subject: [PATCH 233/234] minor updates to koch.nim --- koch.nim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/koch.nim b/koch.nim index f05b9203a4..8385ac84e9 100644 --- a/koch.nim +++ b/koch.nim @@ -93,9 +93,9 @@ proc csource(args: string) = [args, NimrodVersion, compileNimInst, findNim()]) proc zip(args: string) = - exec("$3 cc -r $2 --var:version=$1 scripts compiler/nimrod.ini" % + exec("$3 cc -r $2 --var:version=$1 --var:mingw=mingw32 scripts compiler/nimrod.ini" % [NimrodVersion, compileNimInst, findNim()]) - exec("$# --var:version=$# zip compiler/nimrod.ini" % + exec("$# --var:version=$# --var:mingw=mingw32 zip compiler/nimrod.ini" % ["tools/niminst/niminst".exe, NimrodVersion]) proc buildTool(toolname, args: string) = From 2e4447ca852b4f462814e95c72c2b0dd7893bd6f Mon Sep 17 00:00:00 2001 From: Araq Date: Sun, 19 Oct 2014 20:05:01 +0200 Subject: [PATCH 234/234] documentation improvements --- doc/manual.txt | 2 ++ doc/tut2.txt | 12 ------------ tools/nimweb.nim | 13 +++++++++---- 3 files changed, 11 insertions(+), 16 deletions(-) diff --git a/doc/manual.txt b/doc/manual.txt index 6aed72ce75..c150d27e22 100644 --- a/doc/manual.txt +++ b/doc/manual.txt @@ -4384,6 +4384,8 @@ helper distinct or object type has to be used for one pointer type. operator `=` ------------ +**Note**: Overriding the assignment operator has not yet been implemented. + This operator is the assignment operator. Note that in the contexts like ``let v = expr``, ``var v = expr``, ``parameter = defaultValue`` or for parameter passing no assignment is performed. The ``override`` pragma is diff --git a/doc/tut2.txt b/doc/tut2.txt index 2f42bcefc5..582a6b3e4d 100644 --- a/doc/tut2.txt +++ b/doc/tut2.txt @@ -438,18 +438,6 @@ module. Example: echo "Got exception ", repr(e), " with message ", msg -Exception hierarchy -------------------- - -If you want to create your own exceptions you can inherit from E_Base, but you -can also inherit from one of the existing exceptions if they fit your purpose. -The exception tree is: - -.. include:: exception_hierarchy_fragment.txt - -See the `system `_ module for a description of each exception. - - Annotating procs with raised exceptions --------------------------------------- diff --git a/tools/nimweb.nim b/tools/nimweb.nim index d76c5e354a..00faecc01b 100644 --- a/tools/nimweb.nim +++ b/tools/nimweb.nim @@ -239,7 +239,7 @@ proc mexec(cmds: openarray[string], processors: int) = sexec(cmds) return - if 0 != execProcesses(cmds, {poStdErrToStdOut, poParentStreams, poEchoCmd}): + if execProcesses(cmds, {poStdErrToStdOut, poParentStreams, poEchoCmd}) != 0: echo "external program failed, retrying serial work queue for logs!" sexec(cmds) @@ -289,8 +289,10 @@ proc buildPdfDoc(c: var TConfigData, destPath: string) = exec("pdflatex " & changeFileExt(d, "tex")) exec("pdflatex " & changeFileExt(d, "tex")) # delete all the crappy temporary files: - var pdf = splitFile(d).name & ".pdf" - moveFile(dest=destPath / pdf, source=pdf) + let pdf = splitFile(d).name & ".pdf" + let dest = destPath / pdf + removeFile(dest) + moveFile(dest=dest, source=pdf) removeFile(changeFileExt(pdf, "aux")) if existsFile(changeFileExt(pdf, "toc")): removeFile(changeFileExt(pdf, "toc")) @@ -432,4 +434,7 @@ var c: TConfigData initConfigData(c) parseCmdLine(c) parseIniFile(c) -main(c) +when false: + buildPdfDoc(c, "doc") +else: + main(c)