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

ABI 0.2 (part 1/2) #3

Open
wants to merge 21 commits into
base: wrap-0.2-dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
313 changes: 313 additions & 0 deletions abi/0.2.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,313 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"AnyType": {
"anyOf": [
{
"$ref": "#/definitions/ScalarType"
},
{
"$ref": "#/definitions/ArrayType"
},
{
"$ref": "#/definitions/MapType"
},
{
"$ref": "#/definitions/RefType"
},
{
"$ref": "#/definitions/ImportRefType"
}
]
},
"ArgumentDef": {
"properties": {
"kind": {
"enum": [
"Argument"
],
"type": "string"
},
"name": {
"type": "string"
},
"required": {
"type": "boolean"
},
"type": {
"$ref": "#/definitions/AnyType"
}
},
"type": "object"
},
"ArrayType": {
"properties": {
"item": {
"$ref": "#/definitions/OptionalType"
},
"kind": {
"enum": [
"Array"
],
"type": "string"
}
},
"type": "object"
},
"EnumDef": {
"properties": {
"constants": {
"items": {
"type": "string"
},
"type": "array"
},
"kind": {
"enum": [
"Enum"
],
"type": "string"
},
"name": {
"type": "string"
}
},
"type": "object"
},
"FunctionDef": {
"properties": {
"args": {
"items": {
"$ref": "#/definitions/ArgumentDef"
},
"type": "array"
},
"kind": {
"enum": [
"Function"
],
"type": "string"
},
"name": {
"type": "string"
},
"result": {
"$ref": "#/definitions/ResultDef"
}
},
"type": "object"
},
"ImportRefType": {
"properties": {
"import_id": {
"type": "string"
},
"kind": {
"enum": [
"ImportRef"
],
"type": "string"
},
"ref_kind": {
"$ref": "#/definitions/UniqueDefKind"
},
"ref_name": {
"type": "string"
}
},
"type": "object"
},
"MapType": {
"properties": {
"key": {
"$ref": "#/definitions/MapKeyScalarType"
},
"kind": {
"enum": [
"Map"
],
"type": "string"
},
"value": {
"$ref": "#/definitions/OptionalType"
}
},
"type": "object"
},
"ObjectDef": {
"properties": {
"kind": {
"enum": [
"Object"
],
"type": "string"
},
"name": {
"type": "string"
},
"props": {
"items": {
"$ref": "#/definitions/PropertyDef"
},
"type": "array"
}
},
"type": "object"
},
"OptionalType": {
"properties": {
"required": {
"type": "boolean"
},
"type": {
"$ref": "#/definitions/AnyType"
}
},
"type": "object"
},
"PropertyDef": {
"properties": {
"kind": {
"enum": [
"Property"
],
"type": "string"
},
"name": {
"type": "string"
},
"required": {
"type": "boolean"
},
"type": {
"$ref": "#/definitions/AnyType"
}
},
"type": "object"
},
"RefType": {
"properties": {
"kind": {
"enum": [
"Ref"
],
"type": "string"
},
"ref_kind": {
"$ref": "#/definitions/UniqueDefKind"
},
"ref_name": {
"type": "string"
}
},
"type": "object"
},
"ResultDef": {
"properties": {
"kind": {
"enum": [
"Result"
],
"type": "string"
},
"required": {
"type": "boolean"
},
"type": {
"$ref": "#/definitions/AnyType"
}
},
"type": "object"
},
"ScalarTypeEnum": {
"enum": [
"BigInt",
dOrgJelli marked this conversation as resolved.
Show resolved Hide resolved
"BigNumber",
"Boolean",
"Bytes",
"Int",
"Int16",
"Int32",
"Int8",
"JSON",
"String",
"UInt",
"UInt16",
"UInt32",
"UInt8"
],
"type": "string"
},
"ScalarTypeMapKeyEnum": {
"enum": [
"Int",
"Int16",
"Int32",
"Int8",
"String",
"UInt",
"UInt16",
"UInt32",
"UInt8"
],
"type": "string"
},
"MapKeyScalarType": {
"properties": {
"kind": {
"enum": [
"Scalar"
],
"type": "string"
},
"scalar": {
"$ref": "#/definitions/ScalarTypeMapKeyEnum"
}
},
"type": "object"
},
"ScalarType": {
"properties": {
"kind": {
"enum": [
"Scalar"
],
"type": "string"
},
"scalar": {
"$ref": "#/definitions/ScalarTypeEnum"
}
},
"type": "object"
},
"UniqueDefKind": {
"enum": [
"Enum",
"Function",
"Object"
],
"type": "string"
}
},
"properties": {
"enums": {
"items": {
"$ref": "#/definitions/EnumDef"
},
"type": "array"
},
"functions": {
"items": {
"$ref": "#/definitions/FunctionDef"
},
"type": "array"
},
"objects": {
"items": {
"$ref": "#/definitions/ObjectDef"
},
"type": "array"
}
},
"type": "object"
}
29 changes: 29 additions & 0 deletions abi/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# WRAP ABI (v0.2)
## Goals
- **Optimized:** The size and performance of the ABI should be optimized.
- **Functional:** The composition & usage of this ABI should be highly functional. It should not require expensive parsing / transformation.
- **Stable:** The ABI should be resistent to potential future changes, helping it remain stable and easily upgradeable.

