Merge branch 'devel' of github.com:nim-lang/Nim into devel

This commit is contained in:
Araq
2016-10-24 20:20:20 +02:00
25 changed files with 196 additions and 68 deletions

View File

@@ -317,6 +317,10 @@ type
TTypeKind* = enum # order is important!
# Don't forget to change hti.nim if you make a change here
# XXX put this into an include file to avoid this issue!
# several types are no longer used (guess which), but a
# spot in the sequence is kept for backwards compatibility
# (apparently something with bootstrapping)
# if you need to add a type, they can apparently be reused
tyNone, tyBool, tyChar,
tyEmpty, tyArrayConstr, tyNil, tyExpr, tyStmt, tyTypeDesc,
tyGenericInvocation, # ``T[a, b]`` for types to invoke
@@ -345,9 +349,9 @@ type
tyInt, tyInt8, tyInt16, tyInt32, tyInt64, # signed integers
tyFloat, tyFloat32, tyFloat64, tyFloat128,
tyUInt, tyUInt8, tyUInt16, tyUInt32, tyUInt64,
tyBigNum,
tyConst, tyMutable, tyVarargs,
tyUnused # kept for enum ordinal compatibility
tyUnused0, tyUnused1, tyUnused2,
tyVarargs,
tyUnused,
tyProxy # used as errornous type (for idetools)
tyBuiltInTypeClass #\

View File

@@ -122,7 +122,7 @@ proc mapType(typ: PType): TCTypeKind =
of tyOpenArray, tyArrayConstr, tyArray, tyVarargs: result = ctArray
of tyObject, tyTuple: result = ctStruct
of tyGenericBody, tyGenericInst, tyGenericParam, tyDistinct, tyOrdinal,
tyConst, tyMutable, tyTypeDesc:
tyTypeDesc:
result = mapType(lastSon(typ))
of tyEnum:
if firstOrd(typ) < 0:
@@ -711,7 +711,7 @@ proc getTypeDescAux(m: BModule, typ: PType, check: var IntSet): Rope =
of 1, 2, 4, 8: addf(m.s[cfsTypes], "typedef NU$2 $1;$n", [result, rope(s*8)])
else: addf(m.s[cfsTypes], "typedef NU8 $1[$2];$n",
[result, rope(getSize(t))])
of tyGenericInst, tyDistinct, tyOrdinal, tyConst, tyMutable, tyTypeDesc:
of tyGenericInst, tyDistinct, tyOrdinal, tyTypeDesc:
result = getTypeDescAux(m, lastSon(t), check)
else:
internalError("getTypeDescAux(" & $t.kind & ')')

View File

@@ -93,7 +93,7 @@ proc getUniqueType*(key: PType): PType =
# produced instead of ``NI``.
result = key
of tyEmpty, tyNil, tyExpr, tyStmt, tyPointer, tyString,
tyCString, tyNone, tyBigNum, tyVoid:
tyCString, tyNone, tyVoid:
result = gCanonicalTypes[k]
if result == nil:
gCanonicalTypes[k] = key
@@ -106,7 +106,7 @@ proc getUniqueType*(key: PType): PType =
of tyDistinct:
if key.deepCopy != nil: result = key
else: result = getUniqueType(lastSon(key))
of tyGenericInst, tyOrdinal, tyMutable, tyConst, tyStatic:
of tyGenericInst, tyOrdinal, tyStatic:
result = getUniqueType(lastSon(key))
#let obj = lastSon(key)
#if obj.sym != nil and obj.sym.name.s == "TOption":
@@ -153,7 +153,7 @@ proc getUniqueType*(key: PType): PType =
else:
# ugh, we need the canon here:
result = slowSearch(key, k)
of tyUnused: internalError("getUniqueType")
of tyUnused, tyUnused0, tyUnused1, tyUnused2: internalError("getUniqueType")
proc tableGetType*(tab: TIdTable, key: PType): RootRef =
# returns nil if we need to declare this type

View File

