Skip to content

Commit dd0c491

Browse files
committed
update
Signed-off-by: George Lemon <georgelemon@protonmail.com>
1 parent dd6d9a3 commit dd0c491

File tree

19 files changed

+90
-60
lines changed

19 files changed

+90
-60
lines changed

src/tim.nim

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#
33
# (c) 2025 George Lemon | LGPL-v3 License
44
# Made by Humans from OpenPeeps
5-
# https://github.com/openpeeps/tim | https://tim-engine.com
5+
# https://github.com/openpeeps/tim | https://openpeeps.dev/packages/tim
66

77
when defined napi_build:
88
# Building Tim Engine as a NAPI module
@@ -72,6 +72,7 @@ elif isMainModule:
7272
## Create a symlink to a package in local source
7373
remove string(`pkg`):
7474
## Remove a package from local source
75+
7576
else:
7677
# Importing Tim Engine as a Nimble library
7778
# so it can be used in other Nim projects

src/tim/app/build.nim

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,23 +11,26 @@ import pkg/[flatty, jsony]
1111
import pkg/kapsis/[cli, runtime]
1212

1313
import ../engine/[ast, parser, codegen, chunk, vm, sym]
14-
import ../engine/stdlib/[libsystem]
14+
import ../engine/stdlib/[libsystem, libarrays]
1515

1616
import ../engine/transpilers/[jsgen, pygen, rbgen, phpgen, luagen]
1717

1818
proc srcCommand*(v: Values) =
1919
## Transpiles `timl` code to a target source
2020
# parse the script
21+
var srcPath = $(v.get("timl").getPath)
2122
let
22-
srcPath = getCurrentDir() / $(v.get("timl").getPath)
2323
ext = v.get("--ext").getStr
24-
pretty = v.has("--pretty")
24+
flagPrettyPrint = v.has("--pretty")
2525
flagNoCache = v.has("--nocache")
2626
flagRecache = v.has("--recache")
2727
hasJsonFlag = v.has("--json-errors")
2828
outputPath = if v.has("-o"): v.get("-o").getStr else: ""
29-
withBenchtime = v.has("--bench")
29+
flagBencmarks = v.has("--bench")
3030
# enableWatcher = v.has("w")
31+
32+
if not srcPath.isAbsolute:
33+
srcPath = getCurrentDir() / srcPath
3134

3235
let
3336
timlCode = readFile(srcPath)
@@ -69,6 +72,9 @@ proc srcCommand*(v: Values) =
6972
# let stringsLib = initStrings(script, systemModule)
7073
# module.load(stringsLib)
7174

75+
let arraysLib = initArrays(script, systemModule)
76+
module.load(arraysLib)
77+
7278
script.stdpos = script.procs.high
7379

7480
# let timesModule = script.initTimes(systemModule)
@@ -108,7 +114,7 @@ proc srcCommand*(v: Values) =
108114

109115

110116
# display the time taken for compilation
111-
if withBenchtime:
117+
if flagBencmarks:
112118
displayInfo("Done in " & $(getMonotime() - t))
113119

114120
#

src/tim/engine/ast.nim

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
#
66
# (c) 2025 George Lemon | LGPL-v3 License
77
# Made by Humans from OpenPeeps
8-
# https://github.com/openpeeps/tim | https://tim-engine.com
8+
# https://github.com/openpeeps/tim | https://openpeeps.dev/packages/tim
99

1010
import std/[hashes, strutils, json, sequtils, options]
1111

@@ -186,7 +186,8 @@ proc hash*(node: Node): Hash =
186186
proc `$`*(node: Node): string =
187187
## Stringify a node. This only supports leaf nodes, for trees,
188188
## use ``treeRepr``.
189-
assert node.kind in LeafNodes, "only leaf nodes can be `$`'ed"
189+
assert node.kind in LeafNodes, "only leaf nodes can be `$`'ed. Got " &
190+
$node.kind
190191
case node.kind
191192
of nkEmpty: result = ""
192193
of nkBool: result = $node.boolVal

