threading code deactivated; tiny C bugfix: don't report warnings to error callback

This commit is contained in:
Araq 2010-09-19 21:35:44 +02:00
commit 93b3c03dbd
15 changed files with 208 additions and 135 deletions

View file

@ -1,3 +1,4 @@
Comex
Philippe Lhoste Philippe Lhoste
Mario Ray Mahardhika Mario Ray Mahardhika
Dominik Picheta Dominik Picheta

View file

@ -1,14 +1,13 @@
# #
# #
# Nimrod's Runtime Library # Nimrod's Runtime Library
# (c) Copyright 2006 Andreas Rumpf # (c) Copyright 2010 Andreas Rumpf
# #
# See the file "copying.txt", included in this # See the file "copying.txt", included in this
# distribution, for details about the copyright. # distribution, for details about the copyright.
# #
## Declaration of the Document Object Model for the ECMAScript backend. ## Declaration of the Document Object Model for the ECMAScript backend.
## (c) 2008 Andreas Rumpf
when not defined(ecmascript): when not defined(ecmascript):
{.error: "This module only works on the ECMAScript platform".} {.error: "This module only works on the ECMAScript platform".}

View file

@ -1605,10 +1605,8 @@ when not defined(EcmaScript) and not defined(NimrodVM):
## can be used to mark a condition to be unlikely. This is a hint for the ## can be used to mark a condition to be unlikely. This is a hint for the
## optimizer. ## optimizer.
elif defined(ecmaScript): elif defined(ecmaScript) or defined(NimrodVM):
include "system/ecmasys" # Stubs:
elif defined(NimrodVM):
# Stubs for the GC interface:
proc GC_disable() = nil proc GC_disable() = nil
proc GC_enable() = nil proc GC_enable() = nil
proc GC_fullCollect() = nil proc GC_fullCollect() = nil
@ -1621,15 +1619,18 @@ elif defined(NimrodVM):
proc getFreeMem(): int = return -1 proc getFreeMem(): int = return -1
proc getTotalMem(): int = return -1 proc getTotalMem(): int = return -1
proc cmp(x, y: string): int =
if x == y: return 0
if x < y: return -1
return 1
proc dealloc(p: pointer) = nil proc dealloc(p: pointer) = nil
proc alloc(size: int): pointer = nil proc alloc(size: int): pointer = nil
proc alloc0(size: int): pointer = nil proc alloc0(size: int): pointer = nil
proc realloc(p: Pointer, newsize: int): pointer = nil proc realloc(p: Pointer, newsize: int): pointer = nil
when defined(ecmaScript):
include "system/ecmasys"
elif defined(NimrodVM):
proc cmp(x, y: string): int =
if x == y: return 0
if x < y: return -1
return 1
{.pop.} # checks {.pop.} # checks
{.pop.} # hints {.pop.} # hints

View file

