Skip to content

Commit

Permalink
upgrade generators
Browse files Browse the repository at this point in the history
  • Loading branch information
Ethosa committed Apr 17, 2024
1 parent 34e2f72 commit 7da2c9f
Show file tree
Hide file tree
Showing 4 changed files with 155 additions and 3 deletions.
118 changes: 118 additions & 0 deletions src/elyspkg/ast.nim
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,9 @@ template whileStmt*(c: ASTRoot, b: ASTRoot): WhileStmt =
template forInStmt*(v: seq[ASTRoot], o, b: ASTRoot): ForInStmt =
ForInStmt(vars: v, obj: o, body: b, kind: akForInStmt)

template forInGen*(v: seq[ASTRoot], o, b: ASTRoot, c: Option[ASTRoot]): ForInGenerator =
ForInGenerator(vars: v, obj: o, body: b, condition: c, kind: akForInStmt)

template funcStmt*(n: string, a: ArrayAST, kwa: ObjectAST, b: ASTRoot): FuncStmt =
FuncStmt(name: n, args: a, kwargs: kwa, body: b, kind: akFunc)

Expand Down Expand Up @@ -309,12 +312,32 @@ func `/`*(l, r: ASTRoot, env: Environment): ASTRoot =
a = l.eval(env)
b = r.eval(env)
if a.kind == akInt and b.kind == akInt:
if b.IntAST.val == 0:
zeroDivisionError(
"Can not divide by 0",
l.line, l.col, l.code, l.filepath
)
return floatAST(a.IntAST.val / b.IntAST.val)
elif a.kind == akInt and b.kind == akFloat:
if b.FloatAST.val == 0.0:
zeroDivisionError(
"Can not divide by 0",
l.line, l.col, l.code, l.filepath
)
return floatAst(a.IntAST.val.float / b.FloatAST.val)
elif a.kind == akFloat and b.kind == akInt:
if b.IntAST.val == 0:
zeroDivisionError(
"Can not divide by 0",
l.line, l.col, l.code, l.filepath
)
return floatAst(a.FloatAST.val / b.IntAST.val.float)
elif a.kind == akFloat and b.kind == akFloat:
if b.FloatAST.val == 0.0:
zeroDivisionError(
"Can not divide by 0",
l.line, l.col, l.code, l.filepath
)
return floatAst(a.FloatAST.val / b.FloatAST.val)
else:
valueError(
Expand All @@ -328,8 +351,18 @@ func `//`*(l, r: ASTRoot, env: Environment): ASTRoot =
a = l.eval(env)
b = r.eval(env)
if a.kind == akInt and b.kind == akInt:
if b.IntAST.val == 0:
zeroDivisionError(
"Can not divide by 0",
l.line, l.col, l.code, l.filepath
)
return intAST(a.IntAST.val div b.IntAST.val)
elif a.kind == akInt and b.kind == akFloat:
if b.IntAST.val == 0:
zeroDivisionError(
"Can not divide by 0",
l.line, l.col, l.code, l.filepath
)
return intAst(a.FloatAST.val.int div b.IntAST.val)
else:
valueError(
Expand Down Expand Up @@ -918,3 +951,88 @@ method eval*(self: ForInStmt, env: Environment): ASTRoot =
self.line, self.col, self.code, self.filepath
)
return res

method eval*(self: ForInGenerator, env: Environment): ASTRoot =
let
obj = self.obj.eval(env)
var
environment = newEnv(env)
res = arrAst(@[])
# check for variables
for i in self.vars:
if i.kind != akVar:
valueError(
"Can not iterate over " & obj.astValue(environment) &
" via " & i.astValue(environment),
self.line, self.col, self.code, self.filepath
)
case self.vars.len:
of 1:
let variable = self.vars[0].VarAST.name
case obj.kind:
of akArr:
for i in obj.ArrayAST.val:
environment.setDef(variable, i.eval(environment).ASTExpr)
let x = self.body.eval(environment)
if self.condition.isNone:
res.val.add x
elif self.condition.get.eval(environment):
res.val.add x
of akSliceExpr:
for i in obj.SliceExprAST.l.IntAST.val..obj.SliceExprAST.r.IntAST.val:
environment.setDef(variable, intAst(i))
let x = self.body.eval(environment)
if self.condition.isNone:
res.val.add x
elif self.condition.get.eval(environment):
res.val.add x
of akString:
for i in obj.StringAST.val:
environment.setDef(variable, stringAst($i))
let x = self.body.eval(environment)
if self.condition.isNone:
res.val.add x
elif self.condition.get.eval(environment):
res.val.add x
else:
valueError(
"Can not unpack " & $self.vars.len & " variables from " &
obj.astValue(env),
self.line, self.col, self.code, self.filepath
)
of 2:
let
variable1 = self.vars[0].VarAST.name
variable2 = self.vars[1].VarAST.name
case obj.kind:
of akArr:
for (index, value) in obj.ArrayAST.val.pairs:
environment.setDef(variable2, value.eval(environment).ASTExpr)
environment.setDef(variable1, intAst(index))
let x = self.body.eval(environment)
if self.condition.isNone:
res.val.add x
elif self.condition.get.eval(environment):
res.val.add x
of akString:
for (index, value) in obj.StringAST.val.pairs:
environment.setDef(variable2, stringAst($value))
environment.setDef(variable1, intAst(index))
let x = self.body.eval(environment)
if self.condition.isNone:
res.val.add x
elif self.condition.get.eval(environment):
res.val.add x
else:
valueError(
"Can not unpack " & $self.vars.len & " variables from " &
obj.astValue(env),
self.line, self.col, self.code, self.filepath
)
else:
valueError(
"Can not unpack " & $self.vars.len & " variables from " &
obj.astValue(env),
self.line, self.col, self.code, self.filepath
)
return res
25 changes: 23 additions & 2 deletions src/elyspkg/parser.nim
Original file line number Diff line number Diff line change
Expand Up @@ -200,8 +200,6 @@ func castFuncExpr(): Combinator =


func processStringFuncExpr(res: Result): Option[Result] =
{.noSideEffect.}:
echo res
astRes(
callAst(res.valx.val.get, arrAst(@[res.valy.ast]), objAst(@[])),
res.line, res.col, res.source, res.filepath
Expand Down Expand Up @@ -234,12 +232,35 @@ func methodCallExpr(): Combinator =
) ^ processMethodCallExpr


func processForInGenerator(res: Result): Option[Result] =
var arr: seq[ASTRoot] = @[]
for i in res.valx.valx.valx.valy.arr:
arr.add i.ast
var condition = none[ASTRoot]()
if res.valy.kind == rkPair:
condition = res.valy.valy.ast.some
astRes(forInGen(
arr, res.valx.valy.ast, res.valx.valx.valx.valx.valx.ast, condition
), res.line, res.col, res.source, res.filepath)
func forInGenerator(): Combinator =
(
(operator"[" + (
lazy(expr) + keyword"for" + repSep(idTag() ^ processVar, operator",") +
operator"in" + lazy(expr) + opt(keyword"if" + alt(
(operator"(" + lazy(expr) + operator")"),
lazy(expr)
))
) + operator"]") ^ processGroup
) ^ processForInGenerator


func exprTermPre(): Combinator =
(
exprGroup() |
lazy(ifStatement) |
lazy(stmtListEmbed) |
lazy(exprArray) |
lazy(forInGenerator) |
incDecStatement() |
unaryOperatorStmt() |
bExprNot() |
Expand Down
11 changes: 10 additions & 1 deletion src/elyspkg/result.nim
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ type
akEof,
akStmt, akStmtList, akAssign, akPrint, akIncDec, akElifBranch, akElseBranch,
akIfStmt, akBreak, akContinue, akWhile, akAssignBracket, akSwap, akForInStmt,
akForInGen,
akFunc
ASTRoot* = ref object of RootObj
kind*: ASTKind
Expand Down Expand Up @@ -133,6 +134,11 @@ type
vars*: seq[ASTRoot]
obj*: ASTRoot
body*: ASTRoot
ForInGenerator* = ref object of Stmt
vars*: seq[ASTRoot]
obj*: ASTRoot
body*: ASTRoot
condition*: Option[ASTRoot]
PrintStmt* = ref object of Stmt
data*: seq[Result]

Expand Down Expand Up @@ -204,7 +210,10 @@ func `$`*(ast: ASTRoot): string =
$ast.SwapStmt.toL & ", " & $ast.SwapStmt.toR & ")"
of akForInStmt:
"ForInStmt( (" & ast.ForInStmt.vars.join(", ") & ") in " & $ast.ForInStmt.obj &
$ast.ForInStmt.body & ")"
", " & $ast.ForInStmt.body & ")"
of akForInGen:
"ForInGenerator( (" & ast.ForInGenerator.vars.join(", ") & ") in " & $ast.ForInGenerator.obj &
", " & $ast.ForInGenerator.condition & ")"
else:
"ASTRoot(kind: " & $ast.kind & ")"

Expand Down
4 changes: 4 additions & 0 deletions tests/test.nim
Original file line number Diff line number Diff line change
Expand Up @@ -217,4 +217,8 @@ suite "Elys":
}
}
}
# here python-like generators
print [i for i in 0..10]
print [i for i in 0..10 if i % 2]
print [i*2 for i in 0..10 if i % 2]
"""

0 comments on commit 7da2c9f

Please sign in to comment.