jscl-project / jscl

A Lisp-to-JavaScript compiler bootstrapped from Common Lisp
https://jscl-project.github.io
GNU General Public License v3.0
885 stars 109 forks source link

Type checking #420

Open hemml opened 2 years ago

hemml commented 2 years ago

I'm trying to perform some computations on the browser-side, which is rather slow sometimes. I see in the JSCL-generated code a lot of type checking like this:

var x2=Math.sqrt(v25);
if (typeof x2!='number') throw 'Not a number!';

It seems strange, because Math.sqrt can return numbers only and, anyway, that checks are slowdowns the code. Is there a way to disable type checking in generated code?

nagy commented 2 years ago

I cannot answer the code-generation question, but according to MDN, Math.sqrt can return NaN sometimes:

Return value

The square root of the given number. If the number is negative, NaN is returned. 

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sqrt#return_value

davazp commented 2 years ago

There is no way to disable the checks right now. It could be nice to add support for (declare (optimize speed)) to disable those.

The compiler is rather naive and the type checks are everywhere. It also makes the output huge, because those are inlined. It'd be nice to wrap those type checks in JS functions in prelude, so (+ x y) would compile to just a function call with the typecheck in a single place.

Of course, it would be even better to do some basic analysis in the compiler and remove some unnecessary checks. I started a few attempts to add a smarter compiler, but never got enough time to finish it. But if anyone has time and some will, it is doable.

hemml commented 2 years ago

cannot answer the code-generation question, but according to MDN, Math.sqrt can return NaN sometimes:

Sure, but typeof NaN returns "number" anyway :)

vlad-km commented 2 years ago

There is no way to disable the checks right now. It could be nice to add support for (declare (optimize speed)) to disable those.

Maybe go this way:

Maybe it's easier than compiler redesign? Mmm?

davazp commented 2 years ago

I think the default should be to check the types always. But we can disable them kind of easily with a declaration without improving the compiler. Indeed if the user chooses safety 0, then they could add check-type.

vlad-km commented 2 years ago

I think the default should be to check the types always.

Definitely so. by default, type checking is always enabled.

Introduce the pragma disable-check-type directive.

  1. disables all checks at the top level l cl-user> (pragma :disable-check-type t)
  2. locally in the function, only for the function at compile time
         (pragma :disable-check-type t)
         (let ()))

    As an option.

vlad-km commented 2 years ago

safety 0

it should disable all checks: arrays, indices, strings, lists.