@ -1,26 +1,12 @@
# #
# #
# Nimrod's Runtime Library # Nimrod's Runtime Library
# (c) Copyright 2008 Andreas Rumpf # (c) Copyright 2010 Andreas Rumpf
# #
# See the file "copying.txt", included in this # See the file "copying.txt", included in this
# distribution, for details about the copyright. # distribution, for details about the copyright.
# #
## Stubs for the GC interface:
proc GC_disable() = nil
proc GC_enable() = nil
proc GC_fullCollect() = nil
proc GC_setStrategy(strategy: TGC_Strategy) = nil
proc GC_enableMarkAndSweep() = nil
proc GC_disableMarkAndSweep() = nil
proc GC_getStatistics(): string = return ""
proc getOccupiedMem(): int = return -1
proc getFreeMem(): int = return -1
proc getTotalMem(): int = return -1
proc alert(s: cstring) {.importc, nodecl.} proc alert(s: cstring) {.importc, nodecl.}
type type
@ -130,8 +116,6 @@ proc raiseIndexError() {.compilerproc, noreturn.} =
proc raiseFieldError(f: string) {.compilerproc, noreturn.} = proc raiseFieldError(f: string) {.compilerproc, noreturn.} =
raise newException(EInvalidField, f & " is not accessible") raise newException(EInvalidField, f & " is not accessible")
proc SetConstr() {.varargs, pure, compilerproc.} = proc SetConstr() {.varargs, pure, compilerproc.} =
asm """ asm """
var result = {}; var result = {};
@ -317,61 +301,58 @@ proc ewriteln(x: cstring) =
else: else:
raise newException(EInvalidValue, "<body> element does not exist yet!") raise newException(EInvalidValue, "<body> element does not exist yet!")
proc echo*(x: int) = ewriteln($x) proc rawEcho {.compilerproc.} =
proc echo*(x: float) = ewriteln($x) var node = document.getElementsByTagName("body")[0]
proc echo*(x: bool) = ewriteln(if x: cstring("true") else: cstring("false")) if node == nil: raise newException(EIO, "<body> element does not exist yet!")
proc echo*(x: string) = ewriteln(x) asm """
proc echo*(x: cstring) = ewriteln(x) for (var i = 0; i < arguments.length; ++i) {
var x = `toEcmaStr`(arguments[i]);
proc echo[Ty](x: Ty) = `node`.appendChild(document.createTextNode(x))
echo(x) }
"""
proc echo[Ty](x: openArray[Ty]) = node.appendChild(document.createElement("br"))
for a in items(x): echo(a)
# Arithmetic: # Arithmetic:
proc addInt(a, b: int): int {.pure, compilerproc.} = proc addInt(a, b: int): int {.pure, compilerproc.} =
asm """ asm """
var result = `a` + `b`; var result = `a` + `b`;
if (result > 2147483647 || result < -2147483648) raiseOverflow(); if (result > 2147483647 || result < -2147483648) `raiseOverflow`();
return result; return result;
""" """
proc subInt(a, b: int): int {.pure, compilerproc.} = proc subInt(a, b: int): int {.pure, compilerproc.} =
asm """ asm """
var result = `a` - `b`; var result = `a` - `b`;
if (result > 2147483647 || result < -2147483648) raiseOverflow(); if (result > 2147483647 || result < -2147483648) `raiseOverflow`();
return result; return result;
""" """
proc mulInt(a, b: int): int {.pure, compilerproc.} = proc mulInt(a, b: int): int {.pure, compilerproc.} =
asm """ asm """
var result = `a` * `b`; var result = `a` * `b`;
if (result > 2147483647 || result < -2147483648) raiseOverflow(); if (result > 2147483647 || result < -2147483648) `raiseOverflow`();
return result; return result;
""" """
proc divInt(a, b: int): int {.pure, compilerproc.} = proc divInt(a, b: int): int {.pure, compilerproc.} =
asm """ asm """
if (`b` == 0) raiseDivByZero(); if (`b` == 0) `raiseDivByZero`();
if (`b` == -1 && `a` == 2147483647) raiseOverflow(); if (`b` == -1 && `a` == 2147483647) `raiseOverflow`();
return Math.floor(`a` / `b`); return Math.floor(`a` / `b`);
""" """
proc modInt(a, b: int): int {.pure, compilerproc.} = proc modInt(a, b: int): int {.pure, compilerproc.} =
asm """ asm """
if (`b` == 0) raiseDivByZero(); if (`b` == 0) `raiseDivByZero`();
if (`b` == -1 && `a` == 2147483647) raiseOverflow(); if (`b` == -1 && `a` == 2147483647) `raiseOverflow`();
return Math.floor(`a` % `b`); return Math.floor(`a` % `b`);
""" """
proc addInt64(a, b: int): int {.pure, compilerproc.} = proc addInt64(a, b: int): int {.pure, compilerproc.} =
asm """ asm """
var result = `a` + `b`; var result = `a` + `b`;
if (result > 9223372036854775807 if (result > 9223372036854775807
|| result < -9223372036854775808) raiseOverflow(); || result < -9223372036854775808) `raiseOverflow`();
return result; return result;
""" """
@ -379,7 +360,7 @@ proc subInt64(a, b: int): int {.pure, compilerproc.} =
asm """ asm """
var result = `a` - `b`; var result = `a` - `b`;
if (result > 9223372036854775807 if (result > 9223372036854775807
|| result < -9223372036854775808) raiseOverflow(); || result < -9223372036854775808) `raiseOverflow`();
return result; return result;
""" """
@ -387,21 +368,21 @@ proc mulInt64(a, b: int): int {.pure, compilerproc.} =
asm """ asm """
var result = `a` * `b`; var result = `a` * `b`;
if (result > 9223372036854775807 if (result > 9223372036854775807
|| result < -9223372036854775808) raiseOverflow(); || result < -9223372036854775808) `raiseOverflow`();
return result; return result;
""" """
proc divInt64(a, b: int): int {.pure, compilerproc.} = proc divInt64(a, b: int): int {.pure, compilerproc.} =
asm """ asm """
if (`b` == 0) raiseDivByZero(); if (`b` == 0) `raiseDivByZero`();
if (`b` == -1 && `a` == 9223372036854775807) raiseOverflow(); if (`b` == -1 && `a` == 9223372036854775807) `raiseOverflow`();
return Math.floor(`a` / `b`); return Math.floor(`a` / `b`);
""" """
proc modInt64(a, b: int): int {.pure, compilerproc.} = proc modInt64(a, b: int): int {.pure, compilerproc.} =
asm """ asm """
if (`b` == 0) raiseDivByZero(); if (`b` == 0) `raiseDivByZero`();
if (`b` == -1 && `a` == 9223372036854775807) raiseOverflow(); if (`b` == -1 && `a` == 9223372036854775807) `raiseOverflow`();
return Math.floor(`a` % `b`); return Math.floor(`a` % `b`);
""" """
@ -415,13 +396,13 @@ proc internalAssert(file: cstring, line: int) {.pure, compilerproc.} =
asm """`e`.message = "[Assertion failure] file: "+`file`+", line: "+`line`""" asm """`e`.message = "[Assertion failure] file: "+`file`+", line: "+`line`"""
raise e raise e
include hti include "system/hti"
proc isFatPointer(ti: PNimType): bool = proc isFatPointer(ti: PNimType): bool =
# This has to be consistent with the code generator! # This has to be consistent with the code generator!
return ti.base.kind notin {tyRecord, tyRecordConstr, tyObject, return ti.base.kind notin {tyObject,
tyArray, tyArrayConstr, tyPureObject, tyTuple, tyArray, tyArrayConstr, tyPureObject, tyTuple,
tyEmptySet, tyOpenArray, tySet, tyVar, tyRef, tyPtr} tyOpenArray, tySet, tyVar, tyRef, tyPtr}
proc NimCopy(x: pointer, ti: PNimType): pointer {.compilerproc.} proc NimCopy(x: pointer, ti: PNimType): pointer {.compilerproc.}
@ -452,7 +433,7 @@ proc NimCopy(x: pointer, ti: PNimType): pointer =
`result`[0] = `x`[0]; `result`[0] = `x`[0];
`result`[1] = `x`[1]; `result`[1] = `x`[1];
""" """
of tyEmptySet, tySet: of tySet:
asm """ asm """
`result` = {}; `result` = {};
for (var key in `x`) { `result`[key] = `x`[key]; } for (var key in `x`) { `result`[key] = `x`[key]; }

