Remove str-nonstr concatenation / implicit coercion

This commit is contained in:
K. Lange 2021-02-14 08:25:53 +09:00
parent a7e110cad9
commit e0adfcdc80
5 changed files with 23 additions and 42 deletions

View File

@ -1865,10 +1865,10 @@ static void string(int type) {
krk_rewindScanner(beforeExpression); /* To get us back to where we were with a string token */
parser = parserBefore;
c = inner.start;
KrkToken which = syntheticToken("str");
if (*c == '!') {
c++;
/* Conversion specifiers, must only be one */
KrkToken which;
if (*c == 'r') {
which = syntheticToken("repr");
} else if (*c == 's') {
@ -1877,12 +1877,12 @@ static void string(int type) {
error("Unsupported conversion flag for f-string expression");
goto _cleanupError;
}
size_t ind = identifierConstant(&which);
EMIT_CONSTANT_OP(OP_GET_GLOBAL, ind);
emitByte(OP_SWAP);
emitBytes(OP_CALL, 1);
c++;
}
size_t ind = identifierConstant(&which);
EMIT_CONSTANT_OP(OP_GET_GLOBAL, ind);
emitByte(OP_SWAP);
emitBytes(OP_CALL, 1);
if (*c == ':') {
/* TODO format specs */
error("Format spec not supported in f-string");

View File

@ -38,6 +38,7 @@ KRK_METHOD(str,__init__,{
KRK_METHOD(str,__add__,{
METHOD_TAKES_EXACTLY(1);
CHECK_ARG(1,str,KrkString*,them);
const char * a;
const char * b;
size_t al;
@ -47,24 +48,8 @@ KRK_METHOD(str,__add__,{
a = AS_CSTRING(argv[0]);
al = self->length;
if (!IS_STRING(argv[1])) {
KrkClass * type = krk_getType(argv[1]);
if (type->_tostr) {
krk_push(argv[1]);
KrkValue result = krk_callSimple(OBJECT_VAL(type->_tostr), 1, 0);
krk_push(result);
needsPop = 1;
if (!IS_STRING(result)) return krk_runtimeError(vm.exceptions->typeError, "__str__ produced something that was not a string: '%s'", krk_typeName(result));
b = AS_CSTRING(result);
bl = AS_STRING(result)->length;
} else {
b = krk_typeName(argv[1]);
bl = strlen(b);
}
} else {
b = AS_CSTRING(argv[1]);
bl = AS_STRING(argv[1])->length;
}
b = AS_CSTRING(argv[1]);
bl = them->length;
size_t length = al + bl;
char * chars = ALLOCATE(char, length + 1);

View File

@ -1814,11 +1814,8 @@ static KrkValue run() {
break;
}
case OP_LESS: BINARY_OP(lt);
case OP_GREATER: BINARY_OP(gt)
case OP_ADD:
if (IS_STRING(krk_peek(1))) krk_addObjects(); /* Shortcut for strings */
else BINARY_OP(add)
break;
case OP_GREATER: BINARY_OP(gt);
case OP_ADD: BINARY_OP(add);
case OP_SUBTRACT: BINARY_OP(sub)
case OP_MULTIPLY: BINARY_OP(mul)
case OP_DIVIDE: BINARY_OP_CHECK_ZERO(div)

View File

@ -13,9 +13,8 @@ if False:
print("This is the first line that should print.")
# Concatenation currently requires the first argument be a string.
# Other values then get converted to strings as you go.
print("We can do simple concatenation " + 123 + ".")
# Only str can be concatenated with str
print("We can do simple concatenation " + str(123) + ".")
# Lox only has a 'Number' type for numerical values, but we have
# Integer and Floating to separate the two.
@ -23,13 +22,13 @@ print(4.2 * 9.7) # Should be 40.74
print(1 + 2 + 3)
# Other bases:
print("Hex: " + 0xFF + " Octal: " + 0o123 + " Binary: " + 0b1010)
print("Hex:", 0xFF, "Octal:", 0o123, "Binary:", 0b1010)
# This `for init, cond, step:` syntax is possibly temporary? I do intend to
# implement iterators and `for VAR in ITER:` like in Python, but C-style for
# loops are also useful...
for i = 0; i < 10; i = i + 1:
print("i = " + i)
print("i =", i)
# Functions work like in Python, though currently no default values.
def function(arg): # And of course the parser will handle comments here...
@ -49,7 +48,7 @@ print("This code is after the function definition")
# now we're following traditional scoping rules, and a simple `let foo` at
# the head of the appropriate block should work okay.
let result = function("demo")
print("The function call returned: " + result)
print("The function call returned:", result)
# `sleep()` is a native function bind. Lox has `clock` as an example, but I
# figured something with arguments would be more useful? The purpose of this
@ -57,7 +56,7 @@ print("The function call returned: " + result)
# plugins for bim, so native bindings are going to be very important.
result = time.sleep(0.1)
print("Call to sleep returned: " + result)
print("Call to sleep returned:", result)
function("something else")
@ -125,9 +124,9 @@ class SuperClass():
def __str__(self):
return "(I am a " + self.a + ")"
def __get__(self, ind):
return "(get[" + ind + "])"
return "(get[" + str(ind) + "])"
def __set__(self, ind, val):
print("(set[" + ind + "] = " + val + ")")
print("(set[" + str(ind) + "] = " + val + ")")
class SubClass(SuperClass):
def __init__(self):
@ -145,7 +144,7 @@ subclass.aMethod()
#def notAMethoDeither(self):
# print(self)
print("Subclass says: " + subclass)
print("Subclass says:", subclass)
subclass.__get__(123)
print(subclass[123])
@ -158,13 +157,13 @@ print(hash["hello"])
print("Let's make some lists:")
let l = list()
print("Length before: " + len(l))
print("Length before:", len(l))
l.append(1)
l.append(2)
l.append(3)
print("Length after: " + len(l))
print("Length after:", len(l))
for j = 0; j < len(l); j = j + 1:
print("j=" + j + ", list[j]=" + l[j])
print("j=" + str(j) + ", list[j]=" + str(l[j]))
print("Can we call properties of strings?".__len__()) # Of course we can.

View File

@ -9,4 +9,4 @@ for v in h.keys():
print(v)
for v in h.keys():
print("" + v + ": " + h[v])
print(str(v) + ": " + str(h[v]))