untoldwind / KontrolSystem2

Autopilot scripting system for KSP2
Other
54 stars 14 forks source link

Compilation fails with an `unknown error` message #119

Closed lefouvert closed 1 month ago

lefouvert commented 5 months ago

version 0.5.2.5 (Ckan)

Hi, I made a mistake and wrote wrong code (how surprizing ! ;D) The compiler obviously rage quit. However, the message is intriguing (surely, the linker get less token than expected).

Here the code : gitreport::compilfail::ship::constant.to2

pub type ThrustSituationConst = int

pub const ThrustSituation: (Current: ThrustSituationConst, CurrentAsOn: ThrustSituationConst, Max_Vac: ThrustSituationConst, Max_Atm: ThrustSituationConst, Min: ThrustSituationConst) = (
    Current: 0,
    CurrentAsOn: 1,
    Max_Vac: 2,
    Max_Atm: 3,
    Min: 4
)

gitreport::compilfail::ship::stage.to2

use { Vessel, Part } from ksp::vessel
use { ThrustSituation, ThrustSituationConst } from gitreport::compilfail::ship::constant

pub struct Stage(vessel : Vessel, stage: int) { }
impl Stage {
    fn thrust(self, context: ThrustSituationConst = ThrustSituation.Current) -> float = { return 54.8493 }
}

gitreport::compilfail::console::missingimport.to2

use { CONSOLE } from ksp::console
use { Vessel } from ksp::vessel

use { Stage } from gitreport::compilfail::ship::stage
// use { ThrustSituation } from gitreport::compilfail::ship::constant

pub fn engineering_debug(vessel : Vessel) -> Unit = {
    CONSOLE.print_line("stage thrust param      : " + engineeringScalar(Stage(vessel, 3).thrust(ThrustSituation.Max_Atm), 3) + "N")
}

pub fn engineeringScalar(value: float, significantDigit: int = 3) -> string = { return "whatever" }

Note than missingimport.to2 isn't in the same folder than the other two. Here the error message :

Rebooted in 00:00:03.0494319 ERROR: [(0, 0)] Unknown error Negative stack count at stloc.0 offset 6

while I usually get a nice "InvalidType Unable to lookup type Blablablaaa" or something similar.

The obvious solution is to not write wrong code (and uncomment the import in gitreport::compilfail::console::missingimport.to2 will fix that error), but I feel the nice message is also expected in the situation I've just describe.

Edit : typo

untoldwind commented 5 months ago

Should be fix in 0.5.2.6

lefouvert commented 5 months ago

version 0.5.2.6 (Ckan)

Hi !

Here is another one : gitreport::recordovertyping.to2

use { MAINFRAME } from ksp::game

fn foo() -> Unit = {
    const bar = MAINFRAME.available_processes
        .map(fn(process) -> (name: string = process.name))
    // const bar = MAINFRAME.available_processes
    //     .map(fn(process) -> (name: process.name)) // correct way to write it
}

leads to

Rebooted in 00:00:02.8792689 ERROR: [(0, 0)] Unknown error Negative stack count at stfld offset 9

The mistake here is to define type of the record entry where it is already typed by the value inserted. The commented part is the correct way to write it.

However, the compiler have is very own way to says it :)


Edit : add a case where the compiler is lost

Here's an other one ;) _gitreport::returnmain.to2

use { Ship } from ship::ship

/// Entry Point
pub fn main_flight(vessel: Vessel) -> Result<Unit, string> = {
    if(false)
        return Err("Vessel unable to carry out its mission \r\n")
    // return Ok({})
}

Rebooted in 00:00:03.4492601 ERROR: [(0, 0)] Unknown error Negative stack count at stfld offset 51

Corrected by uncomment the return Ok({}) line.

Is assume it eventualy spit an Option<Result<??>> without the return Ok({}) explicitly written.

untoldwind commented 4 months ago

Type annotations in "anoymous" records are not supported (yet?). So (name: string = process.name) Is actually interpreted as: name is the result of string = process.name, i.e. the assignment of a local-variable string to process.name. So the error should be "There is no variable string". Should be fixed in the next patch.

As for this if-case: That was a bug, internally the return was no able to cleanup the stack correctly.

lefouvert commented 4 months ago

version 0.5.2.6 (Ckan)