View file

@ -10,6 +10,10 @@
# Exception handling code. This is difficult because it has # Exception handling code. This is difficult because it has
# to work if there is no more memory (but it doesn't yet!). # to work if there is no more memory (but it doesn't yet!).
var
stackTraceNewLine* = "\n" ## undocumented feature; it is replaced by ``<br>``
## for CGI applications
when not defined(windows) or not defined(guiapp): when not defined(windows) or not defined(guiapp):
proc writeToStdErr(msg: CString) = write(stdout, msg) proc writeToStdErr(msg: CString) = write(stdout, msg)
@ -32,7 +36,7 @@ type
TSafePoint {.compilerproc, final.} = object TSafePoint {.compilerproc, final.} = object
prev: PSafePoint # points to next safe point ON THE STACK prev: PSafePoint # points to next safe point ON THE STACK
status: int status: int
exc: ref E_Base # XXX only needed for bootstrapping exc: ref E_Base # XXX only needed for bootstrapping; unused
context: C_JmpBuf context: C_JmpBuf
var var
@ -55,6 +59,58 @@ proc pushCurrentException(e: ref E_Base) {.compilerRtl, inl.} =
proc popCurrentException {.compilerRtl, inl.} = proc popCurrentException {.compilerRtl, inl.} =
currException = currException.parent currException = currException.parent
# some platforms have native support for stack traces:
const
nimrodStackTrace = compileOption("stacktrace")
nativeStackTrace = (defined(macosx) or defined(linux)) and
not nimrodStackTrace and false
# `nativeStackTrace` does not work for me --> deactivated for now. Maybe for
# the next release version.
when nativeStacktrace:
type
TDl_info {.importc: "Dl_info", header: "<dlfcn.h>",
final, pure.} = object
dli_fname: CString
dli_fbase: pointer
dli_sname: CString
dli_saddr: pointer
proc backtrace(symbols: ptr pointer, size: int): int {.
importc: "backtrace", header: "<execinfo.h>".}
proc dladdr(addr1: pointer, info: ptr TDl_info): int {.
importc: "dladdr", header: "<dlfcn.h>".}
var
tempAddresses: array [0..127, pointer] # cannot be allocated on the stack!
tempDlInfo: TDl_info
proc auxWriteStackTraceWithBacktrace(s: var string) =
# This is allowed to be expensive since it only happens during crashes
# (but this way you don't need manual stack tracing)
var size = backtrace(cast[ptr pointer](addr(tempAddresses)),
len(tempAddresses))
var enabled = false
for i in 0..size-1:
var dlresult = dladdr(tempAddresses[i], addr(tempDlInfo))
if enabled:
if dlresult != 0:
var oldLen = s.len
add(s, tempDlInfo.dli_fname)
if tempDlInfo.dli_sname != nil:
for k in 1..max(1, 25-(s.len-oldLen)): add(s, ' ')
add(s, tempDlInfo.dli_sname)
else:
add(s, '?')
add(s, stackTraceNewLine)
else:
if dlresult != 0 and tempDlInfo.dli_sname != nil and
c_strcmp(tempDlInfo.dli_sname, "signalHandler") == 0'i32:
# Once we're past signalHandler, we're at what the user is
# interested in
enabled = true
type type
PFrame = ptr TFrame PFrame = ptr TFrame
TFrame {.importc, nodecl, final.} = object TFrame {.importc, nodecl, final.} = object
@ -74,9 +130,6 @@ var
tempFrames: array [0..127, PFrame] # cannot be allocated on the stack! tempFrames: array [0..127, PFrame] # cannot be allocated on the stack!
stackTraceNewLine* = "\n" ## undocumented feature; it is replaced by ``<br>``
## for CGI applications
proc auxWriteStackTrace(f: PFrame, s: var string) = proc auxWriteStackTrace(f: PFrame, s: var string) =
const const
firstCalls = 32 firstCalls = 32
@ -120,7 +173,7 @@ proc auxWriteStackTrace(f: PFrame, s: var string) =
add(s, stackTraceNewLine) add(s, stackTraceNewLine)
proc rawWriteStackTrace(s: var string) = proc rawWriteStackTrace(s: var string) =
when compileOption("stacktrace") or compileOption("linetrace"): when nimrodStackTrace:
if framePtr == nil: if framePtr == nil:
add(s, "No stack traceback available") add(s, "No stack traceback available")
add(s, stackTraceNewLine) add(s, stackTraceNewLine)
@ -128,6 +181,10 @@ proc rawWriteStackTrace(s: var string) =
add(s, "Traceback (most recent call last)") add(s, "Traceback (most recent call last)")
add(s, stackTraceNewLine) add(s, stackTraceNewLine)
auxWriteStackTrace(framePtr, s) auxWriteStackTrace(framePtr, s)
elif nativeStackTrace:
add(s, "Traceback from system (most recent call last)")
add(s, stackTraceNewLine)
auxWriteStackTraceWithBacktrace(s)
else: else:
add(s, "No stack traceback available") add(s, "No stack traceback available")
add(s, stackTraceNewLine) add(s, stackTraceNewLine)
@ -197,11 +254,6 @@ proc WriteStackTrace() =
rawWriteStackTrace(s) rawWriteStackTrace(s)
writeToStdErr(s) writeToStdErr(s)
#proc stackTraceWrapper {.noconv.} =
# writeStackTrace()
#addQuitProc(stackTraceWrapper)
var var
dbgAborting: bool # whether the debugger wants to abort dbgAborting: bool # whether the debugger wants to abort

View file

@ -77,11 +77,13 @@ var
# collection, not a lock for threads! # collection, not a lock for threads!
proc lock(gch: var TGcHeap) {.inline.} = proc lock(gch: var TGcHeap) {.inline.} =
when hasThreadSupport:
if isMultiThreaded: if isMultiThreaded:
Lock(gch.zctLock) Lock(gch.zctLock)
lock(gch.cycleRootsLock) lock(gch.cycleRootsLock)
proc unlock(gch: var TGcHeap) {.inline.} = proc unlock(gch: var TGcHeap) {.inline.} =
when hasThreadSupport:
if isMultiThreaded: if isMultiThreaded:
unlock(gch.zctLock) unlock(gch.zctLock)
unlock(gch.cycleRootsLock) unlock(gch.cycleRootsLock)
@ -202,14 +204,18 @@ proc prepareDealloc(cell: PCell) =
proc rtlAddCycleRoot(c: PCell) {.rtl, inl.} = proc rtlAddCycleRoot(c: PCell) {.rtl, inl.} =
# we MUST access gch as a global here, because this crosses DLL boundaries! # we MUST access gch as a global here, because this crosses DLL boundaries!
when hasThreadSupport:
if isMultiThreaded: Lock(gch.cycleRootsLock) if isMultiThreaded: Lock(gch.cycleRootsLock)
incl(gch.cycleRoots, c) incl(gch.cycleRoots, c)
when hasThreadSupport:
if isMultiThreaded: Unlock(gch.cycleRootsLock) if isMultiThreaded: Unlock(gch.cycleRootsLock)
proc rtlAddZCT(c: PCell) {.rtl, inl.} = proc rtlAddZCT(c: PCell) {.rtl, inl.} =
# we MUST access gch as a global here, because this crosses DLL boundaries! # we MUST access gch as a global here, because this crosses DLL boundaries!
when hasThreadSupport:
if isMultiThreaded: Lock(gch.zctLock) if isMultiThreaded: Lock(gch.zctLock)
addZCT(gch.zct, c) addZCT(gch.zct, c)
when hasThreadSupport:
if isMultiThreaded: Unlock(gch.zctLock) if isMultiThreaded: Unlock(gch.zctLock)
proc decRef(c: PCell) {.inline.} = proc decRef(c: PCell) {.inline.} =
@ -480,7 +486,7 @@ proc gcMark(p: pointer) {.inline.} =
add(gch.decStack, cell) add(gch.decStack, cell)
proc markThreadStacks(gch: var TGcHeap) = proc markThreadStacks(gch: var TGcHeap) =
when isMultiThreaded: when hasThreadSupport:
nil nil
# ----------------- stack management -------------------------------------- # ----------------- stack management --------------------------------------

