question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Proposal: Comptime. Optimization hints for Preprocessors

See original GitHub issue

Suggestion

🔍 Search Terms

compiler preprocessor inline comptime

✅ Viability Checklist

My suggestion meets these guidelines:

  • This wouldn’t be a breaking change in existing TypeScript/JavaScript code
  • This wouldn’t change the runtime behavior of existing JavaScript code
  • This could be implemented without emitting different JS based on the types of the expressions
  • This isn’t a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
  • This feature would agree with the rest of TypeScript’s Design Goals.

⭐ Suggestion

Add syntax hints that preprocessor can use. Typescript should add this so developers would have a common interface to tell there toolchains (in this context: typescript aware preprocessors) which functions or expression can be evaluate at compile time. Preprocessor could then evaluate the runtime code and make it run at compiletime and serve its response static.

This Suggestion is not the first idea proposed here, but it tries to fix the problem the other ones had.

🚫 Non Goals

Typescript should not evaluate the code itself. (Which #26534 suffered from) Typescript should not throw any comptime errors

📃 Motivating Example

This Idea is nothing new. Zig is one of the biggest languages which have implemented this feature.

And comptime is a great feature for the web, as code size matters (like for loading speeds). Yet we want readable code, which often suffers from more code. more readable code.

https://kristoff.it/blog/what-is-zig-comptime/ https://ziglang.org/documentation/master/#comptime

💻 Use Cases

1. comptime for setting a variable

New Valid Syntax:

const compiledAt = comptime new Date().getTime()
// or
const compiledAt = new Date().getTime() as comptime

Compiles directly to:

const compiledAt = new Date().getTime()

A Typescript aware preprocessor would turn this into:

const compiledAt = 1652206435966
2. comptime getting used in a function

New Valid Syntax:

comptime async function readConfigFile() {
      const data = await Deno.readTextFile("config.json");
      return JSON.parse(data);
}

console.log((await readConfigFile()).version)

Compiles directly to:

async function readConfigFile() {
      const data = await Deno.readTextFile("config.json");
      return JSON.parse(data);
}

console.log((await readConfigFile()).version)

A Typescript aware preprocessor would turn this into:

console.log("1.0.0-beta.1");
3. comptime validation depending on function paramets

New Valid Syntax:

// "comptime id" declares that this parameter needs to be known at compile time (aka preprocessor time)
function registerView(comptime id: string) {
      comptime: {
             if (!id.includes("-"))
                    throw new Error("Invalid ID");
             if (id.toUpperCase() != id)
                    throw new Error("Invalid ID");
      }
      // Normal code goes here [ ... ]
}

registerView("Hey-100") // Valid for Typescript
registerView("HEY-100") // Valid for Typescript

Compiles directly to:

function registerView(id) {
      comptime: {  // A "Label" is a valid javascript syntax
             if (!id.includes("-"))
                    throw new Error("Invalid ID");
             if (id.toUpperCase() != id)
                    throw new Error("Invalid ID");
      }
      // Normal code goes here [ ... ]
}

registerView("Hey-100") // Valid for Javascript, Throws a runtime error (which could lead to a unknown bug)
registerView("HEY-100") // Valid for Javascript

A Typescript aware preprocessor would turn this into:

function registerView(id: string) {
      // Normal code goes here [ ... ]
}

registerView("Hey-100") // Invalid for the Preprocessor, Throws a compiletime error (which would identify the bug directly)
registerView("HEY-100") // Valid for the Preprocessor

Issue Analytics

  • State:open
  • Created a year ago
  • Comments:6 (3 by maintainers)

github_iconTop GitHub Comments

2reactions
RyanCavanaughcommented, May 11, 2022

This doesn’t really fit into our design parameters. There are a huge number of questions that would need to be answered here to make this work in the context of a type system, like what happens when you indirect one of these expressions, what the lexical environment is when these functions are evaluated, and so on.

If I had a program that really needed this, I’d write a pass-through precompile<T>(x: T): T function, then whatever build tool that’s evaluating these could look for calls to that function and do “the right thing”, whatever that is. You could even make functions that could only be precompiled by writing something like

// Write once
type Precompiled<T> = { value_do_not_access: T };
function precompile<T>(value: Precompiled<T>): T { return value.value_do_not_access; };
function makePrecompiled<T>(value: T): Precompiled<T> {
  return { value_do_not_access: value };
}

// Use elsewhere
function getVersion(): Precompiled<string> {
  return makePrecompiled("3.1.4.1");
}

const s: string = precompile(getVersion());

This makes the semantics of this extremely clear, which I would think is very important to avoid surprises since writing JS that looks like JS but does something non-JSy is bad.

0reactions
MartinJohnscommented, May 11, 2022

Typescript does this so often. specifically like adding import type just so preprocessor can better understand what the data flow is.

But import type is not an expression-level syntax. Goal 8 states avoiding to add new expression-level syntax, so checking that point in the viability checklist is wrong.

Just look at linters there is eslint-disable-next-line prettier-ignore tslint:disable-next-line and so much more, just for doing the same concept.

Shows that the concept works just fine. 😃

IMO adding a new keyword to the TypeScript language that third-party tools may use is the wrong approach and will just lead to confusion when users expect it to do something.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Constant / compile-time-only functions · Issue #26534 - GitHub
This proposal does depend on the type of function ( compiler function or normal function ), no?
Read more >
Optimizing preprocessors for FORTRAN and C - IBM
The preprocessors perform memory management optimizations, algebraic transformations, inlining, interprocedural analysis, and other optimizations that improve ...
Read more >
Optimization Modes and Hints - Oracle Help Center
Optimization Modes and Hints. This chapter explains when to use the available optimization modes and how to use hints to enhance Oracle performance....
Read more >
Zig Language Reference
Introduction §. Zig is a general-purpose programming language and toolchain for maintaining robust, optimal, and reusable software.
Read more >
Specify Optimization Hints in Queries
By default, the InterSystems SQL query optimizer uses sophisticated and ... SQL provides hints that can be used to manually modify the execution...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found