Skip to content

In assemblyscript,Is there a way to check the type of a value in wasm which has been loaded by assemblyscript, example:i32? #888

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

Closed
chooaya opened this issue Oct 6, 2019 · 23 comments

Comments

@chooaya
Copy link

chooaya commented Oct 6, 2019

image
-1
In the capture image,main.ts is a assemblyscript

assembly/main.ts (assemblyscript)

declare function sayHello(): void;

sayHello()

export function add(x: i32, y: i32): i32 {
  return x + y;
}

export function getTypeOf():string {
  let x:i32 = 12;
  return typeof x;
}
export function teste(): string {
  let x = "ZZZZZZZZZZZZ"
  return x;
}

but the code

export function getTypeOf():string {
  let x:i32 = 12;
  return typeof x;
}

src/main.js

(async()=>{
  let buffer = await fetch("../out/main.wasm");
  let arrayBuffer = await buffer.arrayBuffer();
  let lib = instantiateBuffer(arrayBuffer,{
    main: {
      sayHello() {
        console.log("Hello from WebAssembly!");
      }
    },
    env: {
      abort(_msg, _file, line, column) {
        console.error("abort called at main.ts:" + line + ":" + column);
      }
    },
  });
  document.getElementById("container").textContent = "Result: " + lib.add(19, 23) 
   + " Type:" + lib.__getString(lib.getTypeOf()) 
   + " teste:" + lib.__getString(lib.teste()) ;
})();

lib.getTypeOf() return a ptr of a string,so I use lib.__getString(ptr) to convert ptr to string.but a value is "number",not the "i32"

### Issue: The Expected value of This Function is "i32",but actuality the result is "number"

image
I added a assemblyscript loader by download from 「 https://raw.githubusercontent.com/AssemblyScript/assemblyscript/master/lib/loader/index.js 」,and rename the to loader.js and put the file to folder src.

### In assemblyscript,we have i32 A 32-bit signed integer,if we load this wasm ,so we can check the type of i32?If cannot check i32 by assemblyscript,is there another way to check the value of wasm ?
wasm-project201910070050.zip