## Improvements Upon 0.1
- **Smaller:** 0.2 is much smaller than 0.1, as we have removed a significant amount of redundant information from the ABI.
- **Easier To Parse:** 0.2's structured layout is easier to parse than 0.1, as well as it includes a few properties that help solve ambiguity, which required reparsing to solve.
- **Clearer Semantics:** In 0.2 we're proposing clearer semantic naming conventions, to help bring more structure to the ABI's ontology.

## Decisions Made
1. **ABI Sub-Types:** The different sub-types contained within an ABI have been better defined:
* **"Definition"** = user-defined type (`MyObject`, `MyEnum`, etc).
* **"Type"** = built-in type (`UInt#`, `Int#`, `String`, etc).
* **"Reference"** = reference to a "Definition"
2. **Functions Not Methods:** In 0.1 we called the static functions exported by the module "methods", but since we have plans to introduce stateful objects w/ callable methods, we should rename this in 0.2. So, in 0.2 we will call them "module functions", and later will introduce "object methods".
3. **Imports Are Namespaced ABIs:** Instead of creating multiple properties on the `Abi` interface for each import type (ex: `importedObjects: ObjectDefinition[]`), we instead treat all imports as namespaced ABIs. This allows us to add a single property to the root ABI which contains all imports, `imports: ImportedAbi[]`, where `ImportedAbi` is a derived interface from `Abi` which adds `namespace` and `uri` properties.
4. **Heterogeneous < Homogenous Collections:** Currently the `Abi` interface stores each definition kind within a homogenous array (ex: `objects: ObjectDef[]`). It has been discussed that it may be better to make the `Abi` a heterogeneous collection of all possible definitions (ex: `type Abi = AnyDef[]`). This is also know as a "polymorphic array". After some consideration of 0.2's primary goals, we have decided that we prefer the homogenous collections approach because it is easier to parse, because you know ahead of time what the type of each element in the array is.
5. **Remove Comments:** In order to help optimize the ABI, we've removed all `comment` properties. Comments can instead be found on the original source file written by the user that was used to produce the ABI.
6. **Keyword `implements` no longer implies inheritance**: Currently, users use `implements` as `extends`. If they implement an interface, the interface's properties get automatically copied over to the implementation type. While this allows users to type less, it incorrectly behaves as inheritance; so we're removing that behavior. Now if `A implements B`, we will just validate that `A` contains the properties of `B`.
7. **Remove Interfaces and Capabilities:** All wrappers have implicit interface definitions (by having a schema) but only some have implementations. Therefore, there's no reason to restrict implementation wrappers types to be used as interfaces (with the `implements` keyword); or to only enable `getImplementations` capabilities in interface wrappers. So we're removing the concept of `interfaces` in favor of just using types, and enabling `getImplementation` capabilities for all modules.
8. **Import an imported ABI's imports**: Currently, it isn't possible to use a type that was imported in an import without manually re-exporting it, as referenced here: https://github.com/polywrap/toolchain/issues/1448. This will now be possible by importing it in its namespaced form. See the [example](abi/examples/imports/user.ts)
9. **Introduced `ImportRef` (references to an import)**: references to an imported definition are now defined as `ImportRef`s. All imported ABIs contain an `id` propertyand imported ABIs can also have nested imported ABIs inside of them. Therefore, types defined in nested imports can be referenced through a "route" of their IDs. For example, route `1.2.3` would point to an imported ABI with ID `3`, nested inside an imported ABI with ID `2`, nested inside an imported ABI with ID `1`. `ImportRef`s contain an `import_id` property that point to the referenced types's import route.

## Future Plans

- Research merkle-root hashes for root-definitions (function, object, enum, etc?) to help with validation execution time.
- Introduce the concept of "Runtime ABI", which would be a compressed hyper optimized ABI for small storage & download, and fast runtime traversal & introspection (hashes, etc). This ABI would be separate from the ABI that the CLI uses to generate code. This differentiation would help to avoid constraining ourselves too much with optimizations, in the ABI that we manipulate in the CLI and focus on "ease of work"; while also not holding back on optimizations for the "Runtime ABI" because it'd be harder to work with
Loading