visitUnaryExpr method
Implementation
@override
Object? visitUnaryExpr(UnaryExpr expr) {
final op = expr.prefix.type;
final rhs = expr.rhs.accept(this);
if (op == TokenType.kHash) {
if (rhs is LuaObject) {
final mm = rhs.readMetatable('__len')?.as<LuaObject>();
final v = rhs.value;
if (v is! String && mm != null) {
return callLuaFunction(mm, args: [rhs]);
}
if (v is String) {
return v.length;
}
if (rhs.isNotTable) {
throw 'Length operator # used on a value.';
}
return rhs.tableSize;
} else if (rhs == null) {
throw 'Length operator # used on nil value.';
}
// else ...
throw 'Length operator # used on type ${rhs.runtimeType}.';
} else if (op == TokenType.kBitNot) {
String type = rhs.runtimeType.toString();
Object? v = rhs;
if (rhs is LuaObject) {
type = rhs.luaTypeInfo;
if (rhs.isTable) {
final mm = rhs.readMetatable('__bnot')?.as<LuaObject>();
if (mm != null) {
return callLuaFunction(mm, args: [rhs]);
}
} else {
v = rhs.value;
}
}
// ... else
return switch (v) {
final num n => ~n.toInt(),
_ => throw 'Unsupported bitwise NOT on $type.',
};
} else if (op == TokenType.kSub) {
String type = rhs.runtimeType.toString();
Object? v = rhs;
if (rhs is LuaObject) {
type = rhs.luaTypeInfo;
if (rhs.isTable) {
final mm = rhs.readMetatable('__unm')?.as<LuaObject>();
if (mm != null) {
return callLuaFunction(mm, args: [rhs, rhs]);
}
} else {
v = rhs.value;
}
}
// ... else
return switch (v) {
final num n => -n,
_ => throw 'Unsupported negation on $type.',
};
}
throw 'Unsupported unary operator ${op.toString()}';
}