jamesjuett / lobster

Interactive Program Visualization Tools
8 stars 3 forks source link

Weird error message for uncalled function #288

Closed jamesjuett closed 2 years ago

jamesjuett commented 2 years ago

This gives a declaration.init.convert error, which is a bit weird.

#include <iostream>

using namespace std;

void foo() {
}
int main() {
  cout << "Hello World!" << endl;

  int x = foo;
}
iteemhe commented 2 years ago

I found another weird issue. This will report declaration.init.convert: Invalid conversion from int () to int., but should be size_t ().

#include <iostream>

using namespace std;

size_t foo() {
    return 1;
}

int main() {
    int x = foo;
}

I think the issue I mentioned above is caused by this chunk of code in types.ts, at the end of the file.

export const builtInTypes = {
    char: Char,
    int: Int,
    size_t: Int, //! Should be Size_t?
    bool: Bool,
    float: Float,
    double: Double,
    void: VoidType,
};
iteemhe commented 2 years ago

I found another weird issue. This will report declaration.init.convert: Invalid conversion from int () to int., but should be size_t ().

#include <iostream>

using namespace std;

size_t foo() {
    return 1;
}

int main() {
    int x = foo;
}

I think the issue I mentioned above is caused by this chunk of code in types.ts, at the end of the file.

export const builtInTypes = {
    char: Char,
    int: Int,
    size_t: Int, //! Should be Size_t?
    bool: Bool,
    float: Float,
    double: Double,
    void: VoidType,
};

Issue solved by changing size_t: Int to size_t: Size_t.

Screen Shot 2022-02-21 at 08 08 52

jamesjuett commented 2 years ago

The original error is due to the uncalled function. For the size_t/int difference - in Lobster (for now at least), size_t is simply an alias for int. Lobster doesn't actually support unsigned integers. size_t will have some weird behaviors (e.g. holding negative numbers!), but this was a quick hack so that if students paste in code with size_t (and assume the code doesn't have wrapound) it will be functional.

iteemhe commented 2 years ago

I was able to identify the original issue. The issue is typeString function in class VoidType.

Screen Shot 2022-02-21 at 08 52 44

When the errors.init.convert ask for the type of initType, it will call the toString method, which calls typeString method in VoidType. This call will pass the parameter types of the function pointer to typeString method, as shown in the debugger, () means a function pointer takes 0 parameters.

However, the typeString method in VoidType will return "void" regardless of the varname parameter passed in.

For other types inherit from SimpleType, its typeString method considers varname.

   public typeString(
        excludeBase: boolean,
        varname: string,
        decorated: boolean
    ): string {
        if (excludeBase) {
            return varname ? varname : "";
        } else {
            let typeStr = this.getCVString() + this.simpleType;
            return (
                (decorated ? htmlDecoratedType(typeStr) : typeStr) +
                (varname ? " " + varname : "")
            );
        }
    }

The solution is very simple. return "void" + varname. The issue can be addressed by this fix, but I do not know if it will cause any side effect.

Screen Shot 2022-02-21 at 08 59 10

jamesjuett commented 2 years ago

Ah, good find!

It's recursively called from here in the FunctionType class in the original example.

    public typeString(excludeBase: boolean, varname: string, decorated: boolean = false) {
        return this.returnType.typeString(excludeBase, varname + this.paramStrType, decorated);
    }

And when this.returnType is a VoidType, it isn't properly paying attention to all the parameters passed along.

jamesjuett commented 2 years ago

Fixed in #295! Thanks @iteemhe!