View file

@ -7,12 +7,17 @@
# distribution, for details about the copyright. # distribution, for details about the copyright.
# #
when defined(gcc) or defined(llvm_gcc): const
hasThreadSupport = false # deactivate for now: thread stack walking
# is missing!
maxThreads = 256
when (defined(gcc) or defined(llvm_gcc)) and hasThreadSupport:
proc sync_add_and_fetch(p: var int, val: int): int {. proc sync_add_and_fetch(p: var int, val: int): int {.
importc: "__sync_add_and_fetch", nodecl.} importc: "__sync_add_and_fetch", nodecl.}
proc sync_sub_and_fetch(p: var int, val: int): int {. proc sync_sub_and_fetch(p: var int, val: int): int {.
importc: "__sync_sub_and_fetch", nodecl.} importc: "__sync_sub_and_fetch", nodecl.}
elif defined(vcc): elif defined(vcc) and hasThreadSupport:
proc sync_add_and_fetch(p: var int, val: int): int {. proc sync_add_and_fetch(p: var int, val: int): int {.
importc: "NimXadd", nodecl.} importc: "NimXadd", nodecl.}
else: else:
@ -20,19 +25,18 @@ else:
inc(p, val) inc(p, val)
result = p result = p
const var
isMultiThreaded* = true isMultiThreaded: bool # true when prog created at least 1 thread
maxThreads = 256
proc atomicInc(memLoc: var int, x: int): int = proc atomicInc(memLoc: var int, x: int): int =
when isMultiThreaded: when hasThreadSupport:
result = sync_add_and_fetch(memLoc, x) result = sync_add_and_fetch(memLoc, x)
else: else:
inc(memLoc, x) inc(memLoc, x)
result = memLoc result = memLoc
proc atomicDec(memLoc: var int, x: int): int = proc atomicDec(memLoc: var int, x: int): int =
when isMultiThreaded: when hasThreadSupport:
when defined(sync_sub_and_fetch): when defined(sync_sub_and_fetch):
result = sync_sub_and_fetch(memLoc, x) result = sync_sub_and_fetch(memLoc, x)
else: else:
@ -85,11 +89,8 @@ type
TThreadFunc* = proc (closure: pointer) {.cdecl.} TThreadFunc* = proc (closure: pointer) {.cdecl.}
proc createThread*(t: var TThread, fn: TThreadFunc) = proc createThread*(t: var TThread, fn: TThreadFunc) =
nil nil
proc destroyThread*(t: var TThread) = proc destroyThread*(t: var TThread) =
nil nil

View file

@ -12,9 +12,9 @@
# code!** # code!**
import import
ast, astalgo, strutils, nhashes, trees, platform, magicsys, extccomp, options, ast, astalgo, strutils, nhashes, trees, platform, magicsys, extccomp,
nversion, nimsets, msgs, crc, bitsets, idents, lists, types, os, times, ropes, options, nversion, nimsets, msgs, crc, bitsets, idents, lists, types, os,
math, passes, ccgutils, wordrecg, rnimsyn, rodread times, ropes, math, passes, ccgutils, wordrecg, rnimsyn, rodread
proc ecmasgenPass*(): TPass proc ecmasgenPass*(): TPass
# implementation # implementation
@ -39,7 +39,8 @@ type
kind*: TEcmasTypeKind kind*: TEcmasTypeKind
com*: PRope # computation part com*: PRope # computation part
# address if this is a (address, index)-tuple # address if this is a (address, index)-tuple
res*: PRope # result part; index if this is a (address, index)-tuple res*: PRope # result part; index if this is an
# (address, index)-tuple
TBlock{.final.} = object TBlock{.final.} = object
id*: int # the ID of the label; positive means that it id*: int # the ID of the label; positive means that it
@ -886,12 +887,11 @@ proc genDeref(p: var TProc, n: PNode, r: var TCompRes) =
if a.kind != etyBaseIndex: InternalError(n.info, "genDeref") if a.kind != etyBaseIndex: InternalError(n.info, "genDeref")
r.res = ropef("$1[$2]", [a.com, a.res]) r.res = ropef("$1[$2]", [a.com, a.res])
proc genCall(p: var TProc, n: PNode, r: var TCompRes) = proc genArgs(p: var TProc, n: PNode, r: var TCompRes) =
var a: TCompRes
gen(p, n.sons[0], r)
app(r.res, "(") app(r.res, "(")
for i in countup(1, sonsLen(n) - 1): for i in countup(1, sonsLen(n) - 1):
if i > 1: app(r.res, ", ") if i > 1: app(r.res, ", ")
var a: TCompRes
gen(p, n.sons[i], a) gen(p, n.sons[i], a)
if a.kind == etyBaseIndex: if a.kind == etyBaseIndex:
app(r.res, a.com) app(r.res, a.com)
@ -901,6 +901,14 @@ proc genCall(p: var TProc, n: PNode, r: var TCompRes) =
app(r.res, mergeExpr(a)) app(r.res, mergeExpr(a))
app(r.res, ")") app(r.res, ")")
proc genCall(p: var TProc, n: PNode, r: var TCompRes) =
gen(p, n.sons[0], r)
genArgs(p, n, r)
proc genEcho(p: var TProc, n: PNode, r: var TCompRes) =
app(r.res, "rawEcho")
genArgs(p, n, r)
proc putToSeq(s: string, indirect: bool): PRope = proc putToSeq(s: string, indirect: bool): PRope =
result = toRope(s) result = toRope(s)
if indirect: result = ropef("[$1]", [result]) if indirect: result = ropef("[$1]", [result])
@ -1124,6 +1132,8 @@ proc genMagic(p: var TProc, n: PNode, r: var TCompRes) =
of mInSet: binaryExpr(p, n, r, "", "($1[$2] != undefined)") of mInSet: binaryExpr(p, n, r, "", "($1[$2] != undefined)")
of mNLen..mNError: of mNLen..mNError:
liMessage(n.info, errCannotGenerateCodeForX, n.sons[0].sym.name.s) liMessage(n.info, errCannotGenerateCodeForX, n.sons[0].sym.name.s)
of mNewSeq: binaryStmt(p, n, r, "", "$1 = new Array($2)")
of mEcho: genEcho(p, n, r)
else: else:
genCall(p, n, r) genCall(p, n, r)
#else internalError(e.info, 'genMagic: ' + magicToStr[op]); #else internalError(e.info, 'genMagic: ' + magicToStr[op]);
@ -1389,7 +1399,7 @@ proc newModule(module: PSym, filename: string): BModule =
proc genHeader(): PRope = proc genHeader(): PRope =
result = ropef("/* Generated by the Nimrod Compiler v$1 */$n" & result = ropef("/* Generated by the Nimrod Compiler v$1 */$n" &
"/* (c) 2008 Andreas Rumpf */$n$n" & "$nvar Globals = this;$n" & "/* (c) 2010 Andreas Rumpf */$n$n" & "$nvar Globals = this;$n" &
"var framePtr = null;$n" & "var excHandler = null;$n", "var framePtr = null;$n" & "var excHandler = null;$n",
[toRope(versionAsString)]) [toRope(versionAsString)])

View file

@ -203,7 +203,7 @@ proc MainCommand(cmd, filename: string) =
gCmd = cmdCompileToCpp gCmd = cmdCompileToCpp
wantFile(filename) wantFile(filename)
CommandCompileToC(filename) CommandCompileToC(filename)
of wCompileToEcmaScript: of wCompileToEcmaScript, wJs:
gCmd = cmdCompileToEcmaScript gCmd = cmdCompileToEcmaScript
wantFile(filename) wantFile(filename)
CommandCompileToEcmaScript(filename) CommandCompileToEcmaScript(filename)

View file

@ -55,7 +55,7 @@ type
wCc, wGenscript, wCheckPoint, wCheckPoints, wNoMain, wSubsChar, wCc, wGenscript, wCheckPoint, wCheckPoints, wNoMain, wSubsChar,
wAcyclic, wIndex, wAcyclic, wIndex,
wCompileToC, wCompileToCpp, wCompileToEcmaScript, wCompileToLLVM, wPretty, wCompileToC, wCompileToCpp, wCompileToEcmaScript, wCompileToLLVM, wPretty,
wDoc, wGenDepend, wListDef, wCheck, wParse, wScan, wLazy, wDoc, wGenDepend, wListDef, wCheck, wParse, wScan, wJs,
wRst2html, wRst2tex, wI, wRst2html, wRst2tex, wI,
wWrite, wPutEnv, wPrependEnv, wAppendEnv, wThreadVar wWrite, wPutEnv, wPrependEnv, wAppendEnv, wThreadVar
@ -103,7 +103,7 @@ const
"nomain", "subschar", "acyclic", "index", "nomain", "subschar", "acyclic", "index",
"compiletoc", "compiletocpp", "compiletoecmascript", "compiletollvm", "compiletoc", "compiletocpp", "compiletoecmascript", "compiletollvm",
"pretty", "doc", "gendepend", "listdef", "check", "parse", "scan", "pretty", "doc", "gendepend", "listdef", "check", "parse", "scan",
"lazy", "rst2html", "rst2tex", "i", "js", "rst2html", "rst2tex", "i",
"write", "putenv", "prependenv", "appendenv", "threadvar"] "write", "putenv", "prependenv", "appendenv", "threadvar"]
proc whichKeyword*(id: PIdent): TSpecialWord proc whichKeyword*(id: PIdent): TSpecialWord

View file

@ -2,18 +2,18 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<!-- This has been written by hand. (c) 2008 Andreas Rumpf --> <!-- This has been written by hand. (c) 2010 Andreas Rumpf -->
<head> <head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Nimrod ECMAScript Generator Test</title> <title>Nimrod ECMAScript Generator Test</title>
<style type="text/css"> <style type="text/css">
span.DecNumber {color: blue} span.DecNumber {color: blue}
</style> </style>
<script src="nimrcache/ecmas.js" type="text/javascript"></script> <script src="nimcache/ecmas.js" type="text/javascript"></script>
</head> </head>
<body onload="OnLoad()"> <body onload="OnLoad()">
<form name="form1" action="ecmas.html"> <form name="form1" action="ecmas.html">
<input type="text" name="input" size="3" /> <input type="text" name="input1" size="10" />
<input type="button" value="Calculate square" onclick="OnButtonClick()" /> <input type="button" value="Calculate square" onclick="OnButtonClick()" />
</form> </form>

View file

@ -6,11 +6,14 @@ import
# We need to declare the used elements here. This is annoying but # We need to declare the used elements here. This is annoying but
# prevents any kind of typo: # prevents any kind of typo:
var var
inputElement {.importc: "document.form1.input", nodecl.}: ref TElement inputElement {.importc: "document.form1.input1", nodecl.}: ref TElement
proc OnButtonClick() {.exportc.} = proc OnButtonClick() {.exportc.} =
var x: int = parseInt($inputElement.value) #var x = parseInt($inputElement.value)
echo($(x * x)) #echo($(x * x))
var input = $inputElement.value
echo "Test"
echo "Hi, ", input
proc OnLoad() {.exportc.} = proc OnLoad() {.exportc.} =
echo("Welcome! Please take your time to fill in this formular!") echo "Welcome! Please take your time to fill in this formular!"

View file

@ -808,12 +808,12 @@ void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap)
if (!s1->error_func) { if (!s1->error_func) {
/* default case: stderr */ /* default case: stderr */
fprintf(stderr, "%s\n", buf); fprintf(stderr, "%s\n", buf);
} else {
s1->error_func(s1->error_opaque, buf);
} }
if (!is_warning || s1->warn_error) if (!is_warning || s1->warn_error) {
s1->error_func(s1->error_opaque, buf);
s1->nb_errors++; s1->nb_errors++;
} }
}
void tcc_set_error_func(TCCState *s, void *error_opaque, void tcc_set_error_func(TCCState *s, void *error_opaque,
void (*error_func)(void *opaque, const char *msg)) void (*error_func)(void *opaque, const char *msg))

View file

