Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Interpreter called only when adding a contract #970

Open
1 task done
jeshecdom opened this issue Oct 17, 2024 · 5 comments
Open
1 task done

Interpreter called only when adding a contract #970

jeshecdom opened this issue Oct 17, 2024 · 5 comments
Assignees
Labels
bug Something isn't working or isn't right scope: const-eval The constant and partial evaluation optimization mechanisms
Milestone

Comments

@jeshecdom
Copy link
Contributor

Are you using the latest released (or pre-released, a.k.a. "next") version?

  • I'm using the latest Tact version

Tact source code

fun blowup(v: Int) {
    1 / v;
}

fun test() {
    blowup(0);   // Should produce a div by zero error when interpreter calls the function
}

Relevant Tact/build system log output

No response

What happened?

The interpreter is not activated. But, if we add a dummy contract, like so:

fun blowup(v: Int) {
   1 / v;       // A
}

fun test() {
   blowup(0); 
}

contract DummyContract {
}

The interpreter now produces the div by zero at line A.

What did you expect?

I expected a div by zero at compile-time.

Steps to reproduce

No response

How do you run Tact?

Tact CLI

Anything else?

No response

@jeshecdom jeshecdom added the bug Something isn't working or isn't right label Oct 17, 2024
@anton-trunov anton-trunov added this to the v1.6.0 milestone Oct 18, 2024
@anton-trunov anton-trunov added the scope: const-eval The constant and partial evaluation optimization mechanisms label Oct 18, 2024
@jeshecdom
Copy link
Contributor Author

This problem occurs because the interpreter is called when the writer is called. In turn, the writer is called only when there is a declared contract in the Tact file (see the for-statement at line 100 in file build.ts). In other words, if the Tact file does not have a declared contract, the code generation into FunC is not triggered.

I understand that a FunC file describes the behavior of a contract (it is basically a list of receiver functions together with auxiliary functions). Therefore, if there is no declared contract in a Tact file, there is no FunC program to generate.

But then, in a file like this,

fun blowup(v: Int) {
    1 / v;
}

fun test() {
    blowup(0);
}

what is point of running the typechecker if it is not going to be compiled into FunC anyway? Probably because there are Tact files that are essentially collections of functions that can be used in other Tact files?

In that case, I think that the interpreter should be called not when the writer is called, but immediately after the typechecker finishes. In other words, there must be a pass to simplify expressions before the FunC code generation phase.

What do you think of this?

@anton-trunov
Copy link
Member

I think that the interpreter should be called not when the writer is called, but immediately after the typechecker finishes

yes, this makes sense. btw, when you implement this, please add a CLI option to output the resulting simplified Tact contract (will be really useful for debugging)

@jeshecdom
Copy link
Contributor Author

@anton-trunov, I think I should already create the "optimization phase" in build.ts. Like this:

// Precompile
    try {
        ctx = precompile(ctx, project, stdlib, config.path);
    } catch (e) {
        logger.error(
            config.mode === "checkOnly" || config.mode === "funcOnly"
                ? "Syntax and type checking failed"
                : "Tact compilation failed",
        );
        logger.error(e as Error);
        return { ok: false, error: [e as Error] };
    }

    if (config.mode === "checkOnly") {
        logger.info("✔️ Syntax and type checking succeeded.");
        return { ok: true, error: [] };
    }

/*************************** ADD IT RIGHT HERE *************
   // Tact optimization phase
 ctx = optimize_tact_code(ctx, ..............)


    // Compile contracts
    let ok = true;
....... rest of the FunC code generation and compilation phase

Inside optimize_tact_code will be the expression simplification pass, and also the constant propagation analyzer, and we can add later further passes.

@jeshecdom
Copy link
Contributor Author

Note that this is only the high level optimization pass. Optimization phases for lower level code will need to be added after the FunC generation.

@anton-trunov
Copy link
Member

@jeshecdom sounds good

also, let's add the ability to opt-out of optimizations, for instance, in case there is a bug in the optimizer

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working or isn't right scope: const-eval The constant and partial evaluation optimization mechanisms
Projects
None yet
Development

No branches or pull requests

2 participants