PS:
This days ,I found the https://github.com/AssemblyScript/assemblyscript/tree/master/lib/parse
,but I don`t know the detail about the parse,is this parse can check type the type of i32?

@magic-akari

This comment has been minimized.

@chooaya
Copy link
Author

chooaya commented Oct 6, 2019

Check this out: microsoft/TypeScript#33290

Thank you.But my quesiton is about the i32 type in assemblyscript,is there a Connection between this issue and the microsoft/TypeScript#33290 ?

@MaxGraey
Copy link
Member

MaxGraey commented Oct 6, 2019

Javascript support only numbers (which 64-bit double floats by standard, internally browsers also support Smi but not in this case). All integers during pass from AssemblyScript to javascript and vise versa convert to numbers implicitly, so i32, u64, f32 and etc converts to number (f64) on javascript side.

@dcodeIO
Copy link
Member

dcodeIO commented Oct 6, 2019

typeof is more of a compatibility feature, but there's also nameof<T>() that can be used to obtain a more AssemblyScript-y name.

@chooaya
Copy link
Author

chooaya commented Oct 6, 2019

Javascript support only numbers (which 64-bit double floats by standard, internally browsers also support Smi but not in this case). All integers during pass from AssemblyScript to javascript and vise versa convert to numbers implicitly, so i32, u64, f32 and etc converts to number (f64) on javascript side.

assembly/main.ts is a assemblyscript,so In assemblyscript,i32,u64,f32 is different type,so If typeof can not be used for check the difference,difference check is necessary.

@chooaya
Copy link
Author

chooaya commented Oct 6, 2019

typeof is more of a compatibility feature, but there's also nameof<T>() that can be used to obtain a more AssemblyScript-y name.

Thank you. Would you like to share the link of the nameof() API?

@dcodeIO
Copy link
Member

dcodeIO commented Oct 6, 2019

Was missing in the docs, but added it here: https://docs.assemblyscript.org/basics/environment#utility

@chooaya
Copy link
Author

chooaya commented Oct 21, 2019

Thank you, Everyone, so is it a way to check the type of a value in wasm ?

@dcodeIO
Copy link
Member

dcodeIO commented Oct 21, 2019

If all you need is to evaluate differences between types, the recommended way to do so is to use builtins like isInteger<T>, isString<T> etc. (see). These differ from what is available in JS where everything is dynamic, in that these are compile-time static checks that the compiler can utilize to eliminate untaken branches (see).

@stale
Copy link

stale bot commented Nov 21, 2019

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale label Nov 21, 2019
@stale stale bot closed this as completed Nov 28, 2019
@mesozoic-technology
Copy link

So how does one call nameof? My program isn't compiling when I try to call it - nameoof<t>(whatIWantToFindTheNameOf)

the docs do not mention how to actually invoke it.

@jerrygreen
Copy link

jerrygreen commented Mar 31, 2021

I don’t see any useful usage in nameof but I would really like to use typeof. That’s unfortunate I can’t use such fundamental function as typeof. If it doesn’t require GC (it doesn’t seem to), then I’m not even sure why it’s still not there for all these past years

@dcodeIO
Copy link
Member

dcodeIO commented Mar 31, 2021

The JS typeof, or the TS type typeof?

@jerrygreen
Copy link

jerrygreen commented Mar 31, 2021

Uh, I actually though it doesn't have both of that, but since you're asking: yes, I mean the TS type of typeof... And honestly I wanted to use it for objects like this:

import Entity from '../engine/Entity'

const Position = { // used as type, and also as initial value
  x: 0,
  y: 0,
}

const Shape = 'box' // used as type, and also as initial value

const Velocity = { // used as type, and also as initial value
  x: 0,
  y: 0,
}

const Velocity = { // used as type, and also as initial value
  x: 0,
  y: 0,
}

const Primitive = { ...Position, ...Shape, ...Velocity } // poor man's composition, works quite well in js/ts

class SomeEntity extends Entity<typeof Primitive> {
  props = Primitive
  // ... the rest implementation ...
}

export default SomeEntity

But neither TS-typeof nor objects are supported in AssemblyScript, and I guess I'll be missing hints like this:

TS hints

I really wanted to make ECS implementation in AssemblyScript, but it seems it will be much much more inconvenient to use than I expected

And it doesn't seem I can type Map structure in a more detailed way other than Map<string, string>, like with objects where I can show which exact keys there might be

RIP AssemblyScript ECS implementation dream ☠️

For some pure mathematical functions it's still good, but it doesn't make much sense to write a whole game framework in it. That's unfortunate honestly, because in Rust there are many game frameworks appearing: https://arewegameyet.rs/ecosystem/engines/, so I felt it's a good idea to make it in AssemblyScript too. But seems I was mistaken and the expectations were too high. Sorry

@dcodeIO
Copy link
Member

dcodeIO commented Mar 31, 2021

I do think that being able to write a game framework in AS is a reasonable expectation. What is not, though, is that one can do that with poor man's composition or otherwise resorting to very dynamic JS features. In general, I find it valuable that you are sharing your experience as it indicates where the rough edges are that I, and others, should focus on improving, I am just not very happy with the way you express it.

@jerrygreen
Copy link

@dcodeIO yeah the last one's completely true, yet I just don't know how to express the other way than completely whining here and there, so I guess it's better so, than pure silence which isn't rude but completely unhelpful, and which is actively practiced pretty much everywhere

I might have an another attempt to implement ECS in AssemblyScript, and that you're thinking my expectation is indeed reasonable -> this helps a bit, so thx.

I named object destructuring "a poor man's composition" because of its simplicity but that doesn't mean it's a bad thing. I was able to achieve better results than what Mozilla team did with their ECSY framework with those objects, and I featured this in my article that I already shared somewhere, so you probably already seen it (just in case here's it again: Making Custom Game Engine)

I'll try to do this with Map structure probably, even though I'm loosing hope implementing it in AS 😂 because loosing all the conveniences of TS, hints and else

@MaxGraey
Copy link
Member

MaxGraey commented Mar 31, 2021

I recommend base your ECS AS implementation on some of C# or C++ ECS code. TypeScript don't actually remove "dynamicness" of JS. Also AS still lack of many things like spread operator and full implementation of interfaces and inline objects

@jerrygreen
Copy link

C# and C++ compiled to WASM, you mean? Therefore no any AssemblyScript? That’s not what I wanted... I wanted to implement it in AssemblyScript particularly, and be able to write my game logic in it (particularly Entities, Components, Systems, and maybe only the World would be written in TypeScript, - to orchestrate all of that).

And yeah, I know AS lacks many features (not just TS features but in overall many things aren’t there yet), but I kinda hoped it will be enough what it already has, and I actually expected objects to be part of its fundamental features, as long as TS-typeof, but if you say objects are too dynamic... Yeah, you’re probably right. Still hoped it can be solved somehow 😂 you know, people quite sometimes do what is seemingly impossible

@MaxGraey
Copy link
Member

MaxGraey commented Mar 31, 2021

C# and C++ compiled to WASM, you mean?

I mean port some ECS implementation / concept pattern from C# or C++ to AS instead try port TS/JS ECS to AS

@MaxGraey
Copy link
Member

Basically first ECS patterns were implemented on C# and C++

@jerrygreen
Copy link

@MaxGraey AssemblyScript tries to be similar to TypeScript, right? So why would I’d like to port C++ implementation into AssemblyScript, and not TypeScript implementation into AssemblyScript? Because C++ is less dynamic than TypeScript? Meh...

Thank you for the generating ideas, but I don’t like this idea

@trusktr
Copy link
Member

trusktr commented Aug 6, 2021

@jerrygreen In your example, the line

const Primitive = { ...Position, ...Shape, ...Velocity } // poor man's composition, works quite well in js/ts

does not sense. Did you mean something else?

You are trying to spread a string into an object, and two objects you're spreading have the same keys. The final object looks like the following and does not have all features you are trying to express:

const Primitive = {
  // each key of the string "box"
  0: 'b', 1: 'o', 2: 'x',
  // Only one x and one y (can't have both)
  x: 0, y: 0
}

In any case, making any algorithm or structure is doable in AS. If someone can make ECS in a pure functional language like Haskell, then they can do it in AS which has more than just functions!

In AS you just need to use classes and functions for now, and know that object literals are supported as long as they are casted from classes without constructors (maybe someone didn't mention this because they were offput by how you approached the conversation).

Here's your example with added types showing how it would work in AS, and it is not much more complicated (and I assume you want to keep intact all the features you had previously spread, and I'm following ES/JS/TS/AS variable naming conventions):

import Entity from '../engine/Entity'

class Vector2 {
  x: f32 // or do you want f64?
  y: f32
}

const position = {
  x: 0,
  y: 0,
} as Vector2

const shape: string = 'box'

const velocity = {
  x: 0,
  y: 0,
} as Vector2

class Primitive {
  position: Vector2
  shape: string
  velocity: Vector2
}

const primitive = {
  position: position,
  shape: shape,
  velocity: velocity,
} as Primitive

class SomeEntity extends Entity<Primitive> {
  props: Primitive = primitive
  // ...
}

export default SomeEntity

const entity = new SomeEntity()
entity.props.position.x // it works, intellisense in VS Code works, type checking works

And here's a shorter way to write it not using object literals:

import Entity from '../engine/Entity'

class Vector2 {
  x: f32 = 0
  y: f32 = 0
}

class Primitive {
  position: Vector2 = new Vector2()
  shape: string = "box"
  velocity: Vector2 = new Vector2()
}

class SomeEntity extends Entity<Primitive> {
  props: Primitive = new Primitive() // using a type here, as well as default values it comes with.
  // ...
}

export default SomeEntity

const entity = new SomeEntity()
entity.props.position.x // it works, intellisense in VS Code works, type checking works

That's a lot simpler (and better in my opinion).

AssemblyScript is pretty new, and will take time to gain more and more features like TS has, but it won't gain all of those features because it won't make sense for performance or the maintenance desires of the AssemblyScript team, and it won't align with the strict type system of WebAssembly (it would need to be implemented on top of WebAssembly types, and at that point you may as well be implementing a JavaScript engine, at which point you can just use the JS engine the browser gives you).

Object spread is not something undesirable though, just that someone has to add this feature. I think object spread makes perfect sense as long as the types are declared and things being spread match with what the type of the object receiving the spread has.

It will get there when it does. Someone recently made a pull request for array destructuring, for example.

At this point, if something isn't supported yet in AssemblyScript, then it's about seeing the future, and that future looks really good in AssemblyScript.

@jerrygreen
Copy link

jerrygreen commented Aug 6, 2021

You are trying to spread a string into an object,

I am not trying to spread any strings into an object.
What I do in this code:

const Primitive = { ...Position, ...Shape, ...Velocity }

Is spreading multiple objects into one. Position, Shape, Velocity, - they all have a few parameters and they set default values. For example:

const Position = { position: { x: 0, y: 0 } }
const Shape = { shape: "circle" }
const Velocity = { velocity: { x: 0, y: 0 } }

I described how I use that in my little article:

I had to rewrite whole ECS implementation in TypeScript of an existing library, which also used classes. But classes are slow and unnecessary to storing data. Also, it gets overly complicated when it gets to composing multiple classes into one. Classes are made for logic, for code. But Components in ECS model are just data, they shouldn't be classes. Maybe it's more doable with classes in AssemblyScript, since AS doesn't support object destructuring, but it's just wrong approach. You may read the article to get more details on that.

P.S. Well, if classes that consist of data worked as fast as objects, AND if they were as easily composabale as objects, - then well, I wouldn't be so much against classes for Components. But it's not the reality. So it's better to use each instrument for its purpose: classes for code/logic, objects for data.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants