-
-
Notifications
You must be signed in to change notification settings - Fork 669
Transformer Class #866
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
Transformer Class #866
Conversation
Wdyt of making each transform function a method on a Transform class, and the class provides all the additional utility instead of providing arguments? For example class MyTransform extends Transform {
afterParse() {}
} which then has |
Sounds good to me. Was trying to be minimal, but I'll switch to that. |
Also add error handling for transformers
a4563b1
to
a5441c1
Compare
Previously I had tried to depend directly on the webpacked module, but then it becomes packaged with the transformer. So I tried importing the source files directly. Unfortunately this also means that every file gets packaged with it too. However, since the classes are already packaged or present with the compiler, then you only need the types document. Thus this is also the start of generating types for the AST that are separate from the compiler itself. One thing that I didn't do yet, but is something to consider is what the typescript compiler does, which is to "brand" interfaces. Which makes From their // Note: 'brands' in our syntax nodes serve to give us a small amount of nominal typing.
// Consider 'Expression'. Without the brand, 'Expression' is actually no different
// (structurally) than 'Node'. Because of this you can pass any Node to a function that
// takes an Expression without any error. By using the 'brands' we ensure that the type
// checker actually thinks you have something of the right type. Note: the brands are
// never actually given values. At runtime they have zero cost.
export interface Expression extends Node {
_expressionBrand: any;
}
//....
export interface UnaryExpression extends Expression {
_unaryExpressionBrand: any;
}
export interface UpdateExpression extends UnaryExpression {
_updateExpressionBrand: any;
}
// see: https://tc39.github.io/ecma262/#prod-UpdateExpression
// see: https://tc39.github.io/ecma262/#prod-UnaryExpression
export type PrefixUnaryOperator
= SyntaxKind.PlusPlusToken
| SyntaxKind.MinusMinusToken
| SyntaxKind.PlusToken
| SyntaxKind.MinusToken
| SyntaxKind.TildeToken
| SyntaxKind.ExclamationToken;
export interface PrefixUnaryExpression extends UpdateExpression {
kind: SyntaxKind.PrefixUnaryExpression;
operator: PrefixUnaryOperator;
operand: UnaryExpression;
} This is useful because you have type assertions in typescript rather than type casting. So when I say
type PrefixUnaryExpression = {
_expressionBrand: any;
_unaryExpressionBrand: any;
_updateExpressionBrand: any;
kind: SyntaxKind.PrefixUnaryExpression;
operator: PrefixUnaryOperator;
operand: UnaryExpression;
} I noticed this when I attempted to give the type of each Node, its NodeKind, but found there were instances where the node's parent had the NodeKind and the child couldn't overwrite the type. |
I feel like there's a tendency in your PRs to overstep the mark of what's necessary by a bit and I'd prefer if it remained simple. For instance, I imagine that having to keep another set of typings in sync with the compiler whenever something about the AST changes will result in all sorts of problems and unnecessary work. Ideally, there'd be typings for the transform one can optionally add by means of |
Lol that's why I started simple, but then with your suggestion I went for more because of my previous hardship with working with the types external from the compiler. As for your fear about changes with the AST, I think it's best to have a set of definitions that the compiler will conforms to and any external library will expect. This is also the result of me trying to understand the typescript's typings files and webpack. I attempted to have everything to be global definitions, but enums have to be imported and type files can either be completely ambient or export definitions. When I tried the last of what you mention I end up with two issues: one conflicting definitons of primitives in portable.d.ts and asssemblyscript.d.ts; and I still have to import from the bundle. /// <reference types="../../../dist/assemblyscript" />
export * from "assemblyscript"; compiles to "use strict";
/// <reference types="../../../dist/assemblyscript" />
function __export(m) {
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
}
Object.defineProperty(exports, "__esModule", { value: true });
__export(require("assemblyscript")); So although I just want the types, I still have to import the build js code. Which webpack really doesn't like. I'm new at this stuff and could use any help. |
value: function sincos(x) { | ||
this.sincos_sin = Math.sin(x); | ||
this.sincos_cos = Math.cos(x); | ||
try { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why you wrap this to try/catch?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah because since my code depends on portable too, it causes it to be redefined. I suppose I could change this to check if already define.
I wonder why we need |
It's all because of the pain I had trying to compile a transformer from typescript. Also I didn't add Again if you have a better way to compile this without what I've done, I'd much appreciate it. I tried to touch the current code as little as possible, but I wanted to try to make a tool that removed all the headaches involved with getting the types set up. |
/** | ||
* Example of using a transformer to print the AST for each entry file | ||
*/ | ||
export default class Printer extends Transformer { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
transform[name](...args); | ||
} else if (transform.default) { | ||
// Export default class which needs to be constructor | ||
if (!isConstructor(transform.default)){ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's works only for default
exports which could cause to problems
@@ -939,3 +965,7 @@ exports.tscOptions = { | |||
types: [], | |||
allowJs: false | |||
}; | |||
|
|||
function isConstructor(func) { | |||
return (func && typeof func === "function" && func.prototype && func.prototype.constructor) === func; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should be
function isConstructor(fn) {
return typeof fn === "function" && !!fn.prototype && fn.prototype.constructor === fn;
}
Just check:
assert.equal(isConstructor(undefined), false);
assert.equal(isConstructor(null), false);
Currently all this true
Made a little proof of concept here: cdb4dd6 |
In webpack you use "umd" and "source-map". In tsconfig "commonjs" and "inlineSourceMap". Did you try use |
I tried all sorts of combinations for tsc (I borrowed the webpack from the root one). Currently if I change module to "umd" in the config it doesn't understand the global definitions for |
I just wondering why you need portable.d.ts and |
@@ -0,0 +1,10 @@ | |||
{ | |||
"name": "near-bindgen", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"near-bindgen"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops! Yeah it was a test originally used there.
I thought the goal would be to eventually use assemblyscript itself. If we created a simple interface is assemblyscript, we could compile and load it. For example, we could create decorators written in assemblyscript that can use builtins. |
@willemneal I guess we could close this since all proposed features already in master? |
Also add error handling for transformers