@@ -138,7 +138,7 @@ proc declareGlobal(p: PProc; id: int; r: Rope) =
const
MappedToObject = {tyObject, tyArray, tyArrayConstr, tyTuple, tyOpenArray,
tySet, tyBigNum, tyVarargs}
tySet, tyVarargs}
proc mapType(typ: PType): TJSTypeKind =
let t = skipTypes(typ, abstractInst)
@@ -151,15 +151,13 @@ proc mapType(typ: PType): TJSTypeKind =
of tyPointer:
# treat a tyPointer like a typed pointer to an array of bytes
result = etyBaseIndex
of tyRange, tyDistinct, tyOrdinal, tyConst, tyMutable, tyProxy:
result = mapType(t.sons[0])
of tyRange, tyDistinct, tyOrdinal, tyProxy: result = mapType(t.sons[0])
of tyInt..tyInt64, tyUInt..tyUInt64, tyEnum, tyChar: result = etyInt
of tyBool: result = etyBool
of tyFloat..tyFloat128: result = etyFloat
of tySet: result = etyObject # map a set to a table
of tyString, tySequence: result = etySeq
of tyObject, tyArray, tyArrayConstr, tyTuple, tyOpenArray, tyBigNum,
tyVarargs:
of tyObject, tyArray, tyArrayConstr, tyTuple, tyOpenArray, tyVarargs:
result = etyObject
of tyNil: result = etyNull
of tyGenericInst, tyGenericParam, tyGenericBody, tyGenericInvocation,
@@ -171,7 +169,7 @@ proc mapType(typ: PType): TJSTypeKind =
else: result = etyNone
of tyProc: result = etyProc
of tyCString: result = etyString
of tyUnused: internalError("mapType")
of tyUnused, tyUnused0, tyUnused1, tyUnused2: internalError("mapType")
proc mapType(p: PProc; typ: PType): TJSTypeKind =
if p.target == targetPHP: result = etyObject

View File

@@ -13,6 +13,11 @@ when defined(gcc) and defined(windows):
else:
{.link: "icons/nim_icon.o".}
when defined(amd64) and defined(windows) and defined(vcc):
{.link: "icons/nim-amd64-windows-vcc.res" .}
when defined(i386) and defined(windows) and defined(vcc):
{.link: "icons/nim-i386-windows-vcc.res" .}
import
commands, lexer, condsyms, options, msgs, nversion, nimconf, ropes,
extccomp, strutils, os, osproc, platform, main, parseopt, service,

View File

@@ -289,8 +289,7 @@ proc lsub(n: PNode): int
proc litAux(n: PNode, x: BiggestInt, size: int): string =
proc skip(t: PType): PType =
result = t
while result.kind in {tyGenericInst, tyRange, tyVar, tyDistinct, tyOrdinal,
tyConst, tyMutable}:
while result.kind in {tyGenericInst, tyRange, tyVar, tyDistinct, tyOrdinal}:
result = lastSon(result)
if n.typ != nil and n.typ.skip.kind in {tyBool, tyEnum}:
let enumfields = n.typ.skip.n

View File

@@ -223,13 +223,13 @@ proc liftBodyAux(c: var TLiftCtx; t: PType; body, x, y: PNode) =
localError(c.info, errGenerated, "cannot copy openArray")
of tyFromExpr, tyProxy, tyBuiltInTypeClass, tyUserTypeClass,
tyUserTypeClassInst, tyCompositeTypeClass, tyAnd, tyOr, tyNot, tyAnything,
tyMutable, tyGenericParam, tyGenericBody, tyNil, tyExpr, tyStmt,
tyTypeDesc, tyGenericInvocation, tyBigNum, tyConst, tyForward:
tyGenericParam, tyGenericBody, tyNil, tyExpr, tyStmt,
tyTypeDesc, tyGenericInvocation, tyForward:
internalError(c.info, "assignment requested for type: " & typeToString(t))
of tyOrdinal, tyRange,
tyGenericInst, tyFieldAccessor, tyStatic, tyVar:
liftBodyAux(c, lastSon(t), body, x, y)
of tyUnused: internalError("liftBodyAux")
of tyUnused, tyUnused0, tyUnused1, tyUnused2: internalError("liftBodyAux")
proc newProcType(info: TLineInfo; owner: PSym): PType =
result = newType(tyProc, owner)

View File

