mirror of https://github.com/japl-lang/japl.git
Fixed precedence of is added beta support for the as operator for casting
This commit is contained in:
parent
15072d3c56
commit
56938897d6
|
@ -66,9 +66,10 @@ type
|
|||
Assign,
|
||||
Or,
|
||||
And,
|
||||
Is,
|
||||
Eq,
|
||||
Comp,
|
||||
As,
|
||||
Is,
|
||||
Term,
|
||||
Factor,
|
||||
Unary,
|
||||
|
@ -319,6 +320,8 @@ proc binary(self: Compiler, canAssign: bool) =
|
|||
self.emitByte(OpCode.Band)
|
||||
of TokenType.IS:
|
||||
self.emitByte(OpCode.Is)
|
||||
of TokenType.AS:
|
||||
self.emitByte(OpCode.As)
|
||||
else:
|
||||
discard # Unreachable
|
||||
|
||||
|
@ -1149,7 +1152,9 @@ var rules: array[TokenType, ParseRule] = [
|
|||
makeRule(nil, binary, Precedence.Term), # BAND
|
||||
makeRule(nil, binary, Precedence.Term), # BOR
|
||||
makeRule(unary, nil, Precedence.None), # TILDE
|
||||
makeRule(nil, binary, Precedence.Is) # IS
|
||||
makeRule(nil, binary, Precedence.Is), # IS
|
||||
makeRule(nil, binary, Precedence.As) # AS
|
||||
|
||||
]
|
||||
|
||||
|
||||
|
|
|
@ -56,9 +56,8 @@ const RESERVED = to_table({
|
|||
"this": TokenType.THIS, "super": TokenType.SUPER,
|
||||
"del": TokenType.DEL, "break": TokenType.BREAK,
|
||||
"continue": TokenType.CONTINUE, "inf": TokenType.INF,
|
||||
"nan": TokenType.NAN,
|
||||
"is": TokenType.IS,
|
||||
"not": TokenType.NEG})
|
||||
"nan": TokenType.NAN, "is": TokenType.IS,
|
||||
"not": TokenType.NEG, "as": TokenType.AS})
|
||||
type
|
||||
Lexer* = ref object
|
||||
source*: string
|
||||
|
|
|
@ -69,7 +69,8 @@ type
|
|||
Bor,
|
||||
Band,
|
||||
Bnot,
|
||||
Is
|
||||
Is,
|
||||
As
|
||||
|
||||
|
||||
|
||||
|
@ -81,7 +82,7 @@ const simpleInstructions* = {OpCode.Return, OpCode.Add, OpCode.Multiply,
|
|||
OpCode.Xor, OpCode.Not, OpCode.Equal,
|
||||
OpCode.Greater, OpCode.Less, OpCode.GetItem,
|
||||
OpCode.Slice, OpCode.Pop, OpCode.Negate,
|
||||
OpCode.Is}
|
||||
OpCode.Is, OpCode.As}
|
||||
const constantInstructions* = {OpCode.Constant, OpCode.DefineGlobal,
|
||||
OpCode.GetGlobal, OpCode.SetGlobal,
|
||||
OpCode.DeleteGlobal}
|
||||
|
|
|
@ -29,7 +29,7 @@ type
|
|||
WHILE, DEL, BREAK, EOF,
|
||||
COLON, CONTINUE, CARET,
|
||||
SHL, SHR, NAN, INF, BAND,
|
||||
BOR, TILDE, IS
|
||||
BOR, TILDE, IS, AS
|
||||
Token* = ref object
|
||||
kind*: TokenType
|
||||
lexeme*: string
|
||||
|
|
|
@ -19,6 +19,7 @@ import baseObject
|
|||
import numbers
|
||||
import ../memory
|
||||
import strutils
|
||||
import strformat
|
||||
|
||||
|
||||
type
|
||||
|
@ -62,8 +63,10 @@ proc isFalsey*(self: ptr String): bool =
|
|||
|
||||
|
||||
proc stringify*(self: ptr String): string =
|
||||
result = self.toStr()
|
||||
|
||||
if self.len == 0:
|
||||
result = "''"
|
||||
else:
|
||||
result = self.toStr()
|
||||
|
||||
proc typeName*(self: ptr String): string =
|
||||
return "string"
|
||||
|
|
|
@ -24,6 +24,8 @@ import japlNil
|
|||
import numbers
|
||||
import native
|
||||
|
||||
import parseutils
|
||||
|
||||
|
||||
proc typeName*(self: ptr Obj): string =
|
||||
## Returns the name of the object's type
|
||||
|
@ -403,6 +405,46 @@ proc gt*(self: ptr Obj, other: ptr Obj): bool =
|
|||
raise newException(NotImplementedError, "")
|
||||
|
||||
|
||||
proc objAs*(self: ptr Obj, other: ObjectType): ptr Obj =
|
||||
## Returns the result of self as other
|
||||
## (casts self to other's type)
|
||||
|
||||
# TODO -> This is in beta!
|
||||
case other:
|
||||
of ObjectType.String:
|
||||
result = stringify(self).asStr()
|
||||
of ObjectType.Integer:
|
||||
case self.kind:
|
||||
of ObjectType.String:
|
||||
var intVal: int
|
||||
discard parseInt(cast[ptr String](self).toStr(), intVal)
|
||||
result = intVal.asInt()
|
||||
of ObjectType.Float:
|
||||
var floatVal: float64
|
||||
discard (parseFloat(cast[ptr Float](self).stringify(), floatVal))
|
||||
result = int(floatVal).asInt()
|
||||
of ObjectType.Integer:
|
||||
result = self
|
||||
else:
|
||||
raise newException(NotImplementedError, "")
|
||||
of ObjectType.Float:
|
||||
case self.kind:
|
||||
of ObjectType.String:
|
||||
var floatVal: float64
|
||||
discard parseFloat(cast[ptr String](self).toStr(), floatVal)
|
||||
result = floatVal.asFloat()
|
||||
of ObjectType.Integer:
|
||||
var intVal: int
|
||||
discard parseInt(cast[ptr Integer](self).stringify(), intVal)
|
||||
result = float(intVal).asFloat()
|
||||
of ObjectType.Float:
|
||||
result = self
|
||||
else:
|
||||
raise newException(NotImplementedError, "")
|
||||
|
||||
else:
|
||||
raise newException(NotImplementedError, "")
|
||||
|
||||
|
||||
## Utilities to inspect JAPL objects
|
||||
|
||||
|
|
10
src/vm.nim
10
src/vm.nim
|
@ -326,6 +326,7 @@ proc readLongConstant(self: CallFrame): ptr Obj =
|
|||
copyMem(idx.addr, unsafeAddr(arr), sizeof(arr))
|
||||
result = self.function.chunk.consts[idx]
|
||||
|
||||
|
||||
proc showRuntime*(self: VM, frame: CallFrame, iteration: uint64) =
|
||||
## Shows debug information about the current
|
||||
## state of the virtual machine
|
||||
|
@ -526,6 +527,14 @@ proc run(self: VM, repl: bool): InterpretResult =
|
|||
var right = self.pop()
|
||||
var left = self.pop()
|
||||
self.push(self.getBoolean(left == right))
|
||||
of OpCode.As:
|
||||
var right = self.pop()
|
||||
var left = self.pop()
|
||||
try:
|
||||
self.push(objAs(left, right.kind))
|
||||
except NotImplementedError:
|
||||
self.error(newTypeError(&"unsupported binary operator 'as' for objects of type '{left.typeName()}' and '{right.typeName()}'"))
|
||||
return RuntimeError
|
||||
of OpCode.GetItem:
|
||||
# TODO: More generic method
|
||||
if not self.slice():
|
||||
|
@ -617,6 +626,7 @@ proc run(self: VM, repl: bool): InterpretResult =
|
|||
of OpCode.Return:
|
||||
var retResult = self.pop()
|
||||
if repl and not self.lastPop.isNil() and self.frameCount == 1:
|
||||
# TODO -> Make this more efficient (move into japl.nim?)
|
||||
# Prints the last expression to stdout as long as we're
|
||||
# in REPL mode, the expression isn't nil and we're at the
|
||||
# top-level code
|
||||
|
|
|
@ -9,7 +9,7 @@ print(true and 2);//output:2
|
|||
print(false or 5);//output:5
|
||||
print(0 or 4);//output:4
|
||||
print(0 and true);//output:0
|
||||
print("" and true);//output:
|
||||
print("" and true);//output:''
|
||||
print("" or true);//output:true
|
||||
print(1 or 2 or 3 or 4);//output:1
|
||||
print(1 and 2 and 3 and 4);//output:4
|
||||
|
|
Loading…
Reference in New Issue