Hi ! I get a frustrating one. (Record still involved, but since it's not an anonymous one, I was hoping...)

Let's say I have 3 files : _gitreport::compilfail0::ship::ship.to2

use { ThrustSituation, ThrustSituationConst } from _gitreport::compilfail0::ship::constant

pub struct Ship(){}

impl Ship {
    fn thrust(self, context: ThrustSituationConst = ThrustSituation.Max_Vac) -> float = 0.0
}

_gitreport::compilfail0::ship::constant.to2

pub type ThrustSituationConst = int
pub const ThrustSituation: (Max_Vac: ThrustSituationConst, Max_Atm: ThrustSituationConst) = (
    Max_Vac: 2**0,
    Max_Atm: 2**1
)

_gitreport::compilfail0::ui::monitor.to2

use { yield } from ksp::game
use { Ship } from _gitreport::compilfail0::ship::ship

pub fn main_flight() -> Result<Unit, string> = {
    monitor(Ship())
}

pub fn monitor(ship: Ship) -> bool = {
    const toto = ship.thrust() // to gitreport
    return true
}

I get this error message :

Rebooted in 00:00:03.5567209 ERROR: [(0, 0)] Unknown error Unable to change after type has been created.

If I comment the const toto = ship.thrust(), everything is fine.

Rebooted in 00:00:03.5468515 No errors

With other methods without default value, it work fines. But I suspect just it's not defaults values, but defaults values in Records which are faulty.

untoldwind commented 4 months ago

Quick analysis: The problem is the default-value for the context parameter:

fn thrust(self, context: ThrustSituationConst = ThrustSituation.Max_Vac) -> float = 0.0

workaround would be to change it to

fn thrust(self, context: ThrustSituationConst) -> float = 0.0

Under the hood it is again a nasty hen-egg problem I am still wrapping my head around

lefouvert commented 4 months ago

Looks like I like chickens a little too much ;) Ok, so this isn't the record, but the default. I'll try to be less prolific with these :)

untoldwind commented 4 months ago

It should work now in the 0.5.2.7 release

lefouvert commented 4 months ago

version 0.5.2.7 (Ckan) Hi !

Pokémon 'Gotta catch 'em all !'

Thanks to a misstyping, got this one :

_gitreport::compilfail.to2

// ko v0.5.2.7 issue #119
// ok v

use { Vessel } from ksp::vessel
use { current_time } from ksp::game
use { Direction } from ksp::math

pub struct Foobar(vessel: Vessel) {
    normal: fn() -> Direction = fn() -> vessel.orbit.normal_plus(current_time).to_direction()
    // normal: fn() -> Direction = fn() -> vessel.orbit.normal_plus(current_time()).to_direction()
    radial: fn() -> Direction = fn() -> vessel.orbit.radial_plus(current_time()).to_direction()
    antiradial: fn() -> Direction = fn() -> (-vessel.orbit.radial_plus(current_time())).to_direction()
}

Which gives us a nice

Rebooted in 00:00:03.1016991 ERROR: [(0, 0)] Unknown error Negative stack count at stfld offset 42

Obvioulsy, the correct way to not get an error is the commented one.

Have a nice day !

lefouvert commented 4 months ago

version 0.5.2.8 (Ckan) version 0.5.3.0 (git)

Hi !

Got this one : gitreport::compilfail0.to2

// ko v0.5.2.8 issue #119
// ok 

use { Vessel } from ksp::vessel
use { Body } from ksp::orbit

pub type ApsisConst = int

pub const Apsis: (Periapsis: ApsisConst, Apoapsis: ApsisConst) = (
    Periapsis: 0,
    Apoapsis: 1
)

pub type ApsisModificationConst = float

pub const ApsisModification: (Raise: ApsisModificationConst, Decrease: ApsisModificationConst, Cheaper: ApsisModificationConst) = (
    Raise: 0,
    Decrease: 180,
    Cheaper: -360
)

sync fn atmosphere_depth(body: Body) -> float = {
    return if(body.has_atmosphere) body.atmosphere_depth else 0.0
}

