Closed thacuber2a03 closed 1 month ago
No, this is not possible. The feature would have a high runtime cost. It has been considered in #179 and rejected.
However, I cannot see why you need this hierarchy of interfaces at all. Your Value
is just a VM stack slot, not even an AST node. It's quite "passive", i.e., it shouldn't know how to evaluate()
itself, as this is done by the appropriate VM instructions. Everything on the stack, including functions and objects, can be Value
s.
My radical suggestion is:
type Value* = any
Thus you also get the type information out of the box. Why write
if a.valueType() == .String && b.valueType() == .String {
push(value::String(a) + value::String(b))
}
if you can write
if lhs, rhs := ^str(a), ^str(b); lhs != null && rhs != null {
push(lhs^ + rhs^)
}
?
Thus you also get the type information out of the box. Why write
if a.valueType() == .String && b.valueType() == .String { push(value::String(a) + value::String(b)) }
if you can write
if lhs, rhs := ^str(a), ^str(b); lhs != null && rhs != null { push(lhs^ + rhs^) }
?
what about the values that aren't base types, like value::Nil
:
type Nil* = struct {}
or, say, this Function
type:
type Function* = struct {
arity: uint
chunk: chunk::Chunk
name: value::String
}
off-topic but I got issue number 404 XD
Thus you also get the type information out of the box. Why write
if a.valueType() == .String && b.valueType() == .String { push(value::String(a) + value::String(b)) }
if you can write
if lhs, rhs := ^str(a), ^str(b); lhs != null && rhs != null { push(lhs^ + rhs^) }
?
what about the values that aren't base types, like
value::Nil
:type Nil* = struct {}
or, say, this
Function
type:type Function* = struct { arity: uint chunk: chunk::Chunk name: value::String }
nevermind, did not read this:
Everything on the stack, including functions and objects, can be Values.
let me try that and see if it works out
I, however, want to keep the print
and isFalsey
methods
what about the values that aren't base types, like value::Nil ... or, say, this Function type:
You can convert any type (not necessarily a basic type) to any
. So you can put your Function
into any
and then check if it's indeed your Function
:
val := any(Function{/*...*/})
//...
if f := ^Function(val); f != null {
call(f^)
}
As for Nil
, I don't know what is better: to use your own Nil
as you defined it, or just set any
to null
.
Anyway, I think you needn't reinvent RTTI.
off-topic but I got issue number 404 XD
Also noticed this :)
As for
Nil
, I don't know what is better: to use your ownNil
as you defined it, or just setany
tonull
.
wait, I could make Nil
a ^null
instead, can't I?
null
is a value, not a type. There is no name for the base type of the null
constant.
@vtereshkov thanks :D edit: the commit notice is there already lol
Great! By the way, you can join our community chat if you wish: https://discord.gg/PcT7cn59h9
ok, so I have this interface:
and at some point in the program, I have this call:
(yes, it's another Lox interpreter, but this one is public)
pop()
returnsValue
s, soa
andb
implementValue
, and equality checking in that case is fine, but now I want to add functions to the Lox interpreter, so I make a new interface that extendsValue
:and I make functions implement this interface.
now here's the thing: I want to use the
equals
method from theValue
interface forObject
s, i.e. I want to somehow downcast aValue
or a^Value
, to anObject
or an^Object
respectively. am I able to do this? if so, how? and if I can't, is there some other way I can achieve what I'm trying to do?