src/tim/engine/chunk.nim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
#
66
# (c) 2025 George Lemon | LGPL-v3 License
77
# Made by Humans from OpenPeeps
8-
# https://github.com/openpeeps/tim | https://tim-engine.com
8+
# https://github.com/openpeeps/tim | https://openpeeps.dev/packages/tim
99

1010
import std/[tables]
1111

src/tim/engine/codegen.nim

Lines changed: 36 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
#
66
# (c) 2025 George Lemon | LGPL-v3 License
77
# Made by Humans from OpenPeeps
8-
# https://github.com/openpeeps/tim | https://tim-engine.com
8+
# https://github.com/openpeeps/tim | https://openpeeps.dev/packages/tim
99

1010
import std/[macros, options, os, hashes,
1111
sequtils, strutils, ropes, tables, json]
@@ -190,11 +190,6 @@ proc addSym(gen: var CodeGen, sym: Sym,
190190
if not gen.module.add(sym, name):
191191
name.error(ErrGlobalRedeclaration % [$name])
192192

193-
#
194-
# Forward declarations
195-
#
196-
proc genGetField(node: Node): Sym {.codegen.}
197-
198193
proc newProc*(script: Script, name, impl: Node,
199194
params: seq[ProcParam], returnTy: Sym,
200195
kind: ProcKind, exported = false,
@@ -328,6 +323,7 @@ proc genIterator(node: Node, isInstantiation = false): Sym {.codegen.}
328323
proc genObject(node: Node, isInstantiation = false): Sym {.codegen.}
329324
proc genObjectStorage(node: Node, isInstantiation = false): Sym {.codegen.}
330325
proc genArray(node: Node, isInstantiation = false): Sym {.codegen.}
326+
proc genGetField(node: Node): Sym {.codegen.}
331327
proc genTypeDef(node: Node): Sym {.codegen.}
332328
proc htmlConstr(node: Node): Sym {.codegen.}
333329

@@ -473,7 +469,10 @@ proc lookup(gen: var CodeGen, symName: Node, quiet = false): Sym =
473469
# find out the symbol's name
474470
var name: Node
475471
case symName.kind
476-
of nkIdent: name = symName # regular ident
472+
of nkIdent:
473+
name = symName # regular ident
474+
of nkCall:
475+
name = symName[0] # function call
477476
of nkVarTy: name = symName.varType
478477
of nkIndex:
479478
if symName[0].kind == nkIndex:
@@ -710,7 +709,8 @@ proc splitCall(ast: Node): tuple[callee: Sym, args: seq[Node]] {.codegen.} =
710709
ast[1].error("Use bracket notation to access JSON fields or items")
711710
else:
712711
callee = ast[1]
713-
args = @[ast[0]]
712+
args.add(ast[0])
713+
args.add(ast[1][1..^1])
714714
of nkBracket:
715715
# this is an array access, so we return the array and the index
716716
# as the callee and the argument, respectively
@@ -1090,10 +1090,24 @@ proc call(node: Node): Sym {.codegen.} =
10901090
proc genGetField(node: Node): Sym {.codegen.} =
10911091
# Generate code for field access.
10921092
# all fields must be idents, so we check for that.
1093+
case node[1].kind
1094+
of nkCall:
1095+
let (fnSym, fnParams) = gen.splitCall(node)
1096+
var argTypes: seq[Sym]
1097+
for arg in fnParams:
1098+
argTypes.add(gen.genExpr(arg))
1099+
return gen.callProc(fnSym, argTypes, node)
1100+
else: discard
10931101
if node[1].kind notin {nkIdent, nkBracket}:
10941102
node[1].error(ErrInvalidField % $node[1])
1095-
let typeSym = gen.genExpr(node[0]) # generate the left-hand side
1096-
1103+
var valTy = gen.genExpr(node[0]) # generate the left-hand side
1104+
var varTy: SymKind
1105+
case valTy.kind
1106+
of skVars:
1107+
varTy = valTy.kind
1108+
valTy = valTy.varTy
1109+
else: discard
1110+
10971111
# get the field's name
10981112
var fieldName: string
10991113
if node[1].kind == nkIdent:
@@ -1102,12 +1116,11 @@ proc genGetField(node: Node): Sym {.codegen.} =
11021116
# if the field is accessed using the bracket notation, we use the ident
11031117
# inside the brackets as the field name
11041118
fieldName = node[1][0].ident
1105-
11061119
# only objects have fields. we also check if the given object *does* have the
11071120
# field in question, and generate an error if not
1108-
if typeSym.tyKind == tyObject and typeSym.objectFields.hasKey(fieldName):
1121+
if valTy.tyKind == tyObject and valTy.objectFields.hasKey(fieldName):
11091122
# we use the getF opcode to push fields onto the stack.
1110-
let field = typeSym.objectFields[fieldName]
1123+
let field = valTy.objectFields[fieldName]
11111124
result = field.ty
11121125
gen.chunk.emit(opcGetF)
11131126
gen.chunk.emit(field.id.uint8)
@@ -1116,8 +1129,8 @@ proc genGetField(node: Node): Sym {.codegen.} =
11161129
# an appropriate proc that will retrieve it for us
11171130
let getter = gen.lookup(node[1])
11181131
if getter == nil:
1119-
node[1].error(ErrNonExistentField % [fieldName, $typeSym])
1120-
result = gen.callProc(getter, argTypes = @[typeSym], errorNode = node)
1132+
node[1].error(ErrNonExistentField % [fieldName, $valTy])
1133+
result = gen.callProc(getter, argTypes = @[valTy], errorNode = node)
11211134

11221135
proc genArrayAccess(node: Node): Sym {.codegen.} =
11231136
# Generate code for array access.
@@ -1130,7 +1143,12 @@ proc genArrayAccess(node: Node): Sym {.codegen.} =
11301143
of skVars:
11311144
valTy = valTy.varTy
11321145
else: discard
1133-
1146+
1147+
case indexTy.kind
1148+
of skVars:
1149+
indexTy = indexTy.varTy
1150+
else: discard
1151+
11341152
case valTy.tyKind
11351153
of tyJson:
11361154
# generate the code for accessing a JSON array
@@ -1644,7 +1662,8 @@ proc genExpr(node: Node, varUnwrap = false): Sym {.codegen.} =
16441662
else: symNode)
16451663
of nkPrefix: # prefix operators
16461664
result = gen.prefix(node)
1647-
of nkInfix: # infix operators
1665+
of nkInfix:
1666+
# handle infix expressions
16481667
result = gen.infix(node)
16491668
of nkDot:
16501669
# generate code for object/class field access

src/tim/engine/errors.nim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
#
66
# (c) 2025 George Lemon | LGPL-v3 License
77
# Made by Humans from OpenPeeps
8-
# https://github.com/openpeeps/tim | https://tim-engine.com
8+
# https://github.com/openpeeps/tim | https://openpeeps.dev/packages/tim
99

1010
const
1111
ErrorFmt* = "$1($2:$3): $4"

src/tim/engine/parser.nim

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,14 @@
22
#
33
# (c) 2025 George Lemon | LGPL-v3 License
44
# Made by Humans from OpenPeeps
5-
# https://github.com/openpeeps/tim | https://tim-engine.com
5+
# https://github.com/openpeeps/tim | https://openpeeps.dev/packages/tim
66

77
import std/[macros, lexbase, tables, strutils, critbits, options]
8-
import ./[tokens, errors, ast]
8+
9+
import ./tokens
10+
# import ./lexer
11+
12+
import ./[errors, ast]
913

1014
type
1115
Parser* = object
@@ -16,8 +20,6 @@ type
1620
classCacheAttr: CritBitTree[Node]
1721
# A critbit tree used to cache static class attributes
1822
# prefixed with a dot (.) for faster parsing and memory usage optimization.
19-
# attrCacheAttr: CritBitTree[Node]
20-
# A critbit tree used to cache `key=value` HTML attributes
2123
lvl: int
2224

2325
TimParserError* = object of ValueError
@@ -645,11 +647,11 @@ prefixHandle parseIdentVar:
645647
prefixHandle parseJavaScript:
646648
result = ast.newNode(nkJavaScriptSnippet)
647649
result.snippetCode = p.curr.value
648-
for attr in p.curr.attr:
649-
let identNode = ast.newNode(nkIdent)
650-
let id = attr.split("_")
651-
identNode.ident = id[1]
652-
add result.snippetCodeAttrs, (attr, identNode)
650+
# for attr in p.curr.attr:
651+
# let identNode = ast.newNode(nkIdent)
652+
# let id = attr.split("_")
653+
# identNode.ident = id[1]
654+
# add result.snippetCodeAttrs, (attr, identNode)
653655
walk p
654656

655657
#
@@ -1153,8 +1155,8 @@ prefixHandle parseStmt:
11531155
return prefixFn(p)
11541156

11551157
proc parseScript*(astProgram: var Ast, code: string) =
1156-
var p = Parser(lex: newLexer(code, allowMultilineStrings = true))
1157-
defer: p.lex.close()
1158+
var p = Parser(lex: newLexer(code))
1159+
# defer: p.lex.close()
11581160
p.curr = p.lex.getToken()
11591161
p.next = p.lex.getToken()
11601162
p.skipComments()

src/tim/engine/resolver.nim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#
33
# (c) 2025 George Lemon | LGPL-v3 License
44
# Made by Humans from OpenPeeps
5-
# https://github.com/openpeeps/tim | https://tim-engine.com
5+
# https://github.com/openpeeps/tim | https://openpeeps.dev/packages/tim
66

77
import std/[os, tables]
88

src/tim/engine/stdlib/libstrings.nim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
#
66
# (c) 2025 George Lemon | LGPL-v3 License
77
# Made by Humans from OpenPeeps
8-
# https://github.com/openpeeps/tim | https://tim-engine.com
8+
# https://github.com/openpeeps/tim | https://openpeeps.dev/packages/tim
99

1010
import std/[strutils, options, base64]
1111
import ../[chunk, codegen, ast, parser, sym, value]

src/tim/engine/stdlib/libsystem.nim

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
#
66
# (c) 2025 George Lemon | LGPL-v3 License
77
# Made by Humans from OpenPeeps
8-
# https://github.com/openpeeps/tim | https://tim-engine.com
8+
# https://github.com/openpeeps/tim | https://openpeeps.dev/packages/tim
99

1010
import std/[strutils, options, os, httpclient,
1111
httpcore, json, tables]
@@ -41,8 +41,8 @@ const
4141
const app* = parseJSON('$globalData')
4242
const this* = parseJSON('$localData')
4343
"""
44-
4544
InlineCode* = """
45+
4646
iterator `..`*(min: int, max: int): int {
4747
var i = $min
4848
if $i >= $max {
@@ -288,6 +288,15 @@ proc modSystem*(script: Script, globalData, localData: JsonNode): Module =
288288
result = initValue(len)
289289
)
290290

291+
script.addProc(result, "high", @[paramDef("x", tyArray)], tyInt,
292+
proc (args: StackView): Value =
293+
let len =
294+
if args[0].objectVal.fields.len > 0:
295+
len(args[0].objectVal.fields) - 1
296+
else: 0
297+
result = initValue(len)
298+
)
299+
291300
# script.addProc(result, "len", @[paramDef("x", tyObject)], tyInt,
292301
# proc (args: StackView): Value =
293302
# result = initValue(len(args[0].objectVal.fields)))

0 commit comments

Comments
 (0)