From Stack Machine to Functional Machine: Step 1

Read on GitHub.

tags: Taylor , Yul, Ethereum, WebAssembly,ewasm

For illustrating our journey, we will use the Yul language (that compiles to Ethereum 1.0 and WebAssembly bytecode).

Anatomy of a Stack Runtime

For any calldata that begins with 0xffffffff the above contract will perform <SOME COMPUTING>.

We could assimilate this behavior with a function that has a signature and the output is a number of bytes. This function may have an input (the rest of calldata starting from byte 5 up to the end)

If we have the ability to parse the bytes into some defined types, we could consider that a function is a transformation from a type into another.

T1 and T2 could be any type. They could be even the same type or the None type or a Tuple of a number of types. Even more: we may define functions as being types as well: by using the function signature. For a complete solution on type definitions and casting, one may use dType: a fully decentralized type system. But we leave that subject for another day or conference.

We could treat functions as types. Even better: we should treat types as functions by choosing a representative function. Such a function is the new function: it accepts as input the minimum number of arguments for a type creation.

For such dependent types (that need to know the “parent” type and the size), we can define the dependent signature:

And for simplification, we could consider signature(<number>) => <number> and the signature function as bytes4(keccak(<content>))

Calling a function from another function: apply

Let’s define the apply function:

An example would be:

Using 0xffffffffeeeeeeee000000000000000000000000000000000000000000000000000000000000000a as calldata, we get 12. 0xffffffff applied 0xeeeeeeee on the input arguments (in this case, the value 10).

Using 0xffffffffdddddddd000000000000000000000000000000000000000000000000000000000000000a as calldata, we get 8.

Functional interaction for apply

In the above case, each function extracts the arguments that it expects, but this can become verbose and prone to errors.

We already have a type parser that is generated by on-chain type definitions by dType. Also, we have a Type Interpreter and Function Caller: it is the Pipeline intra-contract on-chain interpreter. More on this, in the next articles.

Recursive apply

Using 0xffffffffcccccccceeeeeeee000000000000000000000000000000000000000000000000000000000000002800000004 as calldata, we instruct the 0xcccccccc function to apply the 0xeeeeeeee function on the value 40, 4 times. This means 40 + 2 * 4. We get 48.

Using 0xffffffffccccccccdddddddd000000000000000000000000000000000000000000000000000000000000002800000004 as calldata, we get 32: 40 - 2 * 4.

Function Persistence

We could save any type/function on-chain (for the EVM) or into a JSON file treated by Javascript (for Wasm ).

A persisted function is a combination of other functions in a recursive manner until the “leaf” functions are applied. The “leaf” functions are contained in the smart contract itself or in other (external) smart contracts or Wasm libraries (in the Wasm case). Such a system of editing and deploying functional combinations is already implemented by the Pipeline Editor.

Implementation

The ideas above and the steps that will be described in future articles are even better implemented in the Taylor project. Taylor is an interpreted functional language with typing described by dType.

Next: Step 2

Recursive application is the “engine” of functional programming. In the next step, we will show applications of this engine.

Therefore, in the next article: Some functional patterns implemented in the same environment.

Read step 2: From Stack Machine to Functional Machine: Step 2 — Currying

Originally published at https://github.com.

Building bricks for the World Computer #ethereum #Pipeline #dType #EIP1900 https://github.com/loredanacirstea, https://www.youtube.com/c/LoredanaCirstea