@ -3,6 +3,8 @@ For version 0.8.10
- fix implicit generic routines - fix implicit generic routines
- bugfix: ccgexprs - bugfix: ccgexprs
- bugfix: make ``finally`` more robust
- bugfix: tiny C broken again!
High priority (version 0.9.0) High priority (version 0.9.0)

View file

@ -7,17 +7,38 @@
# distribution, for details about the copyright. # distribution, for details about the copyright.
# #
import glib2, gtk2, gdk2, osproc, dialogs, strutils import glib2, gtk2, gdk2, os, osproc, dialogs, strutils
when defined(tinyc):
const runCmd = "run"
else:
const runCmd = "c -r"
when not defined(findExe):
# candidate for the stdlib:
proc findExe(exe: string): string =
## returns exe if the exe cannot be found
result = addFileExt(exe, os.exeExt)
if ExistsFile(result): return
var path = os.getEnv("PATH")
for candidate in split(path, pathSep):
var x = candidate / result
if ExistsFile(x): return x
result = ""
var nimExe = findExe("nimrod")
if nimExe.len == 0: nimExe = "../bin" / addFileExt("nimrod", os.exeExt)
proc execCode(code: string): string = proc execCode(code: string): string =
var f: TFile var f: TFile
if open(f, "temp.nim", fmWrite): if open(f, "temp.nim", fmWrite):
f.write(code) f.write(code)
f.close() f.close()
else:
raise newException(EIO, "Unable to open file")
result = osproc.execProcess( result = osproc.execProcess(
"nimrod c -r --verbosity:0 --hint[Conf]:off temp.nim") "$# $# --verbosity:0 --hint[Conf]:off temp.nim" % [nimExe, runCmd],
{poStdErrToStdOut})
else:
result = "cannot open file 'temp.nim'"
var shiftPressed = False var shiftPressed = False
var w: gtk2.PWindow var w: gtk2.PWindow
@ -29,20 +50,17 @@ proc destroy(widget: PWidget, data: pgpointer){.cdecl.} =
proc FileOpenClicked(menuitem: PMenuItem, userdata: pgpointer) {.cdecl.} = proc FileOpenClicked(menuitem: PMenuItem, userdata: pgpointer) {.cdecl.} =
var path = ChooseFileToOpen(w) var path = ChooseFileToOpen(w)
if path != "": if path != "":
var file: string = readFile(path) var file: string = readFile(path)
if file != nil: if file != nil:
set_text(InputTextBuffer, file, len(file)) set_text(InputTextBuffer, file, len(file))
else: else:
error(w, "Unable to read from file") error(w, "Unable to read from file")
proc FileSaveClicked(menuitem: PMenuItem, userdata: pgpointer) {.cdecl.} = proc FileSaveClicked(menuitem: PMenuItem, userdata: pgpointer) {.cdecl.} =
var path = ChooseFileToSave(w) var path = ChooseFileToSave(w)
if path != "": if path == "": return
var startIter: TTextIter var startIter: TTextIter
var endIter: TTextIter var endIter: TTextIter
get_start_iter(InputTextBuffer, addr(startIter)) get_start_iter(InputTextBuffer, addr(startIter))
@ -56,7 +74,6 @@ proc FileSaveClicked(menuitem: PMenuItem, userdata: pgpointer) {.cdecl.} =
else: else:
error(w, "Unable to write to file") error(w, "Unable to write to file")
proc inputKeyPressed(widget: PWidget, event: PEventKey, proc inputKeyPressed(widget: PWidget, event: PEventKey,
userdata: pgpointer): bool = userdata: pgpointer): bool =
if ($keyval_name(event.keyval)).tolower() == "shift_l": if ($keyval_name(event.keyval)).tolower() == "shift_l":
@ -68,13 +85,13 @@ proc setError(msg: string) =
proc inputKeyReleased(widget: PWidget, event: PEventKey, proc inputKeyReleased(widget: PWidget, event: PEventKey,
userdata: pgpointer): bool = userdata: pgpointer): bool =
echo(keyval_name(event.keyval)) #echo(keyval_name(event.keyval))
if ($keyval_name(event.keyval)).tolower() == "shift_l": if ($keyval_name(event.keyval)).tolower() == "shift_l":
# SHIFT is released # SHIFT is released
shiftPressed = False shiftPressed = False
if ($keyval_name(event.keyval)).tolower() == "return": if ($keyval_name(event.keyval)).tolower() == "return":
echo($keyval_name(event.keyval), "Shift_L") #echo($keyval_name(event.keyval), "Shift_L")
# Enter pressed # Enter pressed
if shiftPressed == False: if shiftPressed == False:
var startIter: TTextIter var startIter: TTextIter