@@ -124,7 +124,7 @@ proc instantiateDestructor(c: PContext, typ: PType): PType =
# destructor that must be used for the varialbe.
# The destructor is either user-defined or automatically
# generated by the compiler in a member-wise fashion.
var t = skipTypes(typ, {tyConst, tyMutable}).skipGenericAlias
var t = typ.skipGenericAlias
let typeHoldingUserDefinition = if t.kind == tyGenericInst: t.base else: t
if typeHoldingUserDefinition.destructor != nil:

View File

@@ -51,18 +51,14 @@ const
# TODO: Remove tyTypeDesc from each abstractX and (where necessary)
# replace with typedescX
abstractPtrs* = {tyVar, tyPtr, tyRef, tyGenericInst, tyDistinct, tyOrdinal,
tyConst, tyMutable, tyTypeDesc}
abstractVar* = {tyVar, tyGenericInst, tyDistinct, tyOrdinal,
tyConst, tyMutable, tyTypeDesc}
abstractRange* = {tyGenericInst, tyRange, tyDistinct, tyOrdinal,
tyConst, tyMutable, tyTypeDesc}
abstractVarRange* = {tyGenericInst, tyRange, tyVar, tyDistinct, tyOrdinal,
tyConst, tyMutable, tyTypeDesc}
abstractInst* = {tyGenericInst, tyDistinct, tyConst, tyMutable, tyOrdinal,
tyTypeDesc}
abstractVar* = {tyVar, tyGenericInst, tyDistinct, tyOrdinal, tyTypeDesc}
abstractRange* = {tyGenericInst, tyRange, tyDistinct, tyOrdinal, tyTypeDesc}
abstractVarRange* = {tyGenericInst, tyRange, tyVar, tyDistinct, tyOrdinal,
tyTypeDesc}
abstractInst* = {tyGenericInst, tyDistinct, tyOrdinal, tyTypeDesc}
skipPtrs* = {tyVar, tyPtr, tyRef, tyGenericInst, tyConst, tyMutable,
tyTypeDesc}
skipPtrs* = {tyVar, tyPtr, tyRef, tyGenericInst, tyTypeDesc}
# typedescX is used if we're sure tyTypeDesc should be included (or skipped)
typedescPtrs* = abstractPtrs + {tyTypeDesc}
typedescInst* = abstractInst + {tyTypeDesc}
@@ -116,8 +112,7 @@ proc isFloatLit*(t: PType): bool {.inline.} =
proc isCompatibleToCString(a: PType): bool =
if a.kind == tyArray:
if (firstOrd(a.sons[0]) == 0) and
(skipTypes(a.sons[0], {tyRange, tyConst,
tyMutable, tyGenericInst}).kind in
(skipTypes(a.sons[0], {tyRange, tyGenericInst}).kind in
{tyInt..tyInt64, tyUInt..tyUInt64}) and
(a.sons[1].kind == tyChar):
result = true
@@ -151,13 +146,12 @@ proc isOrdinalType(t: PType): bool =
const
# caution: uint, uint64 are no ordinal types!
baseKinds = {tyChar,tyInt..tyInt64,tyUInt8..tyUInt32,tyBool,tyEnum}
parentKinds = {tyRange, tyOrdinal, tyConst, tyMutable, tyGenericInst,
tyDistinct}
parentKinds = {tyRange, tyOrdinal, tyGenericInst, tyDistinct}
t.kind in baseKinds or (t.kind in parentKinds and isOrdinalType(t.sons[0]))
proc enumHasHoles(t: PType): bool =
var b = t
while b.kind in {tyConst, tyMutable, tyRange, tyGenericInst}: b = b.sons[0]
while b.kind in {tyRange, tyGenericInst}: b = b.sons[0]
result = b.kind == tyEnum and tfEnumHasHoles in b.flags
proc iterOverTypeAux(marker: var IntSet, t: PType, iter: TTypeIter,
@@ -275,7 +269,7 @@ proc analyseObjectWithTypeFieldAux(t: PType,
if res == frHeader: result = frHeader
if result == frNone:
if isObjectWithTypeFieldPredicate(t): result = frHeader
of tyGenericInst, tyDistinct, tyConst, tyMutable:
of tyGenericInst, tyDistinct:
result = analyseObjectWithTypeFieldAux(lastSon(t), marker)
of tyArray, tyArrayConstr, tyTuple:
for i in countup(0, sonsLen(t) - 1):
@@ -408,8 +402,8 @@ const
"int", "int8", "int16", "int32", "int64",
"float", "float32", "float64", "float128",
"uint", "uint8", "uint16", "uint32", "uint64",
"bignum", "const ",
"!", "varargs[$1]", "iter[$1]", "Error Type",
"unused0", "unused1",
"unused2", "varargs[$1]", "unused", "Error Type",
"BuiltInTypeClass", "UserTypeClass",
"UserTypeClassInst", "CompositeTypeClass",
"and", "or", "not", "any", "static", "TypeFromExpr", "FieldAccessor",
@@ -534,7 +528,7 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
add(result, typeToString(t.sons[i]))
if i < sonsLen(t) - 1: add(result, ", ")
add(result, ')')
of tyPtr, tyRef, tyVar, tyMutable, tyConst:
of tyPtr, tyRef, tyVar:
result = typeToStr[t.kind]
if t.len >= 2:
setLen(result, result.len-1)
@@ -606,7 +600,7 @@ proc firstOrd(t: PType): BiggestInt =
else:
assert(t.n.sons[0].kind == nkSym)
result = t.n.sons[0].sym.position
of tyGenericInst, tyDistinct, tyConst, tyMutable, tyTypeDesc, tyFieldAccessor:
of tyGenericInst, tyDistinct, tyTypeDesc, tyFieldAccessor:
result = firstOrd(lastSon(t))
of tyOrdinal:
if t.len > 0: result = firstOrd(lastSon(t))
@@ -642,8 +636,7 @@ proc lastOrd(t: PType): BiggestInt =
of tyEnum:
assert(t.n.sons[sonsLen(t.n) - 1].kind == nkSym)
result = t.n.sons[sonsLen(t.n) - 1].sym.position
of tyGenericInst, tyDistinct, tyConst, tyMutable,
tyTypeDesc, tyFieldAccessor:
of tyGenericInst, tyDistinct, tyTypeDesc, tyFieldAccessor:
result = lastOrd(lastSon(t))
of tyProxy: result = 0
of tyOrdinal:
@@ -656,7 +649,7 @@ proc lastOrd(t: PType): BiggestInt =
proc lengthOrd(t: PType): BiggestInt =
case t.kind
of tyInt64, tyInt32, tyInt: result = lastOrd(t)
of tyDistinct, tyConst, tyMutable: result = lengthOrd(t.sons[0])
of tyDistinct: result = lengthOrd(t.sons[0])
else:
let last = lastOrd t
let first = firstOrd t
@@ -925,7 +918,7 @@ proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
case a.kind
of tyEmpty, tyChar, tyBool, tyNil, tyPointer, tyString, tyCString,
tyInt..tyBigNum, tyStmt, tyExpr, tyVoid:
tyInt..tyUInt64, tyStmt, tyExpr, tyVoid:
result = sameFlags(a, b)
of tyStatic, tyFromExpr:
result = exprStructuralEquivalent(a.n, b.n) and sameFlags(a, b)
@@ -965,8 +958,7 @@ proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
result = a.sym.position == b.sym.position
of tyGenericInvocation, tyGenericBody, tySequence,
tyOpenArray, tySet, tyRef, tyPtr, tyVar, tyArrayConstr,
tyArray, tyProc, tyConst, tyMutable, tyVarargs,
tyOrdinal, tyTypeClasses, tyFieldAccessor:
tyArray, tyProc, tyVarargs, tyOrdinal, tyTypeClasses, tyFieldAccessor:
cycleCheck()
if a.kind == tyUserTypeClass and a.n != nil: return a.n == b.n
result = sameChildrenAux(a, b, c) and sameFlags(a, b)
@@ -980,7 +972,7 @@ proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
sameValue(a.n.sons[1], b.n.sons[1])
of tyGenericInst: discard
of tyNone: result = false
of tyUnused: internalError("sameFlags")
of tyUnused, tyUnused0, tyUnused1, tyUnused2: internalError("sameFlags")
proc sameBackendType*(x, y: PType): bool =
var c = initSameTypeClosure()
@@ -1121,7 +1113,7 @@ proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind,
result = t
of tyNil:
if kind != skConst: result = t
of tyString, tyBool, tyChar, tyEnum, tyInt..tyBigNum, tyCString, tyPointer:
of tyString, tyBool, tyChar, tyEnum, tyInt..tyUInt64, tyCString, tyPointer:
result = nil
of tyOrdinal:
if kind != skParam: result = t
@@ -1144,7 +1136,7 @@ proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind,
else: result = typeAllowedAux(marker, t.lastSon, skVar, flags+{taHeap})
of tyPtr:
result = typeAllowedAux(marker, t.lastSon, skVar, flags+{taHeap})
of tyArrayConstr, tySet, tyConst, tyMutable:
of tyArrayConstr, tySet:
for i in countup(0, sonsLen(t) - 1):
result = typeAllowedAux(marker, t.sons[i], kind, flags)
if result != nil: break
@@ -1161,7 +1153,7 @@ proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind,
# for now same as error node; we say it's a valid type as it should
# prevent cascading errors:
result = nil
of tyUnused: internalError("typeAllowedAux")
of tyUnused, tyUnused0, tyUnused1, tyUnused2: internalError("typeAllowedAux")
proc typeAllowed*(t: PType, kind: TSymKind): PType =
# returns 'nil' on success and otherwise the part of the type that is
@@ -1252,8 +1244,7 @@ proc computeSizeAux(typ: PType, a: var BiggestInt): BiggestInt =
if typ.callConv == ccClosure: result = 2 * ptrSize
else: result = ptrSize
a = ptrSize
of tyNil, tyCString, tyString, tySequence, tyPtr, tyRef, tyVar, tyOpenArray,
tyBigNum:
of tyNil, tyCString, tyString, tySequence, tyPtr, tyRef, tyVar, tyOpenArray:
let base = typ.lastSon
if base == typ or (base.kind == tyTuple and base.size==szIllegalRecursion):
result = szIllegalRecursion
@@ -1313,7 +1304,7 @@ proc computeSizeAux(typ: PType, a: var BiggestInt): BiggestInt =
if result < 0: return
if a < maxAlign: a = maxAlign
result = align(result, a)
of tyGenericInst, tyDistinct, tyGenericBody, tyMutable, tyConst:
of tyGenericInst, tyDistinct, tyGenericBody:
result = computeSizeAux(lastSon(typ), a)
of tyTypeDesc:
result = computeSizeAux(typ.base, a)

View File

@@ -269,9 +269,6 @@ proc mapTypeToAstX(t: PType; info: TLineInfo;
of tyUInt16: result = atomicType("uint16", mUint16)
of tyUInt32: result = atomicType("uint32", mUint32)
of tyUInt64: result = atomicType("uint64", mUint64)
of tyBigNum: result = atomicType("bignum", mNone)
of tyConst: result = mapTypeToBracket("const", mNone, t, info)
of tyMutable: result = mapTypeToBracket("mutable", mNone, t, info)
of tyVarargs: result = mapTypeToBracket("varargs", mVarargs, t, info)
of tyProxy: result = atomicType("error", mNone)
of tyBuiltInTypeClass:
@@ -294,7 +291,7 @@ proc mapTypeToAstX(t: PType; info: TLineInfo;
result.add atomicType("static", mNone)
if t.n != nil:
result.add t.n.copyTree
of tyUnused: internalError("mapTypeToAstX")
of tyUnused, tyUnused0, tyUnused1, tyUnused2: internalError("mapTypeToAstX")
proc opMapTypeToAst*(t: PType; info: TLineInfo): PNode =
result = mapTypeToAstX(t, info, false, true)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -15,6 +15,11 @@ when defined(gcc) and defined(windows):
else:
{.link: "icons/koch_icon.o".}
when defined(amd64) and defined(windows) and defined(vcc):
{.link: "icons/koch-amd64-windows-vcc.res" .}
when defined(i386) and defined(windows) and defined(vcc):
{.link: "icons/koch-i386-windows-vcc.res" .}
import
os, strutils, parseopt, osproc, streams

View File

@@ -78,7 +78,7 @@ type
nnkBreakState
NimNodeKinds* = set[NimNodeKind]
NimTypeKind* = enum
NimTypeKind* = enum # some types are no longer used, see ast.nim
ntyNone, ntyBool, ntyChar, ntyEmpty,
ntyArrayConstr, ntyNil, ntyExpr, ntyStmt,
ntyTypeDesc, ntyGenericInvocation, ntyGenericBody, ntyGenericInst,
@@ -90,8 +90,8 @@ type
ntyInt8, ntyInt16, ntyInt32, ntyInt64,
ntyFloat, ntyFloat32, ntyFloat64, ntyFloat128,
ntyUInt, ntyUInt8, ntyUInt16, ntyUInt32, ntyUInt64,
ntyBigNum,
ntyConst, ntyMutable, ntyVarargs,
ntyUnused0, ntyUnused1, ntyUnused2,
ntyVarargs,
ntyUnused,
ntyError,
ntyBuiltinTypeClass, ntyConcept, ntyConceptInst, ntyComposite,
@@ -890,6 +890,30 @@ proc boolVal*(n: NimNode): bool {.compileTime, noSideEffect.} =
if n.kind == nnkIntLit: n.intVal != 0
else: n == bindSym"true" # hacky solution for now
macro expandMacros*(body: typed): untyped =
## Expands one level of macro - useful for debugging.
## Can be used to inspect what happens when a macro call is expanded,
## without altering its result.
##
## For instance,
##
## .. code-block:: nim
## import future, macros
##
## let
## x = 10
## y = 20
## expandMacros:
## dump(x + y)
##
## will actually dump `x + y`, but at the same time will print at
## compile time the expansion of the ``dump`` macro, which in this
## case is ``debugEcho ["x + y", " = ", x + y]``.
template inner(x: untyped): untyped = x
result = getAst(inner(body))
echo result.toStrLit
when not defined(booting):
template emit*(e: static[string]): untyped {.deprecated.} =
## accepts a single string argument and treats it as nim code

View File

@@ -431,8 +431,12 @@ proc initRegex(pattern: string, flags: int, study = true): Regex =
raise SyntaxError(msg: $errorMsg, pos: errOffset, pattern: pattern)
if study:
# XXX investigate JIT
result.pcreExtra = pcre.study(result.pcreObj, 0x0, addr errorMsg)
var options: cint = 0
var hasJit: cint
if pcre.config(pcre.CONFIG_JIT, addr hasJit) == 0:
if hasJit == 1'i32:
options = pcre.STUDY_JIT_COMPILE
result.pcreExtra = pcre.study(result.pcreObj, options, addr errorMsg)
if errorMsg != nil:
raise StudyError(msg: $errorMsg)

View File

@@ -87,7 +87,12 @@ proc re*(s: string, flags = {reExtended, reStudy}): Regex =
result.h = rawCompile(s, cast[cint](flags - {reStudy}))
if reStudy in flags:
var msg: cstring
result.e = pcre.study(result.h, 0, addr msg)
var options: cint = 0
var hasJit: cint
if pcre.config(pcre.CONFIG_JIT, addr hasJit) == 0:
if hasJit == 1'i32:
options = pcre.STUDY_JIT_COMPILE
result.e = pcre.study(result.h, options, addr msg)
if not isNil(msg): raiseInvalidRegex($msg)
proc matchOrFind(s: string, pattern: Regex, matches: var openArray[string],
@@ -214,7 +219,7 @@ proc find*(s: string, pattern: Regex, start = 0): int =
var
rtarray = initRtArray[cint](3)
rawMatches = rtarray.getRawData
res = pcre.exec(pattern.h, nil, s, len(s).cint, start.cint, 0'i32,
res = pcre.exec(pattern.h, pattern.e, s, len(s).cint, start.cint, 0'i32,
cast[ptr cint](rawMatches), 3)
if res < 0'i32: return res
return rawMatches[0]

44
lib/js/jsconsole.nim Normal file
View File

@@ -0,0 +1,44 @@
#
#
# Nim's Runtime Library
# (c) Copyright 2012 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
## Wrapper for the `console` object for the `JavaScript backend
## <backends.html#the-javascript-target>`_.
when not defined(js) and not defined(Nimdoc):
{.error: "This module only works on the JavaScript platform".}
import macros
type Console* {.importc.} = ref object of RootObj
proc convertToConsoleLoggable*[T](v: T): RootRef {.importcpp: "#".}
template convertToConsoleLoggable*(v: string): RootRef = cast[RootRef](cstring(v))
proc logImpl(console: Console) {.importcpp: "log", varargs.}
proc debugImpl(console: Console) {.importcpp: "debug", varargs.}
proc infoImpl(console: Console) {.importcpp: "info", varargs.}
proc errorImpl(console: Console) {.importcpp: "error", varargs.}
proc makeConsoleCall(console: NimNode, procName: NimNode, args: NimNode): NimNode =
result = newCall(procName, console)
for c in args: result.add(c)
macro log*(console: Console, args: varargs[RootRef, convertToConsoleLoggable]): untyped =
makeConsoleCall(console, bindSym "logImpl", args)
macro debug*(console: Console, args: varargs[RootRef, convertToConsoleLoggable]): untyped =
makeConsoleCall(console, bindSym "debugImpl", args)
macro info*(console: Console, args: varargs[RootRef, convertToConsoleLoggable]): untyped =
makeConsoleCall(console, bindSym "infoImpl", args)
macro error*(console: Console, args: varargs[RootRef, convertToConsoleLoggable]): untyped =
makeConsoleCall(console, bindSym "errorImpl", args)
var console* {.importc, nodecl.}: Console

View File

@@ -177,3 +177,24 @@ macro `[]`*(lc: ListComprehension, comp, typ: untyped): untyped =
newIdentNode("@"),
newNimNode(nnkBracket))),
result))))
macro dump*(x: typed): untyped =
## Dumps the content of an expression, useful for debugging.
## It accepts any expression and prints a textual representation
## of the tree representing the expression - as it would appear in
## source code - together with the value of the expression.
##
## As an example,
##
## .. code-block:: nim
## let
## x = 10
## y = 20
## dump(x + y)
##
## will print ``x + y = 30``.
let s = x.toStrLit
let r = quote do:
debugEcho `s`, " = ", `x`
return r

View File

@@ -62,7 +62,6 @@ type
tyUInt16,
tyUInt32,
tyUInt64,
tyBigNum,
TNimNodeKind = enum nkNone, nkSlot, nkList, nkCase
TNimNode {.codegenType.} = object

13
tests/js/tconsole.nim Normal file
View File

@@ -0,0 +1,13 @@
discard """
output: '''Hello, console
1 2 3
1 'hi' 1.1'''
"""
# This file tests the JavaScript console
import jsconsole
console.log("Hello, console")
console.log(1, 2, 3)
console.log(1, "hi", 1.1)

13
tests/macros/tdump.nim Normal file
View File

@@ -0,0 +1,13 @@
discard """
output: '''x = 10
x + y = 30
'''
"""
import future
let
x = 10
y = 20
dump x
dump(x + y)

View File

@@ -382,8 +382,14 @@ proc `&.?`(a, b: string): string =
proc `&?.`(a, b: string): string =
# candidate for the stdlib?
result = if a.endswith(b): a else: a & b
proc processSingleTest(r: var TResults, cat: Category, options, test: string) =
let test = "tests" & DirSep &.? cat.string / test
proc processCategory(r: var TResults, cat: Category, options: string, fileGlob: string = "t*.nim") =
if existsFile(test): testSpec r, makeTest(test, options, cat)
else: echo "[Warning] - ", test, " test does not exist"
proc processCategory(r: var TResults, cat: Category, options: string) =
case cat.string.normalize
of "rodfiles":
when false: compileRodFiles(r, cat, options)
@@ -424,5 +430,5 @@ proc processCategory(r: var TResults, cat: Category, options: string, fileGlob:
# We can't test it because it depends on a third party.
discard # TODO: Move untestable tests to someplace else, i.e. nimble repo.
else:
for name in os.walkFiles("tests" & DirSep &.? cat.string / fileGlob):
for name in os.walkFiles("tests" & DirSep &.? cat.string / "t*.nim"):
testSpec r, makeTest(name, options, cat)

View File

@@ -445,7 +445,7 @@ proc main() =
let (dir, file) = splitPath(p.key.string)
let (_, subdir) = splitPath(dir)
var cat = Category(subdir)
processCategory(r, cat, p.cmdLineRest.string, file)
processSingleTest(r, cat, p.cmdLineRest.string, file)
of "html":
var commit = 0
discard parseInt(p.cmdLineRest.string, commit)