pub fn circularize(vessel: Vessel, way: ApsisModificationConst = ApsisModification.Cheaper) -> Result<Unit, string> = {
    const body = vessel.main_body

    if(vessel.orbit.periapsis < atmosphere_depth(body) && (!vessel.orbit.apoapsis.defined))
        return Err("Unable to circularize " + vessel.name)
    if(vessel.orbit.periapsis < atmosphere_depth(body) && way == ApsisModification.Decrease)
        return Err("Unable to circularize " + vessel.name + " at " + vessel.orbit.periapsis.to_fixed(0) + " because it's below " + vessel.main_body.name + "'s atmosphere.")
    if((!vessel.orbit.apoapsis.defined) && way == ApsisModification.Raise)
        return Err("Unable to circularize " + vessel.name + " at apoapsis because of hyperbolic orbit (escape " + vessel.main_body.name + "'s sphere of influence)")

    if(way == ApsisModification.Raise) {
        return foobar(vessel, Apsis.Periapsis, vessel.orbit.apoapsis.value)
    } else if(way == ApsisModification.Decrease) {
        return foobar(vessel, Apsis.Apoapsis, vessel.orbit.periapsis)
    }
    else {
        return Ok({}) // TODO
    }
}

fn foobar(vessel: Vessel, apsis: ApsisConst, altitude:float) -> Result<Unit, string> = {
    //things
    return Ok({})
}

which gives us a nice

Rebooted in 00:00:12.0270033 ERROR: [(0, 0)] Unknown error Negative stack count at stloc.s offset 114

However, this

pub fn circularize(vessel: Vessel, way: ApsisModificationConst = ApsisModification.Cheaper) -> Result<Unit, string> = {
    const body = vessel.main_body

    if(vessel.orbit.periapsis < atmosphere_depth(body) && (!vessel.orbit.apoapsis.defined))
        return Err("Unable to circularize " + vessel.name)
    if(vessel.orbit.periapsis < atmosphere_depth(body) && way == ApsisModification.Decrease)
        return Err("Unable to circularize " + vessel.name + " at " + vessel.orbit.periapsis.to_fixed(0) + " because it's below " + vessel.main_body.name + "'s atmosphere.")
    if((!vessel.orbit.apoapsis.defined) && way == ApsisModification.Raise)
        return Err("Unable to circularize " + vessel.name + " at apoapsis because of hyperbolic orbit (escape " + vessel.main_body.name + "'s sphere of influence)")

    if(way == ApsisModification.Raise)
        return foobar(vessel, Apsis.Periapsis, vessel.orbit.apoapsis.value)
}

is perfectly fine :

Rebooted in 00:00:12.1498958 No errors

I should admit I'm pettry lost with this one.

Edit : updated to the 0.5.3.0 Prerelease

untoldwind commented 4 months ago

The compiler struggles to detect that the function ends after an

if(conditsion) return something else return somethingelse

So instead of:

    if(way == ApsisModification.Raise) {
        return foobar(vessel, Apsis.Periapsis, vessel.orbit.apoapsis.value)
    } else if(way == ApsisModification.Decrease) {
        return foobar(vessel, Apsis.Apoapsis, vessel.orbit.periapsis)
    }
    else {
        return Ok({}) // TODO
    }

This should work:

    if(way == ApsisModification.Raise) {
        return foobar(vessel, Apsis.Periapsis, vessel.orbit.apoapsis.value)
    } else if(way == ApsisModification.Decrease) {
        return foobar(vessel, Apsis.Apoapsis, vessel.orbit.periapsis)
    }
    return Ok({}) // TODO

or this:

return if(way == ApsisModification.Raise) {
        foobar(vessel, Apsis.Periapsis, vessel.orbit.apoapsis.value)
    } else if(way == ApsisModification.Decrease) {
        foobar(vessel, Apsis.Apoapsis, vessel.orbit.periapsis)
    }
    else {
        Ok({}) // TODO
    }
lefouvert commented 4 months ago

Uh, Yes, now you mention it, I had catch numerous times where the compiler struggle with if/else form. Often, I had to transform some

fn even(a: float) -> bool = {
    if(a%2 == 0)
        return true
    else
        return false
}

in

fn even(a: float) -> bool = {
    if(a%2 == 0)
        return true
    return false
}

because of some kind of

Error: blabla even function should return bool type but Unit was found

But as the message was clear and the correction was so easy I didn't really pay attention. Here I have been fooled by the fact the else part is in reality way bigger than the issue report, and the less informative compiler error message than usual (and perhaps tiredness)

untoldwind commented 4 months ago
fn even(a: float) -> bool = {
    if(a%2 == 0)
        return true
    else
        return false
}

and the original if-case in circularize should now work in 0.5.3.1

github-actions[bot] commented 2 months ago

This issue is stale because it has been open for 60 days with no activity.

github-actions[bot] commented 1 month ago

This issue was closed because it has been inactive for 14 days since being marked as stale.