Showing preview only (755K chars total). Download the full file or copy to clipboard to get everything.
Repository: pirapira/bamboo
Branch: master
Commit: 1cca98e0b6d2
Files: 162
Total size: 710.1 KB
Directory structure:
gitextract_oes_fca_/
├── .gitignore
├── .gitmodules
├── .travis.yml
├── LICENSE
├── Makefile
├── README.md
├── ReleaseNotes.txt
├── __tests__/
│ └── compare-js-native.js
├── _oasis
├── _tags
├── bsconfig.json
├── doc/
│ ├── manifest.md
│ ├── semantics.md
│ ├── spec.tex
│ ├── testing-bytecode.md
│ └── tutorial.md
├── myocamlbuild.ml
├── opam/
│ ├── descr
│ └── opam
├── package.json
├── setup.ml
├── sketch/
│ ├── future.bbo
│ └── open_auction.bbo
└── src/
├── ast/
│ ├── META
│ ├── ast.mldylib
│ ├── ast.mllib
│ ├── ast_test.ml
│ ├── contract.ml
│ ├── contract.mli
│ ├── ethereum.ml
│ ├── ethereum.mli
│ ├── evm.ml
│ ├── evm.mli
│ ├── location.ml
│ ├── location.mli
│ ├── pseudoImm.ml
│ ├── pseudoImm.mli
│ ├── sideEffect.ml
│ ├── sideEffect.mli
│ ├── syntax.ml
│ ├── syntax.mli
│ ├── type.ml
│ ├── type.mli
│ ├── typeEnv.ml
│ └── typeEnv.mli
├── basics/
│ ├── META
│ ├── assoc.ml
│ ├── assoc.mli
│ ├── basics.mldylib
│ ├── basics.mllib
│ ├── hex_test.ml
│ ├── hexa.ml
│ ├── hexa.mli
│ ├── label.ml
│ ├── label.mli
│ ├── misc.ml
│ ├── misc.mli
│ ├── storage.ml
│ └── storage.mli
├── codegen/
│ ├── META
│ ├── codegen.ml
│ ├── codegen.mldylib
│ ├── codegen.mli
│ ├── codegen.mllib
│ ├── codegenEnv.ml
│ ├── codegenEnv.mli
│ ├── codegen_test.ml
│ ├── codegen_test2.ml
│ ├── entrypointDatabase.ml
│ ├── entrypointDatabase.mli
│ ├── layoutInfo.ml
│ ├── layoutInfo.mli
│ ├── layouts.txt
│ ├── locationEnv.ml
│ ├── locationEnv.mli
│ ├── parse.ml
│ └── parse.mli
├── cross-platform/
│ ├── META
│ ├── cross-platform.mldylib
│ ├── cross-platform.mllib
│ ├── rope.ml
│ ├── wrapBn.ml
│ ├── wrapBnNative.ml
│ ├── wrapCryptokit.ml
│ ├── wrapCryptokitNative.ml
│ ├── wrapList.ml
│ ├── wrapListNative.ml
│ ├── wrapOption.ml
│ ├── wrapString.ml
│ └── wrapStringNative.ml
├── cross-platform-for-ocamlbuild/
│ ├── META
│ ├── cross-platform.mldylib
│ ├── cross-platform.mllib
│ └── wrapOption.ml
├── exec/
│ ├── bamboo.ml
│ ├── compileFile.ml
│ ├── compileFile.mli
│ └── endToEnd.ml
├── exec-js/
│ └── bambooJs.ml
├── lib/
│ ├── META
│ └── lib_test.ml
├── parse/
│ ├── META
│ ├── README.md
│ ├── examples/
│ │ ├── 000nil.bbo
│ │ ├── 001empty.bbo
│ │ ├── 002comment.bbo
│ │ ├── 003default_abort.bbo
│ │ ├── 004simple_case_abort.bbo
│ │ ├── 005auction_start.bbo
│ │ ├── 006auction_first_case.bbo
│ │ ├── 007auction_first_case_more.bbo
│ │ ├── 008new_var.bbo
│ │ ├── 009new_var_auc.bbo
│ │ ├── 00a_auc_first_cast.bbo
│ │ ├── 00b_auction_more.bbo
│ │ ├── 00bbauction_first_named_case.bbo
│ │ ├── 00c_auction.bbo
│ │ ├── 00d_auction.bbo
│ │ ├── 00e_ecdsarecover.bbo
│ │ ├── 00f_bytes32.bbo
│ │ ├── 00g_int8.bbo
│ │ ├── 00h_payment_channel.bbo
│ │ ├── 00i_local_bool.bbo
│ │ ├── 010_logical_and.bbo
│ │ ├── 011_keccak256.bbo
│ │ ├── 013_iszero.bbo
│ │ ├── 014_ifelse.bbo
│ │ ├── 015_ifblock.bbo
│ │ ├── 016_void.bbo
│ │ ├── 017_return_void.bbo
│ │ ├── 018_mapmap.bbo
│ │ ├── 019_something.bbo
│ │ ├── 01a_event.bbo
│ │ ├── 01b_erc20better.bbo
│ │ ├── 020_plus_mult.bbo
│ │ ├── 021_land_neq.bbo
│ │ ├── 022_plus_gt.bbo
│ │ ├── 024_vault.bbo
│ │ ├── 024_vault_shorter.bbo
│ │ ├── 025_declit_numeric.bbo
│ │ ├── 026_abc.bbo
│ │ └── 027_counting.bbo
│ ├── lexer.mll
│ ├── negative_examples/
│ │ ├── bad_end.bbo
│ │ ├── duplicate_contract_names.bbo
│ │ ├── mixed_uints.bbo
│ │ ├── multi_default.bbo
│ │ ├── uint256_too_big.bbo
│ │ ├── uint8_too_big.bbo
│ │ ├── uint8_with_four_digits.bbo
│ │ ├── unknown_ctor_arg.bbo
│ │ ├── unknown_return.bbo
│ │ ├── unknown_type.bbo
│ │ ├── void_not_void.bbo
│ │ ├── void_some_return.bbo
│ │ ├── wrong_arg.bbo
│ │ └── wrong_return.bbo
│ ├── parse.mldylib
│ ├── parse.mllib
│ ├── parser.mly
│ └── parser_test.ml
└── run_tests.sh
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
*~
*.native
_build
setup.data
setup.log
.DS_Store
.merlin
.bsb.lock
npm-debug.log
/lib/bs/
/lib/js/
/node_modules/
src/parse/lexer.ml
src/parse/parser.ml
================================================
FILE: .gitmodules
================================================
[submodule "bamboo-tests"]
path = bamboo-tests
url = https://github.com/pirapira/bamboo-tests.git
================================================
FILE: .travis.yml
================================================
notifications:
webhooks:
urls:
- https://webhooks.gitter.im/e/4f71b9fa80e108068016
on_success: change # options: [always|never|change] default: always
on_failure: always # options: [always|never|change] default: always
on_start: never # options: [always|never|change] default: always
dist: trusty
cache:
directories:
- $HOME/.ccache
- $HOME/build/pirapira/cpp-ethereum
- $HOME/build/pirapira/cmake
env:
global:
- CASHER_TIME_OUT=1200
sudo: required
before_install:
- BAMBOO=`pwd`
- sudo apt-get -qq update
- sudo apt-get install aspcud ccache jq
# - git clone https://github.com/polyml/polyml.git
# - cd polyml
# - git checkout v5.6
# - ./configure
# - make
# - make compiler
# - sudo make install
# - cd -
# - sudo updatedb
# - locate libpolymain.a
- wget https://raw.github.com/ocaml/opam/master/shell/opam_installer.sh -O - | sudo sh -s /usr/local/bin
- export OPAMJOBS=2
- opam init -y --comp=4.02.3+buckle-master
- opam switch 4.02.3+buckle-master
- eval `opam config env`
- opam update
- opam upgrade -y
# It's important to install batteries first, so the proper version of rpc can be installed afterwards
- git clone https://github.com/bsansouci/batteries-included
- cd ./batteries-included && opam pin add -y batteries . && cd ..
- opam install -y ocamlfind menhir rope zarith ppx_deriving rpc=1.9.52 cryptokit hex
- cd ../..
- if [ ! -d cpp-ethereum/.git ]; then rm -rf cpp-ethereum; git clone https://github.com/pirapira/cpp-ethereum --recursive; fi
- sudo apt install -y build-essential libgmp-dev libleveldb-dev libmicrohttpd-dev g++-4.8 gcc-4.8
- sudo apt purge -y cmake
- mkdir -p cmake
- cd cmake
- if [ ! -f cmake-3.8.2-Linux-x86_64.tar.gz ]; then wget https://cmake.org/files/v3.8/cmake-3.8.2-Linux-x86_64.tar.gz && tar xf cmake-3.8.2-Linux-x86_64.tar.gz; fi
- PATH=`pwd`/cmake-3.8.2-Linux-x86_64/bin:$PATH
- cd -
- cmake --version
- cd cpp-ethereum
- git fetch
- git checkout origin/test-raw-sign
- git show | head -n 3
- git submodule update --recursive
- mkdir -p build
- cd build
- CC=gcc-4.8 CXX=g++-4.8 cmake ..
- CC=gcc-4.8 CXX=g++-4.8 make -j3 eth
- sudo make install
- cd $BAMBOO
- sudo apt install texlive-latex-base texlive-science texlive-math-extra
install:
- npm install
- cd bamboo-tests
- npm install
- cd -
script:
- make doc/spec.pdf
- make
- ln -s ./bamboo.native lib/bs/native/bamboo
- PATH=`pwd`/lib/bs/native:$PATH
- cd bamboo-tests
- npm test
- cd -
- make test
- which eth
- eth --version
- mkdir -p /tmp/test
- eth --test -d /tmp/test &> eth.log &
- PID=$!
- sleep 4
- endtoend.native
- kill $PID
- cat eth.log
- opam pin add bamboo . -y
- opam remove bamboo
- opam install bamboo -y
================================================
FILE: LICENSE
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2016 Yoichi Hirai
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
================================================
FILE: Makefile
================================================
.PHONY: test bamboo clean dep
bamboo:
npm run build
dep:
npm install
opam switch 4.02.3+buckle-master
eval `opam config env`
# It's important to install batteries first, so the proper version of rpc can be installed afterwards
git clone https://github.com/bsansouci/batteries-included ./node_modules/batteries-included
cd ./node_modules/batteries-included && opam pin add -y batteries . && cd ../..
opam install -y ocamlfind menhir rope zarith ppx_deriving rpc=1.9.52 cryptokit hex
doc/spec.pdf: doc/spec.tex
(cd doc; pdflatex -halt-on-error spec.tex; pdflatex -halt-on-error spec.tex)
test:
(cd src; sh ./run_tests.sh)
clean:
npm run clean
================================================
FILE: README.md
================================================
# Bamboo: a language for morphing smart contracts
Cornell Blockchain says they can now maintain the Bamboo compiler. https://github.com/CornellBlockchain/bamboo
<hr>
[](https://gitter.im/bbo-dev/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[](https://travis-ci.org/pirapira/bamboo)
Bamboo is a programming language for Ethereum contracts.
Bamboo makes state transition explicit and avoids reentrance problems by default.
See [manifest](doc/manifest.md) for the motivation, or [tutorial](doc/tutorial.md) if you want to deploy something first, or [semantics](doc/semantics.md) if you need something resembling a definition.
## Example Bamboo Code
* [A payment channel](./src/parse/examples/00h_payment_channel.bbo)
* [An ERC20 contract](./src/parse/examples/01b_erc20better.bbo)
* [A vault](https://medium.com/@pirapira/implementing-a-vault-in-bamboo-9c08241b6755)
## Compiler
The Bamboo compiler sometimes produces bytecode, which needs to be tested.
As preparation,
* install [opam](http://opam.ocaml.org/doc/Install.html) with OCaml 4.04.1
* `opam install bamboo`
should install `bamboo`.
When you check out this repository,
```
bamboo < src/parse/examples/006auction_first_case.bbo
```
produces a bytecode. Do not trust the output as the compiler still contains bugs probably.
```
bamboo --abi < src/parse/examples/006auction_first_case.bbo
```
prints ABI.
```
[{"type": "constructor", "inputs":[{"name": "_beneficiary", "type": "address"},{"name": "_bidding_time", "type": "uint256"},{"name": "_highest_bid", "type": "uint256"}], "name": "auction", "outputs":[], "payable": true},{"type":"fallback","inputs": [],"outputs": [],"payable": true}]
```
## Developing Bamboo
To try Bamboo in your local environment, run `make dep` from the project folder. That should install all dependencies.
Once the installation process is done, run `eval $(opam config env)` and then you can build all targets using `make`, and run the tests with `make test`.
When you modify the OCaml source of Bamboo, you can try your version by
```
$ make
$ ./lib/bs/native/bamboo.native < src/parse/examples/006auction_first_case.bbo
```
**Embark**
An [Embark plugin for Bamboo](https://github.com/embark-framework/embark-bamboo) is available. To use it, first install [Embark](https://embark.status.im/docs/) and add then add the plugin to your DApp.
```Javascript
npm install -g embark
embark new AppName
cd AppName
npm install embark-bamboo --save
```
then add embark-bamboo to the plugins section in ```embark.json```:
```Json
"plugins": {
"embark-bamboo": {}
}
```
Afterwards Embark will recognize .bbo files and compile them with Bamboo.
## How to Contribute
* notice problems and point them out. [create issues](https://github.com/pirapira/bamboo/issues/new).
* test the bytecode like [this](doc/tutorial.md), but using other examples. You might find bugs in the compiler.
* write new Bamboo code and test the compiler.
* join the [Gitter channel](https://gitter.im/bbo-dev/Lobby).
* spread a rumor to your friends who are into programming languages.
## Related Work
### Linden Scripting Language
[Linden Scripting Language](http://wiki.secondlife.com/wiki/Getting_started_with_LSL#Introducing_States_and_Events) has similar organization of code according to `state`s.
### Obsidian
[Obsidian](https://ieeexplore.ieee.org/document/7965268/) is another programming language that models smart contracts as state machines. Obsidian even tracks states of the contracts statically.
================================================
FILE: ReleaseNotes.txt
================================================
Version 0.0.03 (2018-05-04)
* fixes incorrect characters in the ABI https://github.com/pirapira/bamboo/issues/279
* integration tests with Ganache-cli https://github.com/pirapira/bamboo/pull/263
* bamboo.js using BuckleScript https://github.com/pirapira/bamboo/pull/260
Version 0.0.02 (2017-10-13)
* decimal literals #208 by @aupiff
* detecting racing side-effects #186
* banning the keyword uint in favor of uint256
* More elegant parser using Menhir libraries
================================================
FILE: __tests__/compare-js-native.js
================================================
// A small script to test if both versions (JS and native) output the same
// string given the same programs as input
// To run: `node compare-js-native.js`
const fs = require('fs');
const path = require('path');
const execSync = require('child_process').execSync;
const examplesFolder = '../src/parse/examples';
fs.readdir(examplesFolder, (err, files) => {
files.forEach(file => {
console.log(`Comparing native vs js output for file: ${file}...`);
const filePath = path.join(examplesFolder, file);
const jsOutput = execSync(`node ../lib/js/src/exec-js/bambooJs.js < ${filePath}`).toString();
const nativeOutput = execSync(`../bamboo.native < ${filePath}`).toString();
const equal = jsOutput === nativeOutput;
console.log(`Result: ${equal ? 'ok' : 'DIFF'}\n`);
});
})
================================================
FILE: _oasis
================================================
OASISFormat: 0.4
Name: bamboo
Version: 0.0.03
Synopsis: A compiler targeting Ethereum Virtual Machine
Authors: Yoichi Hirai <i@yoichihirai.com>
License: Apache-2.0
Plugins: META (0.4)
Homepage: https://github.com/pirapira/bamboo
Description: Bamboo compiles a simple language to Ethereum Virtual Machine. The language is designed to keep programmers away from common mistakes. It features: state transition as recursion with potentially changing arguments, mandatory reentrance continuation when calling out, no loops, no assignments except to mappings and partial compliance with common Ethereum ABI.
SourceRepository opam-pin
Type: Git
Location: https://github.com/pirapira/bamboo.git
Branch: master
Executable bamboo
Path: src/exec
Install: true
BuildTools: ocamlbuild
MainIs: bamboo.ml
CompiledObject: best
BuildDepends: parse, codegen
Library ast
Path: src/ast
Install: false
BuildTools: ocamlbuild
Modules: Contract, Syntax, TypeEnv, Type, PseudoImm, Evm, Location, Ethereum
BuildDepends: basics, cryptokit (>= 1.12), hex
Library basics
Path: src/basics
Install: false
BuildTools: ocamlbuild
Modules: Assoc, Hexa, Label, Misc, Storage
BuildDepends: cross-platform
Library cross-platform
Path: src/cross-platform-for-ocamlbuild
Install: false
BuildTools: ocamlbuild
Modules: WrapBn, WrapCryptokit, WrapList, WrapString, WrapOption
BuildDepends: batteries,rope,cryptokit (>= 1.12),hex
Library codegen
Path: src/codegen
Install: false
BuildTools: ocamlbuild
Modules: CodegenEnv, Codegen, EntrypointDatabase,
LayoutInfo, LocationEnv, Parse
BuildDepends: basics, ast, parse
Library parse
Path: src/parse
Install: false
BuildTools: ocamlbuild
Modules: Lexer
BuildDepends: ast, menhirLib
================================================
FILE: _tags
================================================
# OASIS_START
# DO NOT EDIT (digest: c348eeadfb15aa1af2d805f976b82290)
# Ignore VCS directories, you can use the same kind of rule outside
# OASIS_START/STOP if you want to exclude directories that contains
# useless stuff for the build process
true: annot, bin_annot
<**/.svn>: -traverse
<**/.svn>: not_hygienic
".bzr": -traverse
".bzr": not_hygienic
".hg": -traverse
".hg": not_hygienic
".git": -traverse
".git": not_hygienic
"_darcs": -traverse
"_darcs": not_hygienic
# Library cross-platform
"src/cross-platform-for-ocamlbuild/cross-platform.cmxs": use_cross-platform
<src/cross-platform-for-ocamlbuild/*.ml{,i,y}>: pkg_batteries
<src/cross-platform-for-ocamlbuild/*.ml{,i,y}>: pkg_cryptokit
<src/cross-platform-for-ocamlbuild/*.ml{,i,y}>: pkg_hex
<src/cross-platform-for-ocamlbuild/*.ml{,i,y}>: pkg_rope
# Library basics
"src/basics/basics.cmxs": use_basics
<src/basics/*.ml{,i,y}>: pkg_batteries
<src/basics/*.ml{,i,y}>: pkg_cryptokit
<src/basics/*.ml{,i,y}>: pkg_hex
<src/basics/*.ml{,i,y}>: pkg_rope
<src/basics/*.ml{,i,y}>: use_cross-platform
# Library ast
"src/ast/ast.cmxs": use_ast
<src/ast/*.ml{,i,y}>: pkg_batteries
<src/ast/*.ml{,i,y}>: pkg_cryptokit
<src/ast/*.ml{,i,y}>: pkg_hex
<src/ast/*.ml{,i,y}>: pkg_rope
<src/ast/*.ml{,i,y}>: use_basics
<src/ast/*.ml{,i,y}>: use_cross-platform
# Library parse
"src/parse/parse.cmxs": use_parse
<src/parse/*.ml{,i,y}>: pkg_batteries
<src/parse/*.ml{,i,y}>: pkg_cryptokit
<src/parse/*.ml{,i,y}>: pkg_hex
<src/parse/*.ml{,i,y}>: pkg_menhirLib
<src/parse/*.ml{,i,y}>: pkg_rope
<src/parse/*.ml{,i,y}>: use_ast
<src/parse/*.ml{,i,y}>: use_basics
<src/parse/*.ml{,i,y}>: use_cross-platform
# Library codegen
"src/codegen/codegen.cmxs": use_codegen
<src/codegen/*.ml{,i,y}>: pkg_batteries
<src/codegen/*.ml{,i,y}>: pkg_cryptokit
<src/codegen/*.ml{,i,y}>: pkg_hex
<src/codegen/*.ml{,i,y}>: pkg_menhirLib
<src/codegen/*.ml{,i,y}>: pkg_rope
<src/codegen/*.ml{,i,y}>: use_ast
<src/codegen/*.ml{,i,y}>: use_basics
<src/codegen/*.ml{,i,y}>: use_cross-platform
<src/codegen/*.ml{,i,y}>: use_parse
# Executable bamboo
<src/exec/bamboo.{native,byte}>: pkg_batteries
<src/exec/bamboo.{native,byte}>: pkg_cryptokit
<src/exec/bamboo.{native,byte}>: pkg_hex
<src/exec/bamboo.{native,byte}>: pkg_menhirLib
<src/exec/bamboo.{native,byte}>: pkg_rope
<src/exec/bamboo.{native,byte}>: use_ast
<src/exec/bamboo.{native,byte}>: use_basics
<src/exec/bamboo.{native,byte}>: use_codegen
<src/exec/bamboo.{native,byte}>: use_cross-platform
<src/exec/bamboo.{native,byte}>: use_parse
<src/exec/*.ml{,i,y}>: pkg_batteries
<src/exec/*.ml{,i,y}>: pkg_cryptokit
<src/exec/*.ml{,i,y}>: pkg_hex
<src/exec/*.ml{,i,y}>: pkg_menhirLib
<src/exec/*.ml{,i,y}>: pkg_rope
<src/exec/*.ml{,i,y}>: use_ast
<src/exec/*.ml{,i,y}>: use_basics
<src/exec/*.ml{,i,y}>: use_codegen
<src/exec/*.ml{,i,y}>: use_cross-platform
<src/exec/*.ml{,i,y}>: use_parse
# OASIS_STOP
true: use_menhir
<bamboo-tests>: -traverse
<lib/bs>: -traverse
<node_modules>: -traverse
<batteries-included>: -traverse
================================================
FILE: bsconfig.json
================================================
{
"name": "bamboo",
"version": "0.0.02",
"bsc-flags": "-w -27 -g",
"warnings": {
"number": "-40+6+7-26-27+32..39-28-44+45",
"error": "+8"
},
"bs-dependencies": [
"bs-bn.js"
],
"ocamlfind-dependencies": [
"batteries",
"cryptokit",
"hex",
"ppx_deriving",
"ppx_deriving_rpc",
"rpclib.json"
],
"generators": [
{
"name": "ocamllex",
"command": "ocamllex $in"
},
{
"name": "menhir",
"command": "menhir $in"
}
],
"sources": {
"dir": "src",
"subdirs": [
{"dir": "ast"},
{"dir": "basics"},
{"dir": "codegen"},
{"dir": "cross-platform"},
{"backend": "native", "dir": "exec"},
{"backend": "js", "dir": "exec-js"},
{"dir": "lib"},
{"dir": "parse",
"generators": [
{
"name": "ocamllex",
"edge": ["lexer.ml", ":", "lexer.mll"]
},
{
"name": "menhir",
"edge": ["parser.ml", "parser.mli", ":", "parser.mly"]
}
]
}
]
},
"entries": [
{
"backend": "native",
"main-module": "Bamboo"
},
{
"backend": "native",
"main-module": "Codegen_test"
},
{
"backend": "native",
"main-module": "Codegen_test2"
},
{
"backend": "native",
"main-module": "Lib_test"
},
{
"backend": "native",
"main-module": "Hex_test"
},
{
"backend": "native",
"main-module": "Parser_test"
},
{
"backend": "native",
"main-module": "Ast_test"
},
{
"backend": "native",
"main-module": "EndToEnd"
},
{
"backend": "js",
"main-module": "BambooJs"
}
],
"refmt": 3
}
================================================
FILE: doc/manifest.md
================================================
# Bamboo Manifest
## Problem
Smart contracts should reduce surprises.
The code should reveal what can happen in which order, and the same
ordering must be enforced mechanically. This is not done in the usual
way of writing smart contracts where a smart contract is described as
several interface functions.
In the following example, the names of functions suggest the timing of
the calls, but this ordering can only be enforced by careful timestamp
checking or global state tracking in the body of the functions.
```
contract CrowdFund() {
case(void toBeCalledDuringFunding()) {
// ...
}
case(void toBeCalledAfterFailure()) {
// ...
}
case(void toBeCalledAfterSuccess()) {
// ...
}
case(void notSureWhatThisDoes()) {
// ...
}
}
```
To make my point clearer, I added the last function
`notSureWhatThisDoes()`. Whenever such a function exists the
temporal order is ambiguous. An interface function can be called
at any moment by default. A closer look is necessary for every
interface function before a reader or the machine can enumerate
the possible orderings of events.
## Solution
The solution is polymorphic contracts. According to the stages,
a contract changes its signature.
```
contract Funding() {
case(bool toBeCalledDuringFunding()) {
// something something
return true then become Funding();
}
case(bool endFunding()) {
if (something)
return (true) then become FundingSuccess();
else
return (false) then become FundingFailure();
}
}
contract FundingSuccess() {
case(void toBeCalledAfterSuccess()) {
// something
}
}
contract FundingFailure() {
case(void toBeCalledAfterFailure()) {
// something
}
}
```
All of these contracts `Funding`, `FundingSuccess` and `FundingFailure` occupies the same address. The initial contract `Funding` becomes `FundingSuccess` or `FundingFailure`.
Where has gone the `notSureWhatThisDoes()` function in the previous
example? It's not there because, well, I am not sure where it goes.
The new style forces temporal organization of the code lines.
### Syntax
After some polishing I ended up to something like [this](../src/parse/examples/00d_auction.bbo).
There is some influence from Erlang.
### Not to have
This language is designed to facilliate a particular style.
So the language will not support features like:
* loop constructs (`for`, `while`, ...). Due to the constant block gas limit, loops should be avoided and each iteration should be done in separate transactions.
* assignments into storage variables, except array elements. Instead of assigning a new value to a storage variable, the new value can be given as an argument in the continaution (e.g. `return () then auction(new_highest_bidder, ...)`
================================================
FILE: doc/semantics.md
================================================
# Bamboo Semantics Sketch
This document describes the semantics of the Bamboo language. This is an informal sketch written as a preparation for the coming Coq or K code.
## Overview
### Arena of the Game
A program written in Bamboo, once deployed, participates in a game between the program and the world. In this game, the world makes the first move, the program makes the second move, and so on alternatively. Neither the world or the program makes two moves in a row. This document aims at defining the choice of the program's move, given a sequence of earlier moves.
The world can make the following three kinds of moves:
* calling the program
* returning into the program
* failing into the program
The program can make the following five kinds of moves:
* calling an account
* deploying code
* returning
* failing
* destroying itself
A sequence of moves can be equipped with a number called the nesting.
The empty sequence is associated with zero-nesting. Initially, when the program is deployed, the program is not running (or running with zero-nesting). When the program is not running, the world can only call the program.
When the world calls the program, the nesting increases by one. When the program returns, fails, or destroys itself, the nesting decreases by one.
From the above sentences, you should be able to prove that the nesting never goes below zero.
### Bamboo's Strategy
In general, a program needs to decide on a move after any sequence of moves that ends with the world's move. However, Bamboo does not remember the whole sequence of moves, but just remembers the "program's state". The Bamboo semantics computes the program's next move only using the stored program's state and the previous move made by the world. In addition to the program's move, the Bamboo semantics specifies the program's new altered state for later use.
### Bamboo's Program State
The program's state has three components: a persistent state, a `killed` flag, and pending execution states. When the game is `n`-running, the program's state contains `n` pending execution states.
A persistent state is either the special aborting element or a name of the contract followed by its arguments.
In the simple case, when the source code says
```
contract A ()
```
the persistent state can be simply `A()`.
In a more complicated example, when the source code says
```
contract B (uint totalSupply)
```
the program's state can be `B(0)`, `B(3000)` or `B(<any uint256 value>)`. However, `B()` is not a program state. `B(1,2)` is not a persistent state either because the number of arguments do not match the number of parameters in the source code.
### An example of Persistent States
Let's consider one Bamboo source code, which contains three contracts:
```
contract A() {
default {
return then become B();
}
}
contract B() {
default {
return then become C();
}
}
contract C() {
default {
selfdestruct(this);
}
}
```
When this source code is compiled and deployed, we get a program whose state consists of a persistent state and no pending execution states. The initial persistent state is `A()`. The initial `killed` flag is `false`.
When the world calls the program, the program might return, leaving the persistent state `B()`; intuitively, that's the meaning of `return then become B()`. Otherwise, there is a possibility that the program fails, leaving the persistent state as `A()` (this possibility comes from EVM's out-of-gas).
When the world calls the program again, the program might return, leaving the persistent state `C()`; intuitively, that's the meaning of `return then become C()`. Otherwise, there is a possibility that the program fails, leaving the persistent state as `B()` (this possibility comes from EVM's out-of-gas).
When the world calls the program again, the program might destroy itself. This is described in `selfdestruct(this)`. The form `selfdestruct(.)` takes one argument, which specifies the account where the remaining ETH balance goes. The keyword `this` represents the Ethereum account where the program is deployed. Bamboo inherits EVM's special behavior when the program's own address is specified as the receiver of the remaining balance. In that case, the remaining balance disappears. After selfdestruction, the program's state contains the `killed` flag `true`. Again, there is a possibility that the program fails, leaving the persistent state as `C()` and the `killed` flag `false` (this possibility comes from EVM's out-of-gas).
### What happens after selfdestruction
After the program destroys itself, if the world calls the program, the program simply returns the empty data given enough gas. The program might fail if there is not enough gas. (TODO: make sure the compiler realizes this behavior. Issue [#170](https://github.com/pirapira/bamboo/issues/170).)
### What happens if the selfdestruction is reverted?
People familiar with EVM semantics might ask what happens when state changes are reverted. The Bamboo semantics do not see the state reversion. From a history in the EVM, you can pick up unreverted executions, and the Bamboo semantics can run there.
(TODO: maybe I should not mention the possibilities that the program fails because of out-of-gas in EVM?)
## Pending Execution State
As mentioned, a program's state contains a list of pending execution states. Moreover, after the world makes a move and before the program makes a move, the abstract machine keeps track of the current pending execution state.
A pending execution state contains an evaluation point, a variable environment and an annotating function. Each component is described below.
### An evaluation point
Any pending execution state contains an evaluation point. An evaluation point is either a sentence or an expression in the source code. When identical expressions (resp. sentences) appear in the source code, they are considered different expressions (resp. sentences) if their locations are different.
A Bamboo source code is a list of contracts. A contract contains a list of cases. A case contains a list of sentences. A sentence contains sentences and/or expressions. An expression contains sentences and/or expressions. The current evaluation point is either a sentence or an expression in the source code. (TODO: there should be a separate document called Bamboo Syntax.)
### A variable environment
Any pending execution state contains a variable environment. A variable environment is a finite map from identifiers to values. (TODO: describe identifiers in a separate document Bamboo Syntax).
A value is a sequence of 32 bytes. When values are interpreted as numbers, they are encoded in big-endian.
The empty variable environment maps no identifiers to values.
### An annotating function
Any pending execution state contains an annotation function. An annotation function is a finite map from expressions in the source code to values or persistent states. In other words, given an expression in the source code, an annotation function gives nothing, a value, or a persistent state. When identically looking expressions appear in the source code, they are considered different if their locations are different.
The empty annotating function maps no expressions to values.
## When the World calls the Program
When the world calls the program, the world can specify one of the two kinds of calls: calling the default case or calling a named case.
Anyway, when the world calls the program, the program first looks up the source code for the contract specified in the permanent state. For example, when the permanent state is `A()`, the program tries to find a contract called `A` with zero arguments in the source code. If such a contract is not found in the source code, the Bamboo compiler is broken. If multiple such contracts are found in the compiler, the Bamboo compiler is also broken.
Moreover, if the persistent state of the program contains `killed` flag being true, the program returns or fails at random (the EVM knows if there is enough gas to execute `STOP`, but the Bamboo semantics is not aware of the EVM's choice).
### The world can call the default case
If such a contract is found in the source code, and if the world has called the default case, the program then looks for the `default` case in the contract. If there is none, the program fails. If there are more than one `default` case, the Bamboo compiler is broken. If there is one such `default` case, the `default` case contains a list of sentences. If the list of sentences is empty, the Bamboo compiler is broken. Otherwise, the evaluation point is set to the first sentence in the list of sentences.
The combination of the evaluation point, the empty variable environment, and the empty annotating function is kept as the current pending execution state.
### The world can call a named case
When the world calls a named case, the world needs to specify an identifier (name of the case), a list of ABI types and a list of values.
Bamboo recognizes the following ABI types:
* uint256
* uint8
* bytes32
* address
* bool
These types are just meaningless symbols.
A value is a sequence of 32 bytes.
When the world calls a named case, the program looks up the source code for the contract specified in the permanent state. If the contract is not found, the Bamboo compiler is broken. If multiple contracts are found matching the permanent state, the Bamboo compiler is also broken.
The program searches the contract in the source code for a case that matches the world's call. For instance, when the world specified a named case `f(uint256, bool, address)`, the case `case (f (uint256 x, bool y, address z))` is a matching case. When there are no cases that match the world's call, the program proceeds as if the world specified the default case. If there are multiple cases that match the world's call, the Bamboo compiler is broken.
The case contains a list of sentences. If the list is empty, the Bamboo compiler is broken. Otherwise, the evaluation point is set to the first sentence in the list of sentences. To clarify the first-last direction, the first sentence is the closest to the case's header.
If the world's call contains more values than ABI types, the program fails. If the world's call contains fewer values than ABI types, the program also fails. Otherwise, a variable environment is formed in a straightforward way (TODO: explain).
The combination of the evaluation point, the variable environment, and the empty annotating function is kept as the current pending execution state.
## When there is a current pending execution state
When there is a current pending execution state, there is always a possibility that the program fails immediately. This is because of the underlying EVM mechanism can run out of gas, but Bamboo is not aware of this mechanism. From this document's view, the program just fails at any moment randomly.
Moreover, when the evaluation point in the current pending execution state is an `abort;` sentence, the program certainly fails.
Otherwise, when the evaluation point in the current pending execution state is a `return then become X;` sentence, if the annotating function does not map `X` to anything, the evaluation point is set to `X`. When the annotation function maps `X` to a persistent state, the program returns and leaves the persistent state specified by the annotation function.
Otherwise, when the evaluation point in the current pending execution state is a `return e then become X;` sentence, if the annotating function does not map `X` to anything, the evaluation point is set to `X`. When the annotation function maps `X` to a persistent state, but the annotation function does not map `e` to anything, the evaluation point is set to `e`. When the annotation function maps `X` to a persistent state and the annotation function maps `e` to a value, the program returns the value associated with `e` and leaves the persistent state associated with `X`. When the annotation function does anything else, the Bamboo compiler is broken.
Otherwise, when the evaluation point in the current pending execution state is a `void = X;` sentence, if the annotating function does not map `X` to anything, the evaluation point is set to `X`. Otherwise, the evaluation point advances from the sentence (see below for how an evaluation point advances from a sentence in the source code).
Otherwise, when the evaluation point in the current pending execution state is a `TYPE V = X` where `TYPE` is a name of a type, `V` is an identifier and `X` is an expression, if the annotating function does not map `X` to anything, the evaluation point is set to `X`. Otherwise, if the annotating function maps `X` to a value, the variable environment is updated to map `V` to the value, and the evaluation point advances from this sentence (see below for what it is that the evaluation point advances).
Otherwise, when the evaluation point in the current pending execution state is an `if (C) then B0 else B1` sentence, where `C` is an expression, `B0` is a block and `B1` is another block, the evaluation point is set to `C` if the annotating function does not map `C` to anything. Otherwise, when the annotation function maps `C` to zero, the evaluation point advances into `B1` (see below for what it is that the evaluation point advances into a block). Even otherwise, when the annotation function maps `C` to a non-zero value, the evaluation point advances into `B0`. When the annotation function maps `C` to something else, the Bamboo compiler is broken.
Otherwise, when the evaluation point in the current pending execution state is a `log E(e0, e1, ..., en)` sentence, if the annotation function maps any `ek` to nothing, the last such argument becomes the evaluation point. Otherwise, the evaluation point moves advances from this sentence (see below for what it is for an evaluation point to advance).
Otherwise, when the evaluation point in the current pending execution state is a `selfdestruct(X);` sentence, if the annotating function does not map `X` to anything, the evaluation point is set to `X`. When the annotating function maps `X` to a value, the program destroys itself, specifying the value as the inheritor. The current pending execution state is discarded. The `killed` flag is set in the persistent state. (When the program has been called from a Bamboo program, the world then returns into that Bamboo program, not failing into it.)
Otherwise, when the evaluation point in the current pending execution state is an identifier occurrence, the program looks up the variable environment. If the variable environment does not map the identifier occurrence to a value, the Bamboo compiler is broken. Otherwise, when the variable environment maps the identifier occurrence to a value, the annotating function now associates the identifier occurrence with the value. The evaluation point is set to the surrounding expression or sentence.
Otherwise, when the evaluation point in the current pending execution state is a call `C.m(E1, E2, ...,E_n) reentrance { abort; }`, if the annotating function does not map `C` to anything, the evaluation point is set to `C`. Otherwise, if the annotation function maps any of `E_k` to nothing, the evaluation point is set to the last such argument. Otherwise, the program calls an account of address, specified by the annotation of `C`. The call is on a named case `m` (TODO: for completing this clause, we need some information about the types of arguments of `m`. We need some information in the persistent state), together with annotations of `E1`, ... `E_n`. The program's state should now contain the current pending execution state as the last element in the list of pending execution states. Moreover, the persistent state in the program's state is now the aborting element.
Otherwise, when the evaluation point in the current pending execution state is a deployment `deploy C(E1, E2, E_n) reentrance { abort; }`, if the annotation function maps any of `E_k` to nothing, the evaluation point is set to the last such argument. Otherwise, the program deploys the contract `C` with a packing of annotations of `E_k`s. If the contract `C` does not appear in the source code, the Bamboo compiler is broken. The program's state should now contain the current pending execution state as the last element in the list of pending execution states. Moreover, the persistent state in the program's state is now the aborting element.
## How to advance an evaluation point
When an evaluation point advances from a sentence, if the sentence belongs to a case's body, and there is a next sentence, the next sentence becomes the evaluation point. Otherwise, if the sentence belongs to a case's body but there is no next sentence, the Bamboo compiler has an error. Otherwise, when the sentence belongs to a block, and there is a next sentence, the next sentence becomes the evaluation point. Otherwise, when the sentence belongs to a block and there is no next sentence, the evaluation point advances from the sentence containing the block. Otherwise, when the sentence belongs to a sentence, the evaluation point advances from the containing sentence.
## When the World returns into the Program
When the world returns into the program but the program's state does not contain any pending execution state, something is very wrong. Otherwise, the program finds in its state the last element in the list of pending execution states. This element is removed from the program's state and becomes the current pending execution state. The execution continues according to the execution point in the current pending execution state.
## When the World fails into the Program
The program fails as well.
## Adding Mappings
Sometimes, a contract contains a mapping. For example, when a contract in the source code looks like
```
A(address => uint256 balances) { ... }
```
The permanent state associates a value for `balances`. Moreover, the permanent state contains a grand mapping that takes two values and return a value. This grand mapping `M` is common to all mappings in the permanent state. When `balances[3]` is looked up, actually, `M(<<balances>>, 3)` is looked up (where `<<balances>>` is the value that he permanent state associates to `balances`). When a program is deployed, the grand mapping in the permanent state maps everything to zero. Moreover, the permanent state contains a value called the array seed.
When the program is deployed, the initial permanent state associates `balances` to one, and the array seed is two. In general, when a contract contains `n` mappings, the initial permanent state associates these mappings to `1`, `2`, ..., `n`. Moreover, the initial permanent state has the array seed `n + 1`.
When the evaluation point is an assignment to a mapping `m[idx0][idx1]...[idx_k] = V`, the program looks up the annotating function for `m[idx0][idx1]...[idx_k - 1]`. If the annotating function does not map this part to anything, `m[idx0][idx1]...[idx_k - 1]` becomes the evaluation point. Otherwise, if the annotating function does not map `idx_k` to anything, `idx_k` becomes the evaluation point. Otherwise, if the annotating function does not map `V` to anything, `V` becomes the evaluation point. Otherwise, when all of these are mapped to some value, the grand mapping is updated to map the evaluation of `m[idx0]...[idx_k - 1]` and `idx_k` into the evaluation of `V`, and the evaluation point advances from the assignment sentence.
When the evaluation point is a mapping lookup `m[idx]`, the program looks up the annotating function for `m`. If the annotating function does not map `m` to anything, `m` becomes the evaluation point.
Otherwise, if the annotating function maps `m` to zero, the program assigns a seed to `m` (see below for what it is for a program to assign a seed to `m`).
Otherwise, if the annotating function does not map `idx` to anything, the evaluation point becomes `idx`.
Otherwise, the annotating function is updated to map `m[idx]` to `M(<<m>>, <<idx>>)` where `<<m>>` and `<<idx>>` are the values that the annotation function returns for `m` and `idx`, and the evaluation point is set to the surrounding expression or sentence.
When the program assigns a new array seed to `m[idx]`, the grand mapping function is updated so that `M(<<m>>, <<idx>>)` is the array seed, where `<<m>>` and `<<idx>>` represents the values that the annotation function maps `m` and `idx` into. Then, the array seed is incremented. When the annotation function does not map `m` or `idx` to any value, the Bamboo compiler is broken.
================================================
FILE: doc/spec.tex
================================================
\documentclass{book}
\usepackage{stmaryrd}
\usepackage{amsmath}
\newcommand{\todo}[1]{\underline{TODO: {#1}}}
\newcommand{\sem}[1]{\llbracket{#1}\rrbracket}
\newcommand{\evalE}[1]{E_\mathrm{e}\left({#1}\right)}
\newcommand{\evalS}[1]{E_\mathrm{s}\left({#1}\right)}
\newcommand{\expressionsentence}[1]{\mathsf{void}={#1}\mathsf{;}}
\title{Bamboo Specification---An Early Draft}
\begin{document}
\maketitle
This specification contains some exercises. Please try to solve them at least mentally. Your solutions are welcome at \texttt{https://gitter.im/bbo-dev/Lobby}. \todo{use url}
\chapter{Preliminaries}
\section{What Qualifies a Bamboo Implementation}
\ldots A Bamboo compiler can refuse to compile certain valid programs.
\section{Notations}
$v \in A$ says $v$ is an element of a set~$A$.
\chapter{Syntax}
\section{Keywords}
\newcommand{\abort}{\text{\texttt{abort;}}}
\newcommand{\true}{\text{\texttt{true}}}
\newcommand{\false}{\text{\texttt{false}}}
\newcommand{\msgsender}{\text{\texttt{msg.sender}}}
\newcommand{\msgvalue}{\text{\texttt{msg.value}}}
\newcommand{\this}{\text{\texttt{this}}}
\newcommand{\now}{\text{\texttt{now}}}
\newcommand{\paren}[1]{\mathtt{(}{#1}\mathtt{)}}
\newcommand{\logicalAnd}[2]{{#1}\mathbin{\text{\texttt{\&\&}}{#2}}}
\newcommand{\logicalNot}[1]{\mathop{\text{\texttt{not}}}{#1}}
\newcommand{\balance}[1]{\text{\texttt{balance}}\mathtt{(}{#1}\mathtt{)}}
\newcommand{\arrayAccess}[2]{{#1}[{#2}]}
\newcommand{\lt}[2]{{#1} \mathop{\text{\texttt{<}}} {#2}}
\newcommand{\gt}[2]{{#1} \mathop{\text{\texttt{>}}} {#2}}
\newcommand{\eq}[2]{{#1} \mathop{\text{\texttt{==}}} {#2}}
\newcommand{\notEq}[2]{{#1} \mathop{\text{\texttt{!=}}} {#2}}
The following sequences of characters are \textit{keywords}.
\begin{itemize}
\item $\true$
\item $\false$
\item $\this$
\item $\now$
\item \texttt{not}
\item \texttt{contract}
\item \texttt{default}
\item \texttt{case}
\item \texttt{abort}
\item \texttt{uint8}
\item \texttt{uint256}
\item \texttt{bytes32}
\item \texttt{address}
\item \texttt{bool}
\item \texttt{if}
\item \texttt{else}
\item \texttt{then}
\item \texttt{become}
\item \texttt{return}
\item \texttt{deploy}
\item \texttt{with}
\item \texttt{reentrance}
\item \texttt{selfdestruct}
\item \texttt{block}
\item \texttt{void}
\item \texttt{event}
\item \texttt{log}
\item \texttt{indexed}
\end{itemize}
\todo{Use a maththm like environment for exercises.}
Exercise: which of the following are keywords?
\begin{enumerate}
\item \texttt{True}
\item \texttt{true}
\end{enumerate}
\section{Identifier}
An \textit{identifier} is a sequence of characters that matches the following regular expression (but is not a keyword):
\begin{verbatim}
['a'-'z' 'A'-'Z' '_'] ['a'-'z' 'A'-'Z' '0'-'9' '_']*
\end{verbatim}
\todo{define identifier}
Exercise: which of the following are identifiers? \\
\todo{complete}
\section{Syntactic Types}
The following sequences of characters are \textit{syntactic types}.
\begin{itemize}
\item \texttt{void}
\item \texttt{uint256}
\item \texttt{bool}
\item \texttt{uint8}
\item \texttt{bytes32}
\item \texttt{address}
\item \texttt{mapping } $T$ \texttt{=>} $T'$ when $T$ and $T'$ are syntactic types
\item any identifier except those listed above.
\end{itemize}
Every syntactic type except \texttt{void} is a \textit{non-\texttt{void} syntactic type}.
Exercise: which of the following is true?
\begin{enumerate}
\item \texttt{uint256} is the set of integers at least zero and at most $2^{256} - 1$.
\item \texttt{uint256} is the set of 256-bit words.
\item none of the above.
\end{enumerate}
\section{Expressions}
A \textit{message-info} is a value-info followed by a reentrance-info.
A \textit{case-call-expression} looks like
\[
e . c (e_1, \ldots, e_n)\ m
\]
with $e$ and $e_i$ ($1 \le i \le n$) being expressions and $m$ a message-info.
A \textit{call-expression} is either a case-call-expression or a default-call-expression.
A \textit{deploy-expression} looks
\[
\text{\texttt{deploy}}\ i(e_1,\ldots,e_n)\ m
\]
with $i$ being an identifier, $e_i$ ($1 \le i \le n$) an expression and $m$ a message-info.
\textit{Expressions} are inductively defined as follows.
\begin{itemize}
\item $\true$ is an expression.
\item $\false$ is an expression.
\item $\msgsender$ is an expression.
\item $\msgvalue$ is an expression.
\item $\this$ is an expression.
\item $\now$ is an expression.
\item An identifier is an expression.
\item When $e$ is an expression, $\paren{e}$ is an expression.
\item When $e$ is an expression, $\logicalNot{e}$ is an expression.
\item When $e$ is an expression, $\balance{e}$ is an expression.
\item A deploy-expression is an expression.
\item A call-expression is an expression.
\item AddressExp? What is an AddressExp?
\item When $e_0$ and $e_1$ are expressions, the following are expressions
\begin{itemize}
\item $\logicalAnd{e_0}{e_1}$
\item $\lt{e_0}{e_1}$
\item $\gt{e_0}{e_1}$
\item $\notEq{e_0}{e_1}$
\item $\eq{e_0}{e_1}$
\item $\arrayAccess{e_0}{e_1}$
\item $e_0 + e_1$
\item $e_0 - e_1$
\item $e_0 \times e_1$
\end{itemize}
\end{itemize}
Exercise: prove that \texttt{99a} is not an expression.
\section{Sentences}
A \textit{return sentence} looks
\[
\texttt{return}\, e_0 \,\texttt{then}\, \texttt{become}\, i(e_1,\ldots,e_n);
\]
with $i$ being an identifier and $e_i$ ($0 \le i \le n$) an expression.
An \textit{assignment sentence} looks
\[
l = e;
\]
with $l$ being a left-expression and $e$ an expression.
A \textit{variable initialization sentence} looks
\[
t i = e;
\]
with $t$ being a type, $i$ and identifier and $e$ an expression.
An \textit{expression sentence} looks
\[
\texttt{void}\, = \,e;
\]
with $e$ being an expression.
An \textit{if sentence} looks
\[
\texttt{if}\, (e)\, B
\]
with $e$ being an expression and $B$ either a block or a sentence (this forms a mutual induction together with the definition of sentences).
An \textit{if-then-else sentence} is looks
\[
\texttt{if}\, (e)\, B_0 \,\texttt{else}\, B_1
\]
with $e$ being an expression and each $B_i$ either a block or a sentence (this forms a mutual induction together with the definition of sentences).
A \textit{logging sentence} looks
\[
\texttt{log}\,i(e_1, \ldots, e_n)
\]
where $n \ge 0$. Each $e_j$ is an expression. $i$ is an identifier.
A \textit{selfdestruct sentence} looks
\[
\texttt{selfdestruct}\, e;
\]
with $e$ being an expression.
\textit{Sentences} are inductively defined as follows.
\begin{itemize}
\item $\abort$ is a sentence.
\item a return sentence is a sentence.
\item an assignment sentnece is a sentence.
\item a variable initialization sentence is a sentence.
\item an expression sentence is a sentence.
\item an if sentence is a sentence.
\item an if-then-else sentence is a sentence.
\item a logging sentence is a sentence.
\item a self-destruct sentence is a sentence.
\end{itemize}
\section{Blocks}
A \textit{block} is a possibly empty sequence of stentences surrounded by \texttt{\{} and \texttt{\}}.
\todo{talk about whitespaces, perhaps.}
\section{Cases}
A \textit{case header} is either a default case header or a named case header.
A \textit{case} is a case header followed by a block.
\section{Contract Headers}
A \textit{contract header} looks
\[
\mathtt{contract} i(t_1 i_1, \ldots, t_n i_n);
\]
where $i$ and $i_j$ ($1 \le j \le n$) are identifiers, $t_j$ ($1 \le j \le n$) are syntactic types.
\section{Contracts}
A \textit{contract} is a contract header followed by a \texttt{\{}, some (possibly no) cases and a \texttt{\}}.
\subsection{Contract's Signature}
$(\mathtt{auction}, [\mathtt{address}, \mathtt{uint256}, \mathtt{address}, \mathtt{uint256}])$.
Exercise: what is the signature of the following contract?
\todo{complete the question}
\subsection{Contract Body}
A \textit{contract body} is a possibly empty sequence of cases surrounded by \texttt{\{} and \texttt{\}}.
\subsection{Contract Definitions}
A \textit{contract definition} is a contract header followed by a contract body.
\section{Event Declarations}
An \textit{event declaration} looks like
\[
i(e_1, \ldots, e_n);
\]
where $n \ge 0$, each $e_j$ is an event argument, and $i$ is an identifier.
\section{Program}
A \textit{program} is a possibly empty sequence of contract definitions and event declarations.
\chapter{Semantics}
\section{Notations}
\todo{describe $\in$}
\todo{describe pi}
\section{States}
\subsection{Values}
A \textit{value} is a 256-bit word.
We pick something called $\bot$ (pronounced ``bottom'') which is not a value. The choice should not affect the meaning of a Bamboo program.
(We might specify a set of values for each syntactic type in the future.)
\subsection{A Contract's States}
A contract has \textit{states}.
When a contract has a signature $(x, [T_1, T_2, \ldots, T_n])$ ($n \ge 0$),
the set of the states of the contract~$C$ is
$[[C]] \equiv \Pi_{i = 0}^{n} \sem{T_i}$.
\subsection{A Program's Account States}
A program determines a set of \textit{account states}.
A program contains contract definitions $C_1, \ldots, C_n$ ($n \ge 0$),
disjoint union of $[[C_i]]$ ($1 \le i \le n$).
\section{Dynamics}
\subsection{Variable Environment}
A \textit{variable environment} is a partial map that takes identifiers and may or may not return a value. When a variable environment $\sigma$ maps and identifier~$i$ to a value~$v$, we write
\[
\sigma(i) = v
\]
\subsection{Current Call}
A \textit{current call} $c = (c_\mathrm{s}, c_\mathrm{v}, c_\mathrm{t})$ is a tuple of
\begin{itemize}
\item a value $c_\mathrm{s}$ called the \textit{sender},
\item a value $c_\mathrm{v}$ called the \textit{transferred amount} and
\item a value $c_\mathrm{t}$ called the \textit{timestamp}.
\end{itemize}
\subsection{World Oracle}
\subsubsection{Call Queries}
\subsubsection{Create Queries}
\subsubsection{Balance Queries}
\subsection{Timestamp query}
\newcommand{\timestampQuery}{\text{\texttt{timestamp?}}}
The time stamp query~$\timestampQuery$ is something different from any query that appears above. Apart from that, $\timestampQuery$ can be anything, and the behavior of Bamboo programs should not be affected by the concrete choice of $\timestampQuery$ (with some adaptations on world oracles).
\subsection{Current Account Query}
\newcommand{\thisQuery}[0]{\text{\texttt{this?}}}
The current account query~$\thisQuery$ is something different from any query that appears above.
\subsection{Sender Query}
\newcommand{\senderQuery}{\text{\texttt{sender?}}}
The sender query~$\senderQuery$ is something different from any query that appears above.
\subsection{Value Query}
\newcommand{\valueQuery}{\text{\texttt{value?}}}
The value query~$\valueQuery$ is something different from any query that appears above.
\subsubsection{World Oracle}
Call queries, create queries, \todo{fill in} are \textit{oracle queries}.
A \textit{world oracle} is defined coinductively as a function that takes an oracle query and returns a pair of a value and a world oracle.
When a world oracle~$w$ takes a query~$q$ and returns a pair of a value~$v$ and a world oracle~$w'$, we write $w(q) = (v, w')$.
\todo{Add a possibility that the world oracle calls into the program again.}
\subsection{Evaluation of an Expression}
The evaluation for expressions takes
\begin{itemize}
\item an expression,
\item a current call,
\item a world oracle and
\item a variable environment.
\end{itemize}
It returns
\begin{itemize}
\item a value or $\bot$ and
\item a world oracle
\end{itemize}
\todo{say it's inductively defined over the definition of expressions}.
\subsubsection{Evaluation of Literals}
\textit{Literals} are those keywords whose evaluation is defined below.
\begin{itemize}
\item $\evalE{\boxed{\true}, c, w, \sigma} := (1, w)$
\item $\evalE{\boxed{\false}, c, w, \sigma} := (0, w)$
\item $\evalE{\boxed{\now}, c, w, \sigma} := w(\timestampQuery)$
\item $\evalE{\boxed{\this}, c, w, \sigma} := w(\thisQuery)$
\item $\evalE{\boxed{\msgsender}, c, w, \sigma} := w(\senderQuery)$
\item $\evalE{\boxed{\msgvalue}, c, w, \sigma} := w(\valueQuery)$
\end{itemize}
balance(x) sends a balance query on the world oracle.
\subsubsection{Evaluation of an Identifier}
An identifier~$i$ is evaluated as follows:
\[
\evalE{\boxed{i}, c, w, \sigma} := (\sigma(i), w)
\]
Note that $\sigma(i)$ can be $\bot$.
\subsubsection{Evaluation of a new-expression}
\todo{Consider new-expressions with nontrivial continuation later. That requires an interaction between the program and the world oracle. }
\subsubsection{Evaluation of a call-expression}
\todo{Consider call-expressions with nontrivial continuation later. That requires an interaction between the program and the world oracle. }
\subsubsection{Evaluation of Binary Operators}
\[
\evalE{\boxed{\logicalAnd{e_0}{e_1}}, c, w, \sigma} :=
\begin{cases}
(v_0, w_0) & \text{if}\ v_0 = 0\ \text{or}\ v_0 = \bot \\
(v_1, w_1) & \text{otherwise}
\end{cases}
\]
where
\[
\evalE{\boxed{e_0}, c, w, \sigma} = (v_0, w_0)
\]
and
\[
\evalE{\boxed{e_1}, c, w_0, \sigma} = (v_1, w_1)
\]
\[
\evalE{\boxed{\lt{e_0}{e_1}}, c, w, \sigma} :=
\begin{cases}
(1, w_0) &\text{if}\ v_0 \neq \bot, v_1 \neq\bot\ \text{and}\ v_0 < v_1 \\
(0, w_0) &\text{if}\ v_0 \neq \bot, v_1 \neq\bot\ \text{and}\ v_0 \ge v_1 \\
(\bot, w) &\text{if}\ v_0 = \bot \ \text{or}\ v_1 = \bot
\end{cases}
\]
where
\[
\evalE{\boxed{e_1}, c, w, \sigma} = (v_1, w_1)
\]
and
\[
\evalE{\boxed{e_0}, c, w, \sigma} = (v_0, w_0)
\]
\[
\evalE{\boxed{\arrayAccess{e_0}{e_1}}, c, w, \sigma, M} :=
(w_0, M(v_0, v_1))
\]
where
\[
\evalE{\boxed{e_1}, c, w, \sigma, M} = (v_1, w_1)
\]
and
\[
\evalE{\boxed{e_0}, c, w_1, \sigma, M} = (v_0, w_0)
\]
\subsection{Evaluation of a Sentence}
The evaluation function for sentences take
\begin{itemize}
\item a sentence,
\item a current call,
\item a variable environment and
\item a world oracle
\end{itemize}
and returns
\begin{itemize}
\item a variable environment,
\item a world oracle
\item and optionally an account state.
\end{itemize}
\todo{Show two forms of equations: one without an account state, the other with an account state.}
\subsubsection{Evaluation of an Expression Sentence}
\[
\evalS{\boxed{\expressionsentence{e}}, c, \sigma, w} := (\sigma', w')
\]
where
\[
\evalE{\boxed{e}, c, \sigma, w} = (v, \sigma', w')
\]
\subsection{Evaluation of a Case}
The evaluation function of a case takes
\begin{itemize}
\item A contract state
\item a world oracle
\item a case call
\end{itemize}
and returns
\begin{itemize}
\item an account state
\item a world oracle
\end{itemize}
\subsection{Evaluation of a Contract}
The evaluation function of a contract takes
\begin{itemize}
\item A contract state
\item a world oracle
\item a contract call
\end{itemize}
and returns
\begin{itemize}
\item An account state
\item a world oracle
\end{itemize}
\subsection{Evaluation of a Program}
The evaluation function of a program takes
\begin{itemize}
\item an account state
\item a world oracle
\item a program call
\end{itemize}
and returns
\begin{itemize}
\item an account state
\item a world oracle
\end{itemize}
\section{Account Initialization}
\subsection{Account Deployment Query}
\subsection{Initial Variable Environment}
\chapter{Connection to EVM}
\section{Bamboo Account State as an EVM Account State}
\section{Queries as EVM instructions}
\end{document}
================================================
FILE: doc/testing-bytecode.md
================================================
Testing the Bytecode from bbo
=============================
Getting a Bytecode
------------------
After following the [readme](../README.md),
```
./lib/bs/native/bamboo.native < src/parse/examples/006auction_first_case.bbo
```
should produce something like
```
0x60606040527f0000000000000000000000000000000000000000000000000000000000000060807f0000000000000000000000000000000000000000000000000000000000000040805180920190528180380382397f00000000000000000000000000000000000000000000000000000000000000025b82157f000000000000000000000000000000000000000000000000000000000000012c57815181557f0000000000000000000000000000000000000000000000000000000000000020909203917f000000000000000000000000000000000000000000000000000000000000000101907f000000000000000000000000000000000000000000000000000000000000002001907f0000000000000000000000000000000000000000000000000000000000000076565b5050506001547f000000000000000000000000000000000000000000000000000000000000015957600180555b600154806300000005557f0000000000000000000000000000000000000000000000000000000000000001016001557f00000000000000000000000000000000000000000000000000000000000000237f0000000000000000000000000000000000000000000000000000000000000000557f0000000000000000000000000000000000000000000000000000000000000414807f000000000000000000000000000000000000000000000000000000000000004080518092019052817f000000000000000000000000000000000000000000000000000000000000023b8239f37f000000000000000000000000000000000000000000000000000000000000000054565b60606040527f00000000000000000000000000000000000000000000000000000000000000003560e060020a9004507f0000000000000000000000000000000000000000000000000000000000000075565b7f00000000000000000000000000000000000000000000000000000000000000237f000000000000000000000000000000000000000000000000000000000000000055347f0000000000000000000000000000000000000000000000000000000000000005547f0000000000000000000000000000000000000000000000000000000000000003547f0000000000000000000000000000000000000000000000000000000000000002547f0000000000000000000000000000000000000000000000000000000000000002557f0000000000000000000000000000000000000000000000000000000000000003557f0000000000000000000000000000000000000000000000000000000000000005557f00000000000000000000000000000000000000000000000000000000000000045560016020807f000000000000000000000000000000000000000000000000000000000000004080518092019052918152f360606040527f0000000000000000000000000000000000000000000000000000000000000060807f0000000000000000000000000000000000000000000000000000000000000040805180920190528180380382397f00000000000000000000000000000000000000000000000000000000000000025b82157f000000000000000000000000000000000000000000000000000000000000012c57815181557f0000000000000000000000000000000000000000000000000000000000000020909203917f000000000000000000000000000000000000000000000000000000000000000101907f000000000000000000000000000000000000000000000000000000000000002001907f0000000000000000000000000000000000000000000000000000000000000076565b5050506001547f000000000000000000000000000000000000000000000000000000000000015957600180555b600154806300000005557f0000000000000000000000000000000000000000000000000000000000000001016001557f00000000000000000000000000000000000000000000000000000000000000237f0000000000000000000000000000000000000000000000000000000000000000557f0000000000000000000000000000000000000000000000000000000000000414807f000000000000000000000000000000000000000000000000000000000000004080518092019052817f000000000000000000000000000000000000000000000000000000000000023b8239f3
```
Append Arguments
----------------
The [source](../src/parse/examples/006auction_first_case.bbo) shows the signature of the contract.
```
contract auction
(address _beneficiary
,uint _bidding_time
,bool[address] _bids
,uint _highest_bid)
```
Of the four arguments, the three non-array arguments `_beneficiary`, `_bidding_time` and `_highest_bid` need to be specified. Each of them take 32 bytes (even when it's an address that requires just 20 bytes). Append the arguments to the bytecode, and you will get something like
```
0x60606040527f0000000000000000000000000000000000000000000000000000000000000060807f0000000000000000000000000000000000000000000000000000000000000040805180920190528180380382397f00000000000000000000000000000000000000000000000000000000000000025b82157f000000000000000000000000000000000000000000000000000000000000012c57815181557f0000000000000000000000000000000000000000000000000000000000000020909203917f000000000000000000000000000000000000000000000000000000000000000101907f000000000000000000000000000000000000000000000000000000000000002001907f0000000000000000000000000000000000000000000000000000000000000076565b5050506001547f000000000000000000000000000000000000000000000000000000000000015957600180555b600154806300000005557f0000000000000000000000000000000000000000000000000000000000000001016001557f00000000000000000000000000000000000000000000000000000000000000237f0000000000000000000000000000000000000000000000000000000000000000557f0000000000000000000000000000000000000000000000000000000000000414807f000000000000000000000000000000000000000000000000000000000000004080518092019052817f000000000000000000000000000000000000000000000000000000000000023b8239f37f000000000000000000000000000000000000000000000000000000000000000054565b60606040527f00000000000000000000000000000000000000000000000000000000000000003560e060020a9004507f0000000000000000000000000000000000000000000000000000000000000075565b7f00000000000000000000000000000000000000000000000000000000000000237f000000000000000000000000000000000000000000000000000000000000000055347f0000000000000000000000000000000000000000000000000000000000000005547f0000000000000000000000000000000000000000000000000000000000000003547f0000000000000000000000000000000000000000000000000000000000000002547f0000000000000000000000000000000000000000000000000000000000000002557f0000000000000000000000000000000000000000000000000000000000000003557f0000000000000000000000000000000000000000000000000000000000000005557f00000000000000000000000000000000000000000000000000000000000000045560016020807f000000000000000000000000000000000000000000000000000000000000004080518092019052918152f360606040527f0000000000000000000000000000000000000000000000000000000000000060807f0000000000000000000000000000000000000000000000000000000000000040805180920190528180380382397f00000000000000000000000000000000000000000000000000000000000000025b82157f000000000000000000000000000000000000000000000000000000000000012c57815181557f0000000000000000000000000000000000000000000000000000000000000020909203917f000000000000000000000000000000000000000000000000000000000000000101907f000000000000000000000000000000000000000000000000000000000000002001907f0000000000000000000000000000000000000000000000000000000000000076565b5050506001547f000000000000000000000000000000000000000000000000000000000000015957600180555b600154806300000005557f0000000000000000000000000000000000000000000000000000000000000001016001557f00000000000000000000000000000000000000000000000000000000000000237f0000000000000000000000000000000000000000000000000000000000000000557f0000000000000000000000000000000000000000000000000000000000000414807f000000000000000000000000000000000000000000000000000000000000004080518092019052817f000000000000000000000000000000000000000000000000000000000000023b8239f30x60606040527f0000000000000000000000000000000000000000000000000000000000000060807f0000000000000000000000000000000000000000000000000000000000000040805180920190528180380382397f00000000000000000000000000000000000000000000000000000000000000025b82157f000000000000000000000000000000000000000000000000000000000000012c57815181557f0000000000000000000000000000000000000000000000000000000000000020909203917f000000000000000000000000000000000000000000000000000000000000000101907f000000000000000000000000000000000000000000000000000000000000002001907f0000000000000000000000000000000000000000000000000000000000000076565b5050506001547f000000000000000000000000000000000000000000000000000000000000015957600180555b600154806300000005557f0000000000000000000000000000000000000000000000000000000000000001016001557f00000000000000000000000000000000000000000000000000000000000000237f0000000000000000000000000000000000000000000000000000000000000000557f0000000000000000000000000000000000000000000000000000000000000414807f000000000000000000000000000000000000000000000000000000000000004080518092019052817f000000000000000000000000000000000000000000000000000000000000023b8239f37f000000000000000000000000000000000000000000000000000000000000000054565b60606040527f00000000000000000000000000000000000000000000000000000000000000003560e060020a9004507f0000000000000000000000000000000000000000000000000000000000000075565b7f00000000000000000000000000000000000000000000000000000000000000237f000000000000000000000000000000000000000000000000000000000000000055347f0000000000000000000000000000000000000000000000000000000000000005547f0000000000000000000000000000000000000000000000000000000000000003547f0000000000000000000000000000000000000000000000000000000000000002547f0000000000000000000000000000000000000000000000000000000000000002557f0000000000000000000000000000000000000000000000000000000000000003557f0000000000000000000000000000000000000000000000000000000000000005557f00000000000000000000000000000000000000000000000000000000000000045560016020807f000000000000000000000000000000000000000000000000000000000000004080518092019052918152f360606040527f0000000000000000000000000000000000000000000000000000000000000060807f0000000000000000000000000000000000000000000000000000000000000040805180920190528180380382397f00000000000000000000000000000000000000000000000000000000000000025b82157f000000000000000000000000000000000000000000000000000000000000012c57815181557f0000000000000000000000000000000000000000000000000000000000000020909203917f000000000000000000000000000000000000000000000000000000000000000101907f000000000000000000000000000000000000000000000000000000000000002001907f0000000000000000000000000000000000000000000000000000000000000076565b5050506001547f000000000000000000000000000000000000000000000000000000000000015957600180555b600154806300000005557f0000000000000000000000000000000000000000000000000000000000000001016001557f00000000000000000000000000000000000000000000000000000000000000237f0000000000000000000000000000000000000000000000000000000000000000557f0000000000000000000000000000000000000000000000000000000000000414807f000000000000000000000000000000000000000000000000000000000000004080518092019052817f000000000000000000000000000000000000000000000000000000000000023b8239f3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000
```
In this hex notation, 32 bytes are represented by 64 characters.
Testing the Contract on a Testnet
---------------------------------
Checkout [go-ethereum](https://github.com/ethereum/go-ethereum) and build it.
```
> git clone https://github.com/ethereum/go-ethereum
> cd go-ethereum
> make
```
You might need to install [Go](https://golang.org).
And you can run something like
```
build/bin/geth --testnet console --fast --bootnodes "enode://20c9ad97c081d63397d7b685a412227a40e23c8bdc6688c6f37e97cfbc22d2b4d1db1510d8f61e6a8866ad7f0e17c02b14182d37ea7c3c8b9c2683aeb6b733a1@52.169.14.227:30303,enode://6ce05930c72abc632c58e2e4324f7c7ea478cec0ed4fa2528982cf34483094e9cbc9216e7aa349691242576d552a2a56aaeae426c5303ded677ce455ba1acd9d@13.84.180.240:30303"
```
Below, everything is in the console of `geth`.
Check if you already have an account:
```
> eth.accounts
```
If you have no accounts, create one:
```
> personal.newAccount()
```
to create an account.
```
miner.start(2)
```
to start mining. Leave the machine for half an hour.
If
```
> eth.getBalance(eth.accounts[0])
```
shows some non-zero number, you are ready to continue.
I chose to perform the concatenation in the `geth` console.
```
var data = "0x60606040527f0000000000000000000000000000000000000000000000000000000000000060807f0000000000000000000000000000000000000000000000000000000000000040805180920190528180380382397f00000000000000000000000000000000000000000000000000000000000000025b82157f000000000000000000000000000000000000000000000000000000000000012c57815181557f0000000000000000000000000000000000000000000000000000000000000020909203917f000000000000000000000000000000000000000000000000000000000000000101907f000000000000000000000000000000000000000000000000000000000000002001907f0000000000000000000000000000000000000000000000000000000000000076565b5050506001547f000000000000000000000000000000000000000000000000000000000000015957600180555b600154806300000005557f0000000000000000000000000000000000000000000000000000000000000001016001557f00000000000000000000000000000000000000000000000000000000000000237f0000000000000000000000000000000000000000000000000000000000000000557f0000000000000000000000000000000000000000000000000000000000000414807f000000000000000000000000000000000000000000000000000000000000004080518092019052817f000000000000000000000000000000000000000000000000000000000000023b8239f37f000000000000000000000000000000000000000000000000000000000000000054565b60606040527f00000000000000000000000000000000000000000000000000000000000000003560e060020a9004507f0000000000000000000000000000000000000000000000000000000000000075565b7f00000000000000000000000000000000000000000000000000000000000000237f000000000000000000000000000000000000000000000000000000000000000055347f0000000000000000000000000000000000000000000000000000000000000005547f0000000000000000000000000000000000000000000000000000000000000003547f0000000000000000000000000000000000000000000000000000000000000002547f0000000000000000000000000000000000000000000000000000000000000002557f0000000000000000000000000000000000000000000000000000000000000003557f0000000000000000000000000000000000000000000000000000000000000005557f00000000000000000000000000000000000000000000000000000000000000045560016020807f000000000000000000000000000000000000000000000000000000000000004080518092019052918152f360606040527f0000000000000000000000000000000000000000000000000000000000000060807f0000000000000000000000000000000000000000000000000000000000000040805180920190528180380382397f00000000000000000000000000000000000000000000000000000000000000025b82157f000000000000000000000000000000000000000000000000000000000000012c57815181557f0000000000000000000000000000000000000000000000000000000000000020909203917f000000000000000000000000000000000000000000000000000000000000000101907f000000000000000000000000000000000000000000000000000000000000002001907f0000000000000000000000000000000000000000000000000000000000000076565b5050506001547f000000000000000000000000000000000000000000000000000000000000015957600180555b600154806300000005557f0000000000000000000000000000000000000000000000000000000000000001016001557f00000000000000000000000000000000000000000000000000000000000000237f0000000000000000000000000000000000000000000000000000000000000000557f0000000000000000000000000000000000000000000000000000000000000414807f000000000000000000000000000000000000000000000000000000000000004080518092019052817f000000000000000000000000000000000000000000000000000000000000023b8239f3"
```
```
var data = data+"0000000000000000000000000000000000000000000000000000000000000000"+"0000000000000000000000000000000000000000000000000000000400000020"+"0000000000000000000000000000000000000000000000000000000000000000"
```
Now I can deploy the contract.
```
var tx = eth.sendTransaction({from: eth.accounts[0], data: data, gas: 1000000})
```
After doing this, it takes some time until you see
```
> eth.getTransactionReceipt(tx)
{
blockHash: "0x21ad6127030275d8ec0e0e0c6291e4a9e4a571c00e961f88e385dedeae930487",
blockNumber: 1197013,
contractAddress: "0x56d9ffea1224a661fc63855994638efebbf2c92b",
cumulativeGasUsed: 382585,
from: "0xe64ae430b97ff403a194e214175c4144a82969f4",
gasUsed: 382585,
logs: [],
logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
root: "0xb50914b39a58ef18700766cb8f49753447dee0f70a01443b5a15479908940753",
to: null,
transactionHash: "0xd480e58ceed4e6f2950f45ba7eec1ac9068799d6a49ecc62db97f152da2d79cb",
transactionIndex: 0
}
```
And then, you can get the address of the deployed contract.
```
> var contract = eth.getTransactionReceipt(tx).contractAddress
```
Indeed, there is code.
```
> eth.getCode(contract)
"0x7f000000000000000000000000000000000000000000000000000000000000000054565b60606040527f00000000000000000000000000000000000000000000000000000000000000003560e060020a9004507f0000000000000000000000000000000000000000000000000000000000000075565b7f00000000000000000000000000000000000000000000000000000000000000237f000000000000000000000000000000000000000000000000000000000000000055347f0000000000000000000000000000000000000000000000000000000000000005547f0000000000000000000000000000000000000000000000000000000000000003547f0000000000000000000000000000000000000000000000000000000000000002547f0000000000000000000000000000000000000000000000000000000000000002557f0000000000000000000000000000000000000000000000000000000000000003557f0000000000000000000000000000000000000000000000000000000000000005557f00000000000000000000000000000000000000000000000000000000000000045560016020807f000000000000000000000000000000000000000000000000000000000000004080518092019052918152f360606040527f0000000000000000000000000000000000000000000000000000000000000060807f0000000000000000000000000000000000000000000000000000000000000040805180920190528180380382397f00000000000000000000000000000000000000000000000000000000000000025b82157f000000000000000000000000000000000000000000000000000000000000012c57815181557f0000000000000000000000000000000000000000000000000000000000000020909203917f000000000000000000000000000000000000000000000000000000000000000101907f000000000000000000000000000000000000000000000000000000000000002001907f0000000000000000000000000000000000000000000000000000000000000076565b5050506001547f000000000000000000000000000000000000000000000000000000000000015957600180555b600154806300000005557f0000000000000000000000000000000000000000000000000000000000000001016001557f00000000000000000000000000000000000000000000000000000000000000237f0000000000000000000000000000000000000000000000000000000000000000557f0000000000000000000000000000000000000000000000000000000000000414807f000000000000000000000000000000000000000000000000000000000000004080518092019052817f000000000000000000000000000000000000000000000000000000000000023b8239f3"
```
And the arguments are stored in a straight-forward way
```
> eth.getStorageAt(contract, 2)
"0x0000000000000000000000000000000000000000000000000000000000000000"
> eth.getStorageAt(contract, 3)
"0x0000000000000000000000000000000000000000000000000000000000000020"
> eth.getStorageAt(contract, 4)
"0x0000000000000000000000000000000000000000000000000000000000000000"
```
You can send another transaction to invoke the `default` case
```
eth.sendTransaction({from: eth.accounts[0], to: contract, data: "", value: 100})
```
After a while, you see that the storage has changed.
```
> eth.getStorageAt(contract, 4)
"0x0000000000000000000000000000000000000000000000000000000000000064"
```
================================================
FILE: doc/tutorial.md
================================================
# Bamboo 0.0.01 Tutorial
This document covers
* installation of the Bamboo compiler
* compilation and deployment of a Bamboo program
* interaction with the deployed Ethereum contract
## Installing the Bamboo compiler
Make sure OCaml 4.04 is installed
```
$ ocaml --version
The OCaml toplevel, version 4.04.2
```
If a newer version is installed get the old one [here](http://ocaml.org/releases/4.04.html)
The Bamboo compiler can be installed with the OCaml package manager `opam`.
If you don't have it yet, get `opam` by
* `apt-get install opam`
* `brew install opam`
* or one of [many other ways](https://opam.ocaml.org/doc/Install.html)
After installing `opam`, run `opam init` and follow the instructions.
When `opam` is ready, `opam install bamboo` gets you the Bamboo compiler.
```
$ bamboo --version
0.0.01
```
If anything goes wrong, poke @pirapira on [the Gitter channel](https://gitter.im/bbo-dev).
## Compiling Bamboo code
Let's deploy [this ERC20 contract](https://github.com/pirapira/bamboo/blob/master/src/parse/examples/01b_erc20better.bbo) on the Ropsten test network.
```
$ wget https://raw.githubusercontent.com/pirapira/bamboo/master/src/parse/examples/01b_erc20better.bbo
```
will get you a file `01b_erc20better.bbo`. You can have a look now, but I'll explain the contents when we interact with the contract.
Now,
```
$ bamboo < 01b_erc20better.bbo > compiled.hex
```
should store something in `compiled.hex` file. You can have a look. If you use it for anything serious, you should investigate `compiled.hex` here. Since we are just playing on the test network, we go ahead deploying the compiled code.
Also,
```
$ bamboo --abi < 01b_erc20better.bbo > abi.json
```
will get you a JSON file `abi.json` that describes the interface of this Ethereum contract.
## Deploying on the Ropsten test network
The Ropsten network is a test network for Ethereum. The balances and accounts are cleared sometimes. In this tutorial we deploy the code to Ropsten.
### Connecting go-ethereum to the Ropsten network
We use `go-ethereum`. [Install go-ethereum](https://ethereum.github.io/go-ethereum/install/) somehow and run
```
$ build/bin/geth console --testnet --fast --bootnodes "enode://20c9ad97c081d63397d7b685a412227a40e23c8bdc6688c6f37e97cfbc22d2b4d1db1510d8f61e6a8866ad7f0e17c02b14182d37ea7c3c8b9c2683aeb6b733a1@52.169.14.227:30303,enode://6ce05930c72abc632c58e2e4324f7c7ea478cec0ed4fa2528982cf34483094e9cbc9216e7aa349691242576d552a2a56aaeae426c5303ded677ce455ba1acd9d@13.84.180.240:30303"
```
When you are still seeing something like
```
INFO [08-02|14:00:28] Imported new chain segment blocks=119 txs=324 mgas=130.952 elapsed=8.008s mgasps=16.352 number=1375400 hash=cd3c3f…a39ed3
```
with `blocks=119` or some big numbers, `go-ethereum` has not synced yet.
When it's synced, you will be seeing `blocks=1`
```
INFO [08-02|14:22:16] Imported new chain segment blocks=1 txs=0 mgas=0.000 elapsed=13.958ms mgasps=0.000 number=1417137 hash=8603a5…1de724
```
### Creating an account
For deploying code on the Ropsten network, you need an account. If you don't have one, you can create it by typing
```
> personal.newAccount()
```
into the geth console.
### Earning some Ropsten test Ether
For deploying code on the Ropsten network, you also need Ropsten Ether. You can either mine it, or get it from somebody else.
You can check your first account's balance by
```
> eth.getBalance(eth.accounts[0])
2991644430772416863
```
in the geth console. If it shows zero, there are ways to earn Ropsten Ether.
#### Option 1. mining
You can start mining Ropsten Ether
```
> miner.start(2)
```
Usually you will get some Ropsten Ether within some hours.
When you have some non-zero number, you can stop the mining by
```
> miner.stop()
```
on the geth console.
#### Option 2. asking
If you know somebody with Ropsten Ether, you can tell them your address created above, and ask them to send you some Ropsten Ether.
You can find your address by typing
```
> eth.accounts[0]
```
### Preparing the code and the ABI
Now you can give a name to the hex code in `compiled.hex`.
```
> var code = "0x60606040527f0000000000000000000000000000000000000000000000000000000000000020806040805180920190528180380382397f0000000000000000000000000000000000000000000000000000000000003dd13814156002577f00000000000000000000000000000000000000000000000000000000000000025b821563000000fc57815181557f0000000000000000000000000000000000000000000000000000000000000020909203917f000000000000000000000000000000000000000000000000000000000000000101907f00000000000000000000000000000000000000000000000000000000000000200190630000007e565b505050600154630000010d57600180555b6300000003630000014857600154806300000003557f0000000000000000000000000000000000000000000000000000000000000001016001555b6300000004630000018357600154806300000004557f0000000000000000000000000000000000000000000000000000000000000001016001555b7f00000000000000000000000000000000000000000000000000000000000000237f0000000000000000000000000000000000000000000000000000000000000000557f0000000000000000000000000000000000000000000000000000000000003b9a80604080518092019052817f00000000000000000000000000000000000000000000000000000000000002178239f37f000000000000000000000000000000000000000000000000000000000000000054565b60606040527f00000000000000000000000000000000000000000000000000000000000000003560e060020a9004507f0000000000000000000000000000000000000000000000000000000000000075565b7f000000000000000000000000000000000000000000000000000000000000000254307f000000000000000000000000000000000000000000000000000000000000000354807f000000000000000000000000000000000000000000000000000000000000012c57507f0000000000000000000000000000000000000000000000000000000000000003600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b6000526020526040600020557f000000000000000000000000000000000000000000000000000000000000032d7f0000000000000000000000000000000000000000000000000000000000000000557f000000000000000000000000000000000000000000000000000000000000000454807f000000000000000000000000000000000000000000000000000000000000020f57507f0000000000000000000000000000000000000000000000000000000000000004600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b7f000000000000000000000000000000000000000000000000000000000000000354807f00000000000000000000000000000000000000000000000000000000000002a357507f0000000000000000000000000000000000000000000000000000000000000003600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b7f0000000000000000000000000000000000000000000000000000000000000002547f0000000000000000000000000000000000000000000000000000000000000002557f0000000000000000000000000000000000000000000000000000000000000003557f000000000000000000000000000000000000000000000000000000000000000455005b60606040527f00000000000000000000000000000000000000000000000000000000000000003560e060020a9004806318160ddd147f00000000000000000000000000000000000000000000000000000000000004a857806370a08231147f00000000000000000000000000000000000000000000000000000000000006da578063a9059cbb147f0000000000000000000000000000000000000000000000000000000000000997578063095ea7b3147f00000000000000000000000000000000000000000000000000000000000012e8578063dd62ed3e147f000000000000000000000000000000000000000000000000000000000000178e57806323b872dd147f0000000000000000000000000000000000000000000000000000000000001b45578063d96a094a147f0000000000000000000000000000000000000000000000000000000000002867578063d79875eb147f000000000000000000000000000000000000000000000000000000000000301057506002565b63000000043614156000577f000000000000000000000000000000000000000000000000000000000000032d7f0000000000000000000000000000000000000000000000000000000000000000557f000000000000000000000000000000000000000000000000000000000000000454807f000000000000000000000000000000000000000000000000000000000000058a57507f0000000000000000000000000000000000000000000000000000000000000004600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b7f000000000000000000000000000000000000000000000000000000000000000354807f000000000000000000000000000000000000000000000000000000000000061e57507f0000000000000000000000000000000000000000000000000000000000000003600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b7f0000000000000000000000000000000000000000000000000000000000000002547f0000000000000000000000000000000000000000000000000000000000000002557f0000000000000000000000000000000000000000000000000000000000000003557f0000000000000000000000000000000000000000000000000000000000000004557f00000000000000000000000000000000000000000000000000000000000000025460208060408051809201905291825290f35b63000000243614156000577f000000000000000000000000000000000000000000000000000000000000032d7f0000000000000000000000000000000000000000000000000000000000000000557f000000000000000000000000000000000000000000000000000000000000000454807f00000000000000000000000000000000000000000000000000000000000007bc57507f0000000000000000000000000000000000000000000000000000000000000004600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b7f000000000000000000000000000000000000000000000000000000000000000354807f000000000000000000000000000000000000000000000000000000000000085057507f0000000000000000000000000000000000000000000000000000000000000003600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b7f0000000000000000000000000000000000000000000000000000000000000002547f0000000000000000000000000000000000000000000000000000000000000002557f0000000000000000000000000000000000000000000000000000000000000003557f000000000000000000000000000000000000000000000000000000000000000455630000001035606060020a90047f000000000000000000000000000000000000000000000000000000000000000354807f000000000000000000000000000000000000000000000000000000000000097957507f0000000000000000000000000000000000000000000000000000000000000003600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b60005260205260406000205460208060408051809201905291825290f35b6300000044361415600057630000002435337f000000000000000000000000000000000000000000000000000000000000000354807f0000000000000000000000000000000000000000000000000000000000000a3d57507f0000000000000000000000000000000000000000000000000000000000000003600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b60005260205260406000205410156300000a55576002565b630000001035606060020a90043314156300000c9857333363ddf252ad630000002435602080604080518092019052918252909060006000500190a37f000000000000000000000000000000000000000000000000000000000000032d7f0000000000000000000000000000000000000000000000000000000000000000557f000000000000000000000000000000000000000000000000000000000000000454807f0000000000000000000000000000000000000000000000000000000000000b6857507f0000000000000000000000000000000000000000000000000000000000000004600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b7f000000000000000000000000000000000000000000000000000000000000000354807f0000000000000000000000000000000000000000000000000000000000000bfc57507f0000000000000000000000000000000000000000000000000000000000000003600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b7f0000000000000000000000000000000000000000000000000000000000000002547f0000000000000000000000000000000000000000000000000000000000000002557f0000000000000000000000000000000000000000000000000000000000000003557f000000000000000000000000000000000000000000000000000000000000000455600160208060408051809201905291825290f35b630000002435337f000000000000000000000000000000000000000000000000000000000000000354807f0000000000000000000000000000000000000000000000000000000000000d3357507f0000000000000000000000000000000000000000000000000000000000000003600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b60005260205260406000205403337f000000000000000000000000000000000000000000000000000000000000000354807f0000000000000000000000000000000000000000000000000000000000000dd557507f0000000000000000000000000000000000000000000000000000000000000003600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b600052602052604060002055630000001035606060020a90047f000000000000000000000000000000000000000000000000000000000000000354807f0000000000000000000000000000000000000000000000000000000000000e8257507f0000000000000000000000000000000000000000000000000000000000000003600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b600052602052604060002054630000002435630000001035606060020a90047f000000000000000000000000000000000000000000000000000000000000000354807f0000000000000000000000000000000000000000000000000000000000000f3557507f0000000000000000000000000000000000000000000000000000000000000003600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b6000526020526040600020540110156300000f4e576002565b630000002435630000001035606060020a90047f000000000000000000000000000000000000000000000000000000000000000354807f0000000000000000000000000000000000000000000000000000000000000ff557507f0000000000000000000000000000000000000000000000000000000000000003600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b60005260205260406000205401630000001035606060020a90047f000000000000000000000000000000000000000000000000000000000000000354807f00000000000000000000000000000000000000000000000000000000000010a357507f0000000000000000000000000000000000000000000000000000000000000003600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b600052602052604060002055630000001035606060020a90043363ddf252ad630000002435602080604080518092019052918252909060006000500190a37f000000000000000000000000000000000000000000000000000000000000032d7f0000000000000000000000000000000000000000000000000000000000000000557f000000000000000000000000000000000000000000000000000000000000000454807f00000000000000000000000000000000000000000000000000000000000011b857507f0000000000000000000000000000000000000000000000000000000000000004600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b7f000000000000000000000000000000000000000000000000000000000000000354807f000000000000000000000000000000000000000000000000000000000000124c57507f0000000000000000000000000000000000000000000000000000000000000003600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b7f0000000000000000000000000000000000000000000000000000000000000002547f0000000000000000000000000000000000000000000000000000000000000002557f0000000000000000000000000000000000000000000000000000000000000003557f000000000000000000000000000000000000000000000000000000000000000455600160208060408051809201905291825290f35b6300000044361415600057630000002435337f000000000000000000000000000000000000000000000000000000000000000354807f000000000000000000000000000000000000000000000000000000000000138e57507f0000000000000000000000000000000000000000000000000000000000000003600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b600052602052604060002054101563000013a6576002565b630000001035606060020a900433141563000013c0576002565b630000002435630000001035606060020a9004337f000000000000000000000000000000000000000000000000000000000000000454807f000000000000000000000000000000000000000000000000000000000000146857507f0000000000000000000000000000000000000000000000000000000000000004600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b6000526020526040600020548063000015495750337f000000000000000000000000000000000000000000000000000000000000000454807f000000000000000000000000000000000000000000000000000000000000151157507f0000000000000000000000000000000000000000000000000000000000000004600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b6000526020526040600020600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b600052602052604060002055630000001035606060020a900433638c5be1e5630000002435602080604080518092019052918252909060006000500190a37f000000000000000000000000000000000000000000000000000000000000032d7f0000000000000000000000000000000000000000000000000000000000000000557f000000000000000000000000000000000000000000000000000000000000000454807f000000000000000000000000000000000000000000000000000000000000165e57507f0000000000000000000000000000000000000000000000000000000000000004600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b7f000000000000000000000000000000000000000000000000000000000000000354807f00000000000000000000000000000000000000000000000000000000000016f257507f0000000000000000000000000000000000000000000000000000000000000003600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b7f0000000000000000000000000000000000000000000000000000000000000002547f0000000000000000000000000000000000000000000000000000000000000002557f0000000000000000000000000000000000000000000000000000000000000003557f000000000000000000000000000000000000000000000000000000000000000455600160208060408051809201905291825290f35b63000000443614156000577f000000000000000000000000000000000000000000000000000000000000032d7f0000000000000000000000000000000000000000000000000000000000000000557f000000000000000000000000000000000000000000000000000000000000000454807f000000000000000000000000000000000000000000000000000000000000187057507f0000000000000000000000000000000000000000000000000000000000000004600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b7f000000000000000000000000000000000000000000000000000000000000000354807f000000000000000000000000000000000000000000000000000000000000190457507f0000000000000000000000000000000000000000000000000000000000000003600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b7f0000000000000000000000000000000000000000000000000000000000000002547f0000000000000000000000000000000000000000000000000000000000000002557f0000000000000000000000000000000000000000000000000000000000000003557f000000000000000000000000000000000000000000000000000000000000000455630000003035606060020a9004630000001035606060020a90047f000000000000000000000000000000000000000000000000000000000000000454807f0000000000000000000000000000000000000000000000000000000000001a3a57507f0000000000000000000000000000000000000000000000000000000000000004600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b600052602052604060002054806300001b275750630000001035606060020a90047f000000000000000000000000000000000000000000000000000000000000000454807f0000000000000000000000000000000000000000000000000000000000001aef57507f0000000000000000000000000000000000000000000000000000000000000004600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b6000526020526040600020600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b60005260205260406000205460208060408051809201905291825290f35b6300000064361415600057630000004435630000001035606060020a90047f000000000000000000000000000000000000000000000000000000000000000354807f0000000000000000000000000000000000000000000000000000000000001bf757507f0000000000000000000000000000000000000000000000000000000000000003600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b60005260205260406000205410156300001c0f576002565b63000000443533630000001035606060020a90047f000000000000000000000000000000000000000000000000000000000000000454807f0000000000000000000000000000000000000000000000000000000000001cb757507f0000000000000000000000000000000000000000000000000000000000000004600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b600052602052604060002054806300001da45750630000001035606060020a90047f000000000000000000000000000000000000000000000000000000000000000454807f0000000000000000000000000000000000000000000000000000000000001d6c57507f0000000000000000000000000000000000000000000000000000000000000004600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b6000526020526040600020600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b60005260205260406000205410156300001dbc576002565b630000003035606060020a9004630000001035606060020a90041415630000202357630000003035606060020a9004630000001035606060020a900463ddf252ad630000004435602080604080518092019052918252909060006000500190a37f000000000000000000000000000000000000000000000000000000000000032d7f0000000000000000000000000000000000000000000000000000000000000000557f000000000000000000000000000000000000000000000000000000000000000454807f0000000000000000000000000000000000000000000000000000000000001ef357507f0000000000000000000000000000000000000000000000000000000000000004600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b7f000000000000000000000000000000000000000000000000000000000000000354807f0000000000000000000000000000000000000000000000000000000000001f8757507f0000000000000000000000000000000000000000000000000000000000000003600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b7f0000000000000000000000000000000000000000000000000000000000000002547f0000000000000000000000000000000000000000000000000000000000000002557f0000000000000000000000000000000000000000000000000000000000000003557f000000000000000000000000000000000000000000000000000000000000000455600160208060408051809201905291825290f35b630000004435630000001035606060020a90047f000000000000000000000000000000000000000000000000000000000000000354807f00000000000000000000000000000000000000000000000000000000000020ca57507f0000000000000000000000000000000000000000000000000000000000000003600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b60005260205260406000205403630000001035606060020a90047f000000000000000000000000000000000000000000000000000000000000000354807f000000000000000000000000000000000000000000000000000000000000217857507f0000000000000000000000000000000000000000000000000000000000000003600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b60005260205260406000205563000000443533630000001035606060020a90047f000000000000000000000000000000000000000000000000000000000000000454807f000000000000000000000000000000000000000000000000000000000000222c57507f0000000000000000000000000000000000000000000000000000000000000004600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b6000526020526040600020548063000023195750630000001035606060020a90047f000000000000000000000000000000000000000000000000000000000000000454807f00000000000000000000000000000000000000000000000000000000000022e157507f0000000000000000000000000000000000000000000000000000000000000004600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b6000526020526040600020600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b6000526020526040600020540333630000001035606060020a90047f000000000000000000000000000000000000000000000000000000000000000454807f00000000000000000000000000000000000000000000000000000000000023c857507f0000000000000000000000000000000000000000000000000000000000000004600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b6000526020526040600020548063000024b55750630000001035606060020a90047f000000000000000000000000000000000000000000000000000000000000000454807f000000000000000000000000000000000000000000000000000000000000247d57507f0000000000000000000000000000000000000000000000000000000000000004600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b6000526020526040600020600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b600052602052604060002055630000004435630000003035606060020a90047f000000000000000000000000000000000000000000000000000000000000000354807f000000000000000000000000000000000000000000000000000000000000256857507f0000000000000000000000000000000000000000000000000000000000000003600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b60005260205260406000205401630000003035606060020a90047f000000000000000000000000000000000000000000000000000000000000000354807f000000000000000000000000000000000000000000000000000000000000261657507f0000000000000000000000000000000000000000000000000000000000000003600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b600052602052604060002055630000003035606060020a9004630000001035606060020a900463ddf252ad630000004435602080604080518092019052918252909060006000500190a37f000000000000000000000000000000000000000000000000000000000000032d7f0000000000000000000000000000000000000000000000000000000000000000557f000000000000000000000000000000000000000000000000000000000000000454807f000000000000000000000000000000000000000000000000000000000000273757507f0000000000000000000000000000000000000000000000000000000000000004600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b7f000000000000000000000000000000000000000000000000000000000000000354807f00000000000000000000000000000000000000000000000000000000000027cb57507f0000000000000000000000000000000000000000000000000000000000000003600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b7f0000000000000000000000000000000000000000000000000000000000000002547f0000000000000000000000000000000000000000000000000000000000000002557f0000000000000000000000000000000000000000000000000000000000000003557f000000000000000000000000000000000000000000000000000000000000000455600160208060408051809201905291825290f35b6300000024361415600057630000000435307f000000000000000000000000000000000000000000000000000000000000000354807f000000000000000000000000000000000000000000000000000000000000290d57507f0000000000000000000000000000000000000000000000000000000000000003600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b60005260205260406000205410156300002925576002565b337f000000000000000000000000000000000000000000000000000000000000000354807f00000000000000000000000000000000000000000000000000000000000029ba57507f0000000000000000000000000000000000000000000000000000000000000003600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b600052602052604060002054630000000435337f000000000000000000000000000000000000000000000000000000000000000354807f0000000000000000000000000000000000000000000000000000000000002a6157507f0000000000000000000000000000000000000000000000000000000000000003600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b6000526020526040600020540110156300002a7a576002565b3430310334630000000435307f000000000000000000000000000000000000000000000000000000000000000354807f0000000000000000000000000000000000000000000000000000000000002b1a57507f0000000000000000000000000000000000000000000000000000000000000003600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b600052602052604060002054030263000000043530310211156300002b3d576002565b630000000435307f000000000000000000000000000000000000000000000000000000000000000354807f0000000000000000000000000000000000000000000000000000000000002bd857507f0000000000000000000000000000000000000000000000000000000000000003600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b60005260205260406000205403307f000000000000000000000000000000000000000000000000000000000000000354807f0000000000000000000000000000000000000000000000000000000000002c7a57507f0000000000000000000000000000000000000000000000000000000000000003600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b600052602052604060002055630000000435337f000000000000000000000000000000000000000000000000000000000000000354807f0000000000000000000000000000000000000000000000000000000000002d2157507f0000000000000000000000000000000000000000000000000000000000000003600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b60005260205260406000205401337f000000000000000000000000000000000000000000000000000000000000000354807f0000000000000000000000000000000000000000000000000000000000002dc357507f0000000000000000000000000000000000000000000000000000000000000003600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b60005260205260406000205533631cbc5ab1630000000435602080604080518092019052918252909034602080604080518092019052918252909060006000500190500190a27f000000000000000000000000000000000000000000000000000000000000032d7f0000000000000000000000000000000000000000000000000000000000000000557f000000000000000000000000000000000000000000000000000000000000000454807f0000000000000000000000000000000000000000000000000000000000002ee057507f0000000000000000000000000000000000000000000000000000000000000004600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b7f000000000000000000000000000000000000000000000000000000000000000354807f0000000000000000000000000000000000000000000000000000000000002f7457507f0000000000000000000000000000000000000000000000000000000000000003600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b7f0000000000000000000000000000000000000000000000000000000000000002547f0000000000000000000000000000000000000000000000000000000000000002557f0000000000000000000000000000000000000000000000000000000000000003557f000000000000000000000000000000000000000000000000000000000000000455600160208060408051809201905291825290f35b630000004436141560005763000000243530311015630000302f576002565b630000000435337f000000000000000000000000000000000000000000000000000000000000000354807f00000000000000000000000000000000000000000000000000000000000030ca57507f0000000000000000000000000000000000000000000000000000000000000003600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b600052602052604060002054101563000030e2576002565b307f000000000000000000000000000000000000000000000000000000000000000354807f000000000000000000000000000000000000000000000000000000000000317757507f0000000000000000000000000000000000000000000000000000000000000003600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b600052602052604060002054630000000435307f000000000000000000000000000000000000000000000000000000000000000354807f000000000000000000000000000000000000000000000000000000000000321e57507f0000000000000000000000000000000000000000000000000000000000000003600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b6000526020526040600020540110156300003237576002565b341515156300003245576002565b3031630000002435303103630000000435307f000000000000000000000000000000000000000000000000000000000000000354807f00000000000000000000000000000000000000000000000000000000000032eb57507f0000000000000000000000000000000000000000000000000000000000000003600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b600052602052604060002054016300000024358102630000000435830210156300003314576002565b80307f000000000000000000000000000000000000000000000000000000000000000354807f00000000000000000000000000000000000000000000000000000000000033aa57507f0000000000000000000000000000000000000000000000000000000000000003600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b600052602052604060002055630000000435337f000000000000000000000000000000000000000000000000000000000000000354807f000000000000000000000000000000000000000000000000000000000000345157507f0000000000000000000000000000000000000000000000000000000000000003600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b60005260205260406000205403337f000000000000000000000000000000000000000000000000000000000000000354807f00000000000000000000000000000000000000000000000000000000000034f357507f0000000000000000000000000000000000000000000000000000000000000003600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b6000526020526040600020553363ed7a144f6300000004356020806040805180920190529182529090630000002435602080604080518092019052918252909060006000500190500190a26000546000805560008081818181630000002435336300000bb85a03f1156000579160005550507f000000000000000000000000000000000000000000000000000000000000032d7f0000000000000000000000000000000000000000000000000000000000000000557f000000000000000000000000000000000000000000000000000000000000000454807f000000000000000000000000000000000000000000000000000000000000363c57507f0000000000000000000000000000000000000000000000000000000000000004600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b7f000000000000000000000000000000000000000000000000000000000000000354807f00000000000000000000000000000000000000000000000000000000000036d057507f0000000000000000000000000000000000000000000000000000000000000003600154807f0000000000000000000000000000000000000000000000000000000000000001016001558091555b7f0000000000000000000000000000000000000000000000000000000000000002547f0000000000000000000000000000000000000000000000000000000000000002557f0000000000000000000000000000000000000000000000000000000000000003557f000000000000000000000000000000000000000000000000000000000000000455600160208060408051809201905291825290f360606040527f0000000000000000000000000000000000000000000000000000000000000020806040805180920190528180380382397f0000000000000000000000000000000000000000000000000000000000003dd13814156002577f00000000000000000000000000000000000000000000000000000000000000025b821563000000fc57815181557f0000000000000000000000000000000000000000000000000000000000000020909203917f000000000000000000000000000000000000000000000000000000000000000101907f00000000000000000000000000000000000000000000000000000000000000200190630000007e565b505050600154630000010d57600180555b6300000003630000014857600154806300000003557f0000000000000000000000000000000000000000000000000000000000000001016001555b6300000004630000018357600154806300000004557f0000000000000000000000000000000000000000000000000000000000000001016001555b7f00000000000000000000000000000000000000000000000000000000000000237f0000000000000000000000000000000000000000000000000000000000000000557f0000000000000000000000000000000000000000000000000000000000003b9a80604080518092019052817f00000000000000000000000000000000000000000000000000000000000002178239f360606040527f0000000000000000000000000000000000000000000000000000000000000020806040805180920190528180380382397f0000000000000000000000000000000000000000000000000000000000003dd13814156002577f00000000000000000000000000000000000000000000000000000000000000025b821563000000fc57815181557f0000000000000000000000000000000000000000000000000000000000000020909203917f000000000000000000000000000000000000000000000000000000000000000101907f00000000000000000000000000000000000000000000000000000000000000200190630000007e565b505050600154630000010d57600180555b6300000003630000014857600154806300000003557f0000000000000000000000000000000000000000000000000000000000000001016001555b6300000004630000018357600154806300000004557f0000000000000000000000000000000000000000000000000000000000000001016001555b7f000000000000000000000000000000000000000000000000000000000000032d7f0000000000000000000000000000000000000000000000000000000000000000557f0000000000000000000000000000000000000000000000000000000000003b9a80604080518092019052817f00000000000000000000000000000000000000000000000000000000000002178239f3"
```
Now console session remembers the code.
```
> code
```
should show the same string.
(If you don't want to copy-and-paste strings, probably you should look at the [web3](https://github.com/ethereum/web3.js/) library.)
Also, we can store the abi in `abi.json`.
```
var abi = [{"type": "constructor", "inputs":[{"name": "totalSupply", "type": "uint256"}], "name": "PreToken", "outputs":[], "payable": true},{"type":"fallback","inputs": [],"outputs": [],"payable": true},{"type":"event","inputs":[{"name":"_from","type":"address","indexed":true},{"name":"_to","type":"address","indexed":true},{"name":"_amount","type":"uint256","indexed":false}],"name":"Transfer"},{"type":"event","inputs":[{"name":"_buyer","type":"address","indexed":true},{"name":"_amount","type":"uint256","indexed":false},{"name":"_value","type":"uint256","indexed":false}],"name":"Buy"},{"type":"event","inputs":[{"name":"_buyer","type":"address","indexed":true},{"name":"_amount","type":"uint256","indexed":false},{"name":"_value","type":"uint256","indexed":false}],"name":"Sell"},{"type":"event","inputs":[{"name":"_owner","type":"address","indexed":true},{"name":"_spender","type":"address","indexed":true},{"name":"_value","type":"uint256","indexed":false}],"name":"Approval"},{"type":"function","name":"totalSupply","inputs": [],"outputs": [{"name": "", "type": "uint256"}],"payable": true},{"type":"function","name":"balanceOf","inputs": [{"name": "a", "type": "address"}],"outputs": [{"name": "", "type": "uint256"}],"payable": true},{"type":"function","name":"transfer","inputs": [{"name": "_to", "type": "address"},{"name": "_amount", "type": "uint256"}],"outputs": [{"name": "", "type": "bool"}],"payable": true},{"type":"function","name":"approve","inputs": [{"name": "_spender", "type": "address"},{"name": "_amount", "type": "uint256"}],"outputs": [{"name": "", "type": "bool"}],"payable": true},{"type":"function","name":"allowance","inputs": [{"name": "_owner", "type": "address"},{"name": "_spender", "type": "address"}],"outputs": [{"name": "", "type": "uint256"}],"payable": true},{"type":"function","name":"transferFrom","inputs": [{"name": "_from", "type": "address"},{"name": "_to", "type": "address"},{"name": "_amount", "type": "uint256"}],"outputs": [{"name": "", "type": "bool"}],"payable": true},{"type":"function","name":"buy","inputs": [{"name": "_amount", "type": "uint256"}],"outputs": [{"name": "", "type": "bool"}],"payable": true},{"type":"function","name":"sell","inputs": [{"name": "_amount", "type": "uint256"},{"name": "_value", "type": "uint256"}],"outputs": [{"name": "", "type": "bool"}],"payable": true}]
```
### Preparing the initial arguments
When you deploy the code, the contract first becomes the `PreToken` contract.
```
contract PreToken
(uint256 totalSupply
,address => uint256 balances
,address => address => uint256 allowances
)
{
<snip>
}
```
The `PreToken` contract has three arguments `totalSupply`, `balances`, and `allowances`. However, when you deploy the code, you can only specify `totalSupply` because the other arguments are mappings (TODO: document mappings and add a link here).
Let's say we want the `totalSupply` to be `2^30`. The argument needs to be in hex (without `0x`) and 64 characters (representing 32 bytes = 1 word in Ethereum).
```
var totalSupply = "0000000000000000000000000000000000000000000000000000000040000000"
```
You can check the length of `totalSupply` like this:
```
> totalSupply.length
64
```
If you have a different number, the contract will not be deployed.
When we concatenate the code and the argument, we get the initialization data.
```
var initdata = code + totalSupply
```
### Unlocking the Account
In order to deploy code, you need an unlocked account with positive balance.
```
> personal.unlockAccount(eth.accounts[0])
```
### Deploying the contract
```
> var tx = eth.sendTransaction({from: eth.accounts[0], data: initdata, gas: 4000000})
```
For the beginning, while the transaction is not included in the blockchain yet, you see
```
> eth.getTransactionReceipt(tx)
null
```
After a while, you will see something like
```
> eth.getTransactionReceipt(tx)
{
blockHash: "0x00b34e48533b402b212b8278a06cd8455779af02eb213ca125e2cb0a67176d0c",
blockNumber: 1417246,
contractAddress: "0x624b4eab5c2dadc2e6db2e3517b0623d3bb15a68",
cumulativeGasUsed: 3486372,
from: "0xe64ae430b97ff403a194e214175c4144a82969f4",
gasUsed: 3486372,
logs: [],
logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
root: "0xfeeace094af32de1843304a2e50942a20e86275e97566b42da82aa5cc0d56f91",
to: null,
transactionHash: "0x3a8bb995cfd33af80d3a65d29f5c6906bb6759cde65824988fea3bb5794caaf4",
transactionIndex: 0
}
```
Now the Ethereum contract has been deployed on the Ropsten network!
## Interacting with the Ethereum contract
The Ethereum contract is deployed at a certain address.
```
var contractAddress = eth.getTransactionReceipt(tx).contractAddress
```
You can get an object representing the Ethereum contract.
```
var contract = eth.contract(abi).at(contractAddress)
```
Now remember that the contract is currently a `PreToken`:
```
contract PreToken
(uint256 totalSupply
,address => uint256 balances
,address => address => uint256 allowances
)
{
default
{
balances[this] = totalSupply;
return then become Token(totalSupply, balances, allowances);
}
}
```
As the source code reads, `PreToken` `become`s a `Token` contract when it is called with enough gas.
Now let's just try to do that.
```
> eth.sendTransaction({from: eth.accounts[0], to: contractAddress, gas:3000000})
```
You might need to unlock the account.
After that, the contract becomes a `Token` contract.
```
contract Token
(uint256 totalSupply
,address => uint256 balances
,address => address => uint256 allowances
)
{
case(uint256 totalSupply())
{
<snip>
}
case(uint256 balanceOf(address a))
{
<snip>
}
case(bool transfer(address _to, uint256 _amount))
{
<snip>
}
case(bool approve(address _spender, uint256 _amount))
{
<snip>
}
case(uint256 allowance(address _owner, address _spender))
{
<snip>
}
case(bool transferFrom(address _from, address _to, uint256 _amount))
{
<snip>
}
case(bool buy(uint256 _amount))
{
<snip>
}
case (bool sell(uint256 _amount, uint256 _value))
{
<snip>
}
}
```
You don't have a balance in this ERC20 contract yet, so you can only `buy` the ERC20 token you have just created.
Say you want to buy 100 tokens with 500 wei.
```
> contract.buy(100, {from: eth.accounts[0], value: 500})
```
After a while, you will see the balance
```
> contract.balanceOf.call(eth.accounts[0])
100
```
Now you can use the other methods as well. Try `transfer()` perhaps.
================================================
FILE: myocamlbuild.ml
================================================
(* OASIS_START *)
(* DO NOT EDIT (digest: 9311c1947cc1275785273cf40407014e) *)
module OASISGettext = struct
(* # 22 "src/oasis/OASISGettext.ml" *)
let ns_ str = str
let s_ str = str
let f_ (str: ('a, 'b, 'c, 'd) format4) = str
let fn_ fmt1 fmt2 n =
if n = 1 then
fmt1^^""
else
fmt2^^""
let init = []
end
module OASISString = struct
(* # 22 "src/oasis/OASISString.ml" *)
(** Various string utilities.
Mostly inspired by extlib and batteries ExtString and BatString libraries.
@author Sylvain Le Gall
*)
let nsplitf str f =
if str = "" then
[]
else
let buf = Buffer.create 13 in
let lst = ref [] in
let push () =
lst := Buffer.contents buf :: !lst;
Buffer.clear buf
in
let str_len = String.length str in
for i = 0 to str_len - 1 do
if f str.[i] then
push ()
else
Buffer.add_char buf str.[i]
done;
push ();
List.rev !lst
(** [nsplit c s] Split the string [s] at char [c]. It doesn't include the
separator.
*)
let nsplit str c =
nsplitf str ((=) c)
let find ~what ?(offset=0) str =
let what_idx = ref 0 in
let str_idx = ref offset in
while !str_idx < String.length str &&
!what_idx < String.length what do
if str.[!str_idx] = what.[!what_idx] then
incr what_idx
else
what_idx := 0;
incr str_idx
done;
if !what_idx <> String.length what then
raise Not_found
else
!str_idx - !what_idx
let sub_start str len =
let str_len = String.length str in
if len >= str_len then
""
else
String.sub str len (str_len - len)
let sub_end ?(offset=0) str len =
let str_len = String.length str in
if len >= str_len then
""
else
String.sub str 0 (str_len - len)
let starts_with ~what ?(offset=0) str =
let what_idx = ref 0 in
let str_idx = ref offset in
let ok = ref true in
while !ok &&
!str_idx < String.length str &&
!what_idx < String.length what do
if str.[!str_idx] = what.[!what_idx] then
incr what_idx
else
ok := false;
incr str_idx
done;
!what_idx = String.length what
let strip_starts_with ~what str =
if starts_with ~what str then
sub_start str (String.length what)
else
raise Not_found
let ends_with ~what ?(offset=0) str =
let what_idx = ref ((String.length what) - 1) in
let str_idx = ref ((String.length str) - 1) in
let ok = ref true in
while !ok &&
offset <= !str_idx &&
0 <= !what_idx do
if str.[!str_idx] = what.[!what_idx] then
decr what_idx
else
ok := false;
decr str_idx
done;
!what_idx = -1
let strip_ends_with ~what str =
if ends_with ~what str then
sub_end str (String.length what)
else
raise Not_found
let replace_chars f s =
let buf = Buffer.create (String.length s) in
String.iter (fun c -> Buffer.add_char buf (f c)) s;
Buffer.contents buf
let lowercase_ascii =
replace_chars
(fun c ->
if (c >= 'A' && c <= 'Z') then
Char.chr (Char.code c + 32)
else
c)
let uncapitalize_ascii s =
if s <> "" then
(lowercase_ascii (String.sub s 0 1)) ^ (String.sub s 1 ((String.length s) - 1))
else
s
let uppercase_ascii =
replace_chars
(fun c ->
if (c >= 'a' && c <= 'z') then
Char.chr (Char.code c - 32)
else
c)
let capitalize_ascii s =
if s <> "" then
(uppercase_ascii (String.sub s 0 1)) ^ (String.sub s 1 ((String.length s) - 1))
else
s
end
module OASISUtils = struct
(* # 22 "src/oasis/OASISUtils.ml" *)
open OASISGettext
module MapExt =
struct
module type S =
sig
include Map.S
val add_list: 'a t -> (key * 'a) list -> 'a t
val of_list: (key * 'a) list -> 'a t
val to_list: 'a t -> (key * 'a) list
end
module Make (Ord: Map.OrderedType) =
struct
include Map.Make(Ord)
let rec add_list t =
function
| (k, v) :: tl -> add_list (add k v t) tl
| [] -> t
let of_list lst = add_list empty lst
let to_list t = fold (fun k v acc -> (k, v) :: acc) t []
end
end
module MapString = MapExt.Make(String)
module SetExt =
struct
module type S =
sig
include Set.S
val add_list: t -> elt list -> t
val of_list: elt list -> t
val to_list: t -> elt list
end
module Make (Ord: Set.OrderedType) =
struct
include Set.Make(Ord)
let rec add_list t =
function
| e :: tl -> add_list (add e t) tl
| [] -> t
let of_list lst = add_list empty lst
let to_list = elements
end
end
module SetString = SetExt.Make(String)
let compare_csl s1 s2 =
String.compare (OASISString.lowercase_ascii s1) (OASISString.lowercase_ascii s2)
module HashStringCsl =
Hashtbl.Make
(struct
type t = string
let equal s1 s2 = (compare_csl s1 s2) = 0
let hash s = Hashtbl.hash (OASISString.lowercase_ascii s)
end)
module SetStringCsl =
SetExt.Make
(struct
type t = string
let compare = compare_csl
end)
let varname_of_string ?(hyphen='_') s =
if String.length s = 0 then
begin
invalid_arg "varname_of_string"
end
else
begin
let buf =
OASISString.replace_chars
(fun c ->
if ('a' <= c && c <= 'z')
||
('A' <= c && c <= 'Z')
||
('0' <= c && c <= '9') then
c
else
hyphen)
s;
in
let buf =
(* Start with a _ if digit *)
if '0' <= s.[0] && s.[0] <= '9' then
"_"^buf
else
buf
in
OASISString.lowercase_ascii buf
end
let varname_concat ?(hyphen='_') p s =
let what = String.make 1 hyphen in
let p =
try
OASISString.strip_ends_with ~what p
with Not_found ->
p
in
let s =
try
OASISString.strip_starts_with ~what s
with Not_found ->
s
in
p^what^s
let is_varname str =
str = varname_of_string str
let failwithf fmt = Printf.ksprintf failwith fmt
let rec file_location ?pos1 ?pos2 ?lexbuf () =
match pos1, pos2, lexbuf with
| Some p, None, _ | None, Some p, _ ->
file_location ~pos1:p ~pos2:p ?lexbuf ()
| Some p1, Some p2, _ ->
let open Lexing in
let fn, lineno = p1.pos_fname, p1.pos_lnum in
let c1 = p1.pos_cnum - p1.pos_bol in
let c2 = c1 + (p2.pos_cnum - p1.pos_cnum) in
Printf.sprintf (f_ "file %S, line %d, characters %d-%d") fn lineno c1 c2
| _, _, Some lexbuf ->
file_location
~pos1:(Lexing.lexeme_start_p lexbuf)
~pos2:(Lexing.lexeme_end_p lexbuf)
()
| None, None, None ->
s_ "<position undefined>"
let failwithpf ?pos1 ?pos2 ?lexbuf fmt =
let loc = file_location ?pos1 ?pos2 ?lexbuf () in
Printf.ksprintf (fun s -> failwith (Printf.sprintf "%s: %s" loc s)) fmt
end
module OASISExpr = struct
(* # 22 "src/oasis/OASISExpr.ml" *)
open OASISGettext
open OASISUtils
type test = string
type flag = string
type t =
| EBool of bool
| ENot of t
| EAnd of t * t
| EOr of t * t
| EFlag of flag
| ETest of test * string
type 'a choices = (t * 'a) list
let eval var_get t =
let rec eval' =
function
| EBool b ->
b
| ENot e ->
not (eval' e)
| EAnd (e1, e2) ->
(eval' e1) && (eval' e2)
| EOr (e1, e2) ->
(eval' e1) || (eval' e2)
| EFlag nm ->
let v =
var_get nm
in
assert(v = "true" || v = "false");
(v = "true")
| ETest (nm, vl) ->
let v =
var_get nm
in
(v = vl)
in
eval' t
let choose ?printer ?name var_get lst =
let rec choose_aux =
function
| (cond, vl) :: tl ->
if eval var_get cond then
vl
else
choose_aux tl
| [] ->
let str_lst =
if lst = [] then
s_ "<empty>"
else
String.concat
(s_ ", ")
(List.map
(fun (cond, vl) ->
match printer with
| Some p -> p vl
| None -> s_ "<no printer>")
lst)
in
match name with
| Some nm ->
failwith
(Printf.sprintf
(f_ "No result for the choice list '%s': %s")
nm str_lst)
| None ->
failwith
(Printf.sprintf
(f_ "No result for a choice list: %s")
str_lst)
in
choose_aux (List.rev lst)
end
# 437 "myocamlbuild.ml"
module BaseEnvLight = struct
(* # 22 "src/base/BaseEnvLight.ml" *)
module MapString = Map.Make(String)
type t = string MapString.t
let default_filename = Filename.concat (Sys.getcwd ()) "setup.data"
let load ?(allow_empty=false) ?(filename=default_filename) ?stream () =
let line = ref 1 in
let lexer st =
let st_line =
Stream.from
(fun _ ->
try
match Stream.next st with
| '\n' -> incr line; Some '\n'
| c -> Some c
with Stream.Failure -> None)
in
Genlex.make_lexer ["="] st_line
in
let rec read_file lxr mp =
match Stream.npeek 3 lxr with
| [Genlex.Ident nm; Genlex.Kwd "="; Genlex.String value] ->
Stream.junk lxr; Stream.junk lxr; Stream.junk lxr;
read_file lxr (MapString.add nm value mp)
| [] -> mp
| _ ->
failwith
(Printf.sprintf "Malformed data file '%s' line %d" filename !line)
in
match stream with
| Some st -> read_file (lexer st) MapString.empty
| None ->
if Sys.file_exists filename then begin
let chn = open_in_bin filename in
let st = Stream.of_channel chn in
try
let mp = read_file (lexer st) MapString.empty in
close_in chn; mp
with e ->
close_in chn; raise e
end else if allow_empty then begin
MapString.empty
end else begin
failwith
(Printf.sprintf
"Unable to load environment, the file '%s' doesn't exist."
filename)
end
let rec var_expand str env =
let buff = Buffer.create ((String.length str) * 2) in
Buffer.add_substitute
buff
(fun var ->
try
var_expand (MapString.find var env) env
with Not_found ->
failwith
(Printf.sprintf
"No variable %s defined when trying to expand %S."
var
str))
str;
Buffer.contents buff
let var_get name env = var_expand (MapString.find name env) env
let var_choose lst env = OASISExpr.choose (fun nm -> var_get nm env) lst
end
# 517 "myocamlbuild.ml"
module MyOCamlbuildFindlib = struct
(* # 22 "src/plugins/ocamlbuild/MyOCamlbuildFindlib.ml" *)
(** OCamlbuild extension, copied from
* https://ocaml.org/learn/tutorials/ocamlbuild/Using_ocamlfind_with_ocamlbuild.html
* by N. Pouillard and others
*
* Updated on 2016-06-02
*
* Modified by Sylvain Le Gall
*)
open Ocamlbuild_plugin
type conf = {no_automatic_syntax: bool}
let run_and_read = Ocamlbuild_pack.My_unix.run_and_read
let blank_sep_strings = Ocamlbuild_pack.Lexers.blank_sep_strings
let exec_from_conf exec =
let exec =
let env = BaseEnvLight.load ~allow_empty:true () in
try
BaseEnvLight.var_get exec env
with Not_found ->
Printf.eprintf "W: Cannot get variable %s\n" exec;
exec
in
let fix_win32 str =
if Sys.os_type = "Win32" then begin
let buff = Buffer.create (String.length str) in
(* Adapt for windowsi, ocamlbuild + win32 has a hard time to handle '\\'.
*)
String.iter
(fun c -> Buffer.add_char buff (if c = '\\' then '/' else c))
str;
Buffer.contents buff
end else begin
str
end
in
fix_win32 exec
let split s ch =
let buf = Buffer.create 13 in
let x = ref [] in
let flush () =
x := (Buffer.contents buf) :: !x;
Buffer.clear buf
in
String.iter
(fun c ->
if c = ch then
flush ()
else
Buffer.add_char buf c)
s;
flush ();
List.rev !x
let split_nl s = split s '\n'
let before_space s =
try
String.before s (String.index s ' ')
with Not_found -> s
(* ocamlfind command *)
let ocamlfind x = S[Sh (exec_from_conf "ocamlfind"); x]
(* This lists all supported packages. *)
let find_packages () =
List.map before_space (split_nl & run_and_read (exec_from_conf "ocamlfind" ^ " list"))
(* Mock to list available syntaxes. *)
let find_syntaxes () = ["camlp4o"; "camlp4r"]
let well_known_syntax = [
"camlp4.quotations.o";
"camlp4.quotations.r";
"camlp4.exceptiontracer";
"camlp4.extend";
"camlp4.foldgenerator";
"camlp4.listcomprehension";
"camlp4.locationstripper";
"camlp4.macro";
"camlp4.mapgenerator";
"camlp4.metagenerator";
"camlp4.profiler";
"camlp4.tracer"
]
let dispatch conf =
function
| After_options ->
(* By using Before_options one let command line options have an higher
* priority on the contrary using After_options will guarantee to have
* the higher priority override default commands by ocamlfind ones *)
Options.ocamlc := ocamlfind & A"ocamlc";
Options.ocamlopt := ocamlfind & A"ocamlopt";
Options.ocamldep := ocamlfind & A"ocamldep";
Options.ocamldoc := ocamlfind & A"ocamldoc";
Options.ocamlmktop := ocamlfind & A"ocamlmktop";
Options.ocamlmklib := ocamlfind & A"ocamlmklib"
| After_rules ->
(* Avoid warnings for unused tag *)
flag ["tests"] N;
(* When one link an OCaml library/binary/package, one should use
* -linkpkg *)
flag ["ocaml"; "link"; "program"] & A"-linkpkg";
(* For each ocamlfind package one inject the -package option when
* compiling, computing dependencies, generating documentation and
* linking. *)
List.iter
begin fun pkg ->
let base_args = [A"-package"; A pkg] in
(* TODO: consider how to really choose camlp4o or camlp4r. *)
let syn_args = [A"-syntax"; A "camlp4o"] in
let (args, pargs) =
(* Heuristic to identify syntax extensions: whether they end in
".syntax"; some might not.
*)
if not (conf.no_automatic_syntax) &&
(Filename.check_suffix pkg "syntax" ||
List.mem pkg well_known_syntax) then
(syn_args @ base_args, syn_args)
else
(base_args, [])
in
flag ["ocaml"; "compile"; "pkg_"^pkg] & S args;
flag ["ocaml"; "ocamldep"; "pkg_"^pkg] & S args;
flag ["ocaml"; "doc"; "pkg_"^pkg] & S args;
flag ["ocaml"; "link"; "pkg_"^pkg] & S base_args;
flag ["ocaml"; "infer_interface"; "pkg_"^pkg] & S args;
(* TODO: Check if this is allowed for OCaml < 3.12.1 *)
flag ["ocaml"; "compile"; "package("^pkg^")"] & S pargs;
flag ["ocaml"; "ocamldep"; "package("^pkg^")"] & S pargs;
flag ["ocaml"; "doc"; "package("^pkg^")"] & S pargs;
flag ["ocaml"; "infer_interface"; "package("^pkg^")"] & S pargs;
end
(find_packages ());
(* Like -package but for extensions syntax. Morover -syntax is useless
* when linking. *)
List.iter begin fun syntax ->
flag ["ocaml"; "compile"; "syntax_"^syntax] & S[A"-syntax"; A syntax];
flag ["ocaml"; "ocamldep"; "syntax_"^syntax] & S[A"-syntax"; A syntax];
flag ["ocaml"; "doc"; "syntax_"^syntax] & S[A"-syntax"; A syntax];
flag ["ocaml"; "infer_interface"; "syntax_"^syntax] &
S[A"-syntax"; A syntax];
end (find_syntaxes ());
(* The default "thread" tag is not compatible with ocamlfind.
* Indeed, the default rules add the "threads.cma" or "threads.cmxa"
* options when using this tag. When using the "-linkpkg" option with
* ocamlfind, this module will then be added twice on the command line.
*
* To solve this, one approach is to add the "-thread" option when using
* the "threads" package using the previous plugin.
*)
flag ["ocaml"; "pkg_threads"; "compile"] (S[A "-thread"]);
flag ["ocaml"; "pkg_threads"; "doc"] (S[A "-I"; A "+threads"]);
flag ["ocaml"; "pkg_threads"; "link"] (S[A "-thread"]);
flag ["ocaml"; "pkg_threads"; "infer_interface"] (S[A "-thread"]);
flag ["c"; "pkg_threads"; "compile"] (S[A "-thread"]);
flag ["ocaml"; "package(threads)"; "compile"] (S[A "-thread"]);
flag ["ocaml"; "package(threads)"; "doc"] (S[A "-I"; A "+threads"]);
flag ["ocaml"; "package(threads)"; "link"] (S[A "-thread"]);
flag ["ocaml"; "package(threads)"; "infer_interface"] (S[A "-thread"]);
flag ["c"; "package(threads)"; "compile"] (S[A "-thread"]);
| _ ->
()
end
module MyOCamlbuildBase = struct
(* # 22 "src/plugins/ocamlbuild/MyOCamlbuildBase.ml" *)
(** Base functions for writing myocamlbuild.ml
@author Sylvain Le Gall
*)
open Ocamlbuild_plugin
module OC = Ocamlbuild_pack.Ocaml_compiler
type dir = string
type file = string
type name = string
type tag = string
type t =
{
lib_ocaml: (name * dir list * string list) list;
lib_c: (name * dir * file list) list;
flags: (tag list * (spec OASISExpr.choices)) list;
(* Replace the 'dir: include' from _tags by a precise interdepends in
* directory.
*)
includes: (dir * dir list) list;
}
(* # 110 "src/plugins/ocamlbuild/MyOCamlbuildBase.ml" *)
let env_filename = Pathname.basename BaseEnvLight.default_filename
let dispatch_combine lst =
fun e ->
List.iter
(fun dispatch -> dispatch e)
lst
let tag_libstubs nm =
"use_lib"^nm^"_stubs"
let nm_libstubs nm =
nm^"_stubs"
let dispatch t e =
let env = BaseEnvLight.load ~allow_empty:true () in
match e with
| Before_options ->
let no_trailing_dot s =
if String.length s >= 1 && s.[0] = '.' then
String.sub s 1 ((String.length s) - 1)
else
s
in
List.iter
(fun (opt, var) ->
try
opt := no_trailing_dot (BaseEnvLight.var_get var env)
with Not_found ->
Printf.eprintf "W: Cannot get variable %s\n" var)
[
Options.ext_obj, "ext_obj";
Options.ext_lib, "ext_lib";
Options.ext_dll, "ext_dll";
]
| After_rules ->
(* Declare OCaml libraries *)
List.iter
(function
| nm, [], intf_modules ->
ocaml_lib nm;
let cmis =
List.map (fun m -> (OASISString.uncapitalize_ascii m) ^ ".cmi")
intf_modules in
dep ["ocaml"; "link"; "library"; "file:"^nm^".cma"] cmis
| nm, dir :: tl, intf_modules ->
ocaml_lib ~dir:dir (dir^"/"^nm);
List.iter
(fun dir ->
List.iter
(fun str ->
flag ["ocaml"; "use_"^nm; str] (S[A"-I"; P dir]))
["compile"; "infer_interface"; "doc"])
tl;
let cmis =
List.map (fun m -> dir^"/"^(OASISString.uncapitalize_ascii m)^".cmi")
intf_modules in
dep ["ocaml"; "link"; "library"; "file:"^dir^"/"^nm^".cma"]
cmis)
t.lib_ocaml;
(* Declare directories dependencies, replace "include" in _tags. *)
List.iter
(fun (dir, include_dirs) ->
Pathname.define_context dir include_dirs)
t.includes;
(* Declare C libraries *)
List.iter
(fun (lib, dir, headers) ->
(* Handle C part of library *)
flag ["link"; "library"; "ocaml"; "byte"; tag_libstubs lib]
(S[A"-dllib"; A("-l"^(nm_libstubs lib)); A"-cclib";
A("-l"^(nm_libstubs lib))]);
flag ["link"; "library"; "ocaml"; "native"; tag_libstubs lib]
(S[A"-cclib"; A("-l"^(nm_libstubs lib))]);
if bool_of_string (BaseEnvLight.var_get "native_dynlink" env) then
flag ["link"; "program"; "ocaml"; "byte"; tag_libstubs lib]
(S[A"-dllib"; A("dll"^(nm_libstubs lib))]);
(* When ocaml link something that use the C library, then one
need that file to be up to date.
This holds both for programs and for libraries.
*)
dep ["link"; "ocaml"; tag_libstubs lib]
[dir/"lib"^(nm_libstubs lib)^"."^(!Options.ext_lib)];
dep ["compile"; "ocaml"; tag_libstubs lib]
[dir/"lib"^(nm_libstubs lib)^"."^(!Options.ext_lib)];
(* TODO: be more specific about what depends on headers *)
(* Depends on .h files *)
dep ["compile"; "c"]
headers;
(* Setup search path for lib *)
flag ["link"; "ocaml"; "use_"^lib]
(S[A"-I"; P(dir)]);
)
t.lib_c;
(* Add flags *)
List.iter
(fun (tags, cond_specs) ->
let spec = BaseEnvLight.var_choose cond_specs env in
let rec eval_specs =
function
| S lst -> S (List.map eval_specs lst)
| A str -> A (BaseEnvLight.var_expand str env)
| spec -> spec
in
flag tags & (eval_specs spec))
t.flags
| _ ->
()
let dispatch_default conf t =
dispatch_combine
[
dispatch t;
MyOCamlbuildFindlib.dispatch conf;
]
end
# 878 "myocamlbuild.ml"
open Ocamlbuild_plugin;;
let package_default =
{
MyOCamlbuildBase.lib_ocaml =
[
("cross-platform", ["src/cross-platform-for-ocamlbuild"], []);
("basics", ["src/basics"], []);
("ast", ["src/ast"], []);
("parse", ["src/parse"], []);
("codegen", ["src/codegen"], [])
];
lib_c = [];
flags = [];
includes =
[
("src/parse", ["src/ast"]);
("src/exec", ["src/codegen"; "src/parse"]);
("src/codegen", ["src/ast"; "src/basics"; "src/parse"]);
("src/basics", ["src/cross-platform-for-ocamlbuild"]);
("src/ast", ["src/basics"])
]
}
;;
let conf = {MyOCamlbuildFindlib.no_automatic_syntax = false}
let dispatch_default = MyOCamlbuildBase.dispatch_default conf package_default;;
# 908 "myocamlbuild.ml"
(* OASIS_STOP *)
Ocamlbuild_plugin.dispatch dispatch_default;;
================================================
FILE: opam/descr
================================================
A compiler targeting Ethereum Virtual Machine
Bamboo compiles a simple language to Ethereum Virtual Machine. The
language is designed to keep programmers away from common mistakes. It
features: state transition as recursion with potentially changing
arguments, mandatory reentrance continuation when calling out, no
loops, no assignments except to mappings and partial compliance with
common Ethereum ABI.
================================================
FILE: opam/opam
================================================
opam-version: "1.2"
maintainer: "Yoichi Hirai <i@yoichihirai.com>"
authors: "Yoichi Hirai <i@yoichihirai.com>"
name: "bamboo"
version: "0.0.03"
homepage: "https://github.com/pirapira/bamboo"
bug-reports: "https://github.com/pirapira/bamboo/issues"
license: "Apache-2.0"
dev-repo: "https://github.com/pirapira/bamboo.git"
build: [
[
"rm"
"-f"
"src/parse/parser.ml"
"src/parse/parser.mli"
"src/parse/lexer.ml"
]
["ocaml" "setup.ml" "-configure" "--prefix" prefix]
["ocaml" "setup.ml" "-build"]
]
install: ["ocaml" "setup.ml" "-install"]
build-test: [
["ocaml" "setup.ml" "-configure" "--enable-tests"]
["ocaml" "setup.ml" "-build"]
["ocaml" "setup.ml" "-test"]
]
remove: ["ocamlfind" "remove" "bamboo"]
depends: [
"batteries" {build}
"cryptokit" {build & >= "1.12"}
"hex" {build & >= "0.1.0" & <= "1.0.0"}
"menhir" {build & >= "20120123" & <= "20151005"}
"ocamlbuild" {build & (>= "0.9.3" | = "0")}
"ocamlfind" {build}
"rope" {build}
]
================================================
FILE: package.json
================================================
{
"name": "bamboo",
"version": "0.0.02",
"description": "A compiler targeting Ethereum Virtual Machine",
"keywords": [
"ethereum",
"smart-contracts",
"blockchain",
"virtual machine",
"compiler"
],
"repository": {
"type": "git",
"url": "https://github.com/pirapira/bamboo"
},
"homepage": "https://github.com/pirapira/bamboo",
"author": "Yoichi Hirai <i@yoichihirai.com>",
"license": "Apache-2.0",
"devDependencies": {
"bs-platform": "bsansouci/bsb-native#2.1.1"
},
"scripts": {
"build": "bsb -make-world -backend native",
"build-js": "bsb -make-world -backend js",
"watch": "bsb -make-world -backend native -w",
"test": "npm run build && ./lib/bs/native/test.native",
"clean": "bsb -clean-world"
},
"dependencies": {
"bn.js": "^4.11.8",
"bs-bn.js": "0.0.2",
"keccak": "^1.4.0"
}
}
================================================
FILE: setup.ml
================================================
(* setup.ml generated for the first time by OASIS v0.4.10 *)
(* OASIS_START *)
(* DO NOT EDIT (digest: e49f9499c8ae75ca2ab01e5d5fc622dd) *)
(*
Regenerated by OASIS v0.4.10
Visit http://oasis.forge.ocamlcore.org for more information and
documentation about functions used in this file.
*)
module OASISGettext = struct
(* # 22 "src/oasis/OASISGettext.ml" *)
let ns_ str = str
let s_ str = str
let f_ (str: ('a, 'b, 'c, 'd) format4) = str
let fn_ fmt1 fmt2 n =
if n = 1 then
fmt1^^""
else
fmt2^^""
let init = []
end
module OASISString = struct
(* # 22 "src/oasis/OASISString.ml" *)
(** Various string utilities.
Mostly inspired by extlib and batteries ExtString and BatString libraries.
@author Sylvain Le Gall
*)
let nsplitf str f =
if str = "" then
[]
else
let buf = Buffer.create 13 in
let lst = ref [] in
let push () =
lst := Buffer.contents buf :: !lst;
Buffer.clear buf
in
let str_len = String.length str in
for i = 0 to str_len - 1 do
if f str.[i] then
push ()
else
Buffer.add_char buf str.[i]
done;
push ();
List.rev !lst
(** [nsplit c s] Split the string [s] at char [c]. It doesn't include the
separator.
*)
let nsplit str c =
nsplitf str ((=) c)
let find ~what ?(offset=0) str =
let what_idx = ref 0 in
let str_idx = ref offset in
while !str_idx < String.length str &&
!what_idx < String.length what do
if str.[!str_idx] = what.[!what_idx] then
incr what_idx
else
what_idx := 0;
incr str_idx
done;
if !what_idx <> String.length what then
raise Not_found
else
!str_idx - !what_idx
let sub_start str len =
let str_len = String.length str in
if len >= str_len then
""
else
String.sub str len (str_len - len)
let sub_end ?(offset=0) str len =
let str_len = String.length str in
if len >= str_len then
""
else
String.sub str 0 (str_len - len)
let starts_with ~what ?(offset=0) str =
let what_idx = ref 0 in
let str_idx = ref offset in
let ok = ref true in
while !ok &&
!str_idx < String.length str &&
!what_idx < String.length what do
if str.[!str_idx] = what.[!what_idx] then
incr what_idx
else
ok := false;
incr str_idx
done;
!what_idx = String.length what
let strip_starts_with ~what str =
if starts_with ~what str then
sub_start str (String.length what)
else
raise Not_found
let ends_with ~what ?(offset=0) str =
let what_idx = ref ((String.length what) - 1) in
let str_idx = ref ((String.length str) - 1) in
let ok = ref true in
while !ok &&
offset <= !str_idx &&
0 <= !what_idx do
if str.[!str_idx] = what.[!what_idx] then
decr what_idx
else
ok := false;
decr str_idx
done;
!what_idx = -1
let strip_ends_with ~what str =
if ends_with ~what str then
sub_end str (String.length what)
else
raise Not_found
let replace_chars f s =
let buf = Buffer.create (String.length s) in
String.iter (fun c -> Buffer.add_char buf (f c)) s;
Buffer.contents buf
let lowercase_ascii =
replace_chars
(fun c ->
if (c >= 'A' && c <= 'Z') then
Char.chr (Char.code c + 32)
else
c)
let uncapitalize_ascii s =
if s <> "" then
(lowercase_ascii (String.sub s 0 1)) ^ (String.sub s 1 ((String.length s) - 1))
else
s
let uppercase_ascii =
replace_chars
(fun c ->
if (c >= 'a' && c <= 'z') then
Char.chr (Char.code c - 32)
else
c)
let capitalize_ascii s =
if s <> "" then
(uppercase_ascii (String.sub s 0 1)) ^ (String.sub s 1 ((String.length s) - 1))
else
s
end
module OASISUtils = struct
(* # 22 "src/oasis/OASISUtils.ml" *)
open OASISGettext
module MapExt =
struct
module type S =
sig
include Map.S
val add_list: 'a t -> (key * 'a) list -> 'a t
val of_list: (key * 'a) list -> 'a t
val to_list: 'a t -> (key * 'a) list
end
module Make (Ord: Map.OrderedType) =
struct
include Map.Make(Ord)
let rec add_list t =
function
| (k, v) :: tl -> add_list (add k v t) tl
| [] -> t
let of_list lst = add_list empty lst
let to_list t = fold (fun k v acc -> (k, v) :: acc) t []
end
end
module MapString = MapExt.Make(String)
module SetExt =
struct
module type S =
sig
include Set.S
val add_list: t -> elt list -> t
val of_list: elt list -> t
val to_list: t -> elt list
end
module Make (Ord: Set.OrderedType) =
struct
include Set.Make(Ord)
let rec add_list t =
function
| e :: tl -> add_list (add e t) tl
| [] -> t
let of_list lst = add_list empty lst
let to_list = elements
end
end
module SetString = SetExt.Make(String)
let compare_csl s1 s2 =
String.compare (OASISString.lowercase_ascii s1) (OASISString.lowercase_ascii s2)
module HashStringCsl =
Hashtbl.Make
(struct
type t = string
let equal s1 s2 = (compare_csl s1 s2) = 0
let hash s = Hashtbl.hash (OASISString.lowercase_ascii s)
end)
module SetStringCsl =
SetExt.Make
(struct
type t = string
let compare = compare_csl
end)
let varname_of_string ?(hyphen='_') s =
if String.length s = 0 then
begin
invalid_arg "varname_of_string"
end
else
begin
let buf =
OASISString.replace_chars
(fun c ->
if ('a' <= c && c <= 'z')
||
('A' <= c && c <= 'Z')
||
('0' <= c && c <= '9') then
c
else
hyphen)
s;
in
let buf =
(* Start with a _ if digit *)
if '0' <= s.[0] && s.[0] <= '9' then
"_"^buf
else
buf
in
OASISString.lowercase_ascii buf
end
let varname_concat ?(hyphen='_') p s =
let what = String.make 1 hyphen in
let p =
try
OASISString.strip_ends_with ~what p
with Not_found ->
p
in
let s =
try
OASISString.strip_starts_with ~what s
with Not_found ->
s
in
p^what^s
let is_varname str =
str = varname_of_string str
let failwithf fmt = Printf.ksprintf failwith fmt
let rec file_location ?pos1 ?pos2 ?lexbuf () =
match pos1, pos2, lexbuf with
| Some p, None, _ | None, Some p, _ ->
file_location ~pos1:p ~pos2:p ?lexbuf ()
| Some p1, Some p2, _ ->
let open Lexing in
let fn, lineno = p1.pos_fname, p1.pos_lnum in
let c1 = p1.pos_cnum - p1.pos_bol in
let c2 = c1 + (p2.pos_cnum - p1.pos_cnum) in
Printf.sprintf (f_ "file %S, line %d, characters %d-%d") fn lineno c1 c2
| _, _, Some lexbuf ->
file_location
~pos1:(Lexing.lexeme_start_p lexbuf)
~pos2:(Lexing.lexeme_end_p lexbuf)
()
| None, None, None ->
s_ "<position undefined>"
let failwithpf ?pos1 ?pos2 ?lexbuf fmt =
let loc = file_location ?pos1 ?pos2 ?lexbuf () in
Printf.ksprintf (fun s -> failwith (Printf.sprintf "%s: %s" loc s)) fmt
end
module OASISUnixPath = struct
(* # 22 "src/oasis/OASISUnixPath.ml" *)
type unix_filename = string
type unix_dirname = string
type host_filename = string
type host_dirname = string
let current_dir_name = "."
let parent_dir_name = ".."
let is_current_dir fn =
fn = current_dir_name || fn = ""
let concat f1 f2 =
if is_current_dir f1 then
f2
else
let f1' =
try OASISString.strip_ends_with ~what:"/" f1 with Not_found -> f1
in
f1'^"/"^f2
let make =
function
| hd :: tl ->
List.fold_left
(fun f p -> concat f p)
hd
tl
| [] ->
invalid_arg "OASISUnixPath.make"
let dirname f =
try
String.sub f 0 (String.rindex f '/')
with Not_found ->
current_dir_name
let basename f =
try
let pos_start =
(String.rindex f '/') + 1
in
String.sub f pos_start ((String.length f) - pos_start)
with Not_found ->
f
let chop_extension f =
try
let last_dot =
String.rindex f '.'
in
let sub =
String.sub f 0 last_dot
in
try
let last_slash =
String.rindex f '/'
in
if last_slash < last_dot then
sub
else
f
with Not_found ->
sub
with Not_found ->
f
let capitalize_file f =
let dir = dirname f in
let base = basename f in
concat dir (OASISString.capitalize_ascii base)
let uncapitalize_file f =
let dir = dirname f in
let base = basename f in
concat dir (OASISString.uncapitalize_ascii base)
end
module OASISHostPath = struct
(* # 22 "src/oasis/OASISHostPath.ml" *)
open Filename
open OASISGettext
module Unix = OASISUnixPath
let make =
function
| [] ->
invalid_arg "OASISHostPath.make"
| hd :: tl ->
List.fold_left Filename.concat hd tl
let of_unix ufn =
match Sys.os_type with
| "Unix" | "Cygwin" -> ufn
| "Win32" ->
make
(List.map
(fun p ->
if p = Unix.current_dir_name then
current_dir_name
else if p = Unix.parent_dir_name then
parent_dir_name
else
p)
(OASISString.nsplit ufn '/'))
| os_type ->
OASISUtils.failwithf
(f_ "Don't know the path format of os_type %S when translating unix \
filename. %S")
os_type ufn
end
module OASISFileSystem = struct
(* # 22 "src/oasis/OASISFileSystem.ml" *)
(** File System functions
@author Sylvain Le Gall
*)
type 'a filename = string
class type closer =
object
method close: unit
end
class type reader =
object
inherit closer
method input: Buffer.t -> int -> unit
end
class type writer =
object
inherit closer
method output: Buffer.t -> unit
end
class type ['a] fs =
object
method string_of_filename: 'a filename -> string
method open_out: ?mode:(open_flag list) -> ?perm:int -> 'a filename -> writer
method open_in: ?mode:(open_flag list) -> ?perm:int -> 'a filename -> reader
method file_exists: 'a filename -> bool
method remove: 'a filename -> unit
end
module Mode =
struct
let default_in = [Open_rdonly]
let default_out = [Open_wronly; Open_creat; Open_trunc]
let text_in = Open_text :: default_in
let text_out = Open_text :: default_out
let binary_in = Open_binary :: default_in
let binary_out = Open_binary :: default_out
end
let std_length = 4096 (* Standard buffer/read length. *)
let binary_out = Mode.binary_out
let binary_in = Mode.binary_in
let of_unix_filename ufn = (ufn: 'a filename)
let to_unix_filename fn = (fn: string)
let defer_close o f =
try
let r = f o in o#close; r
with e ->
o#close; raise e
let stream_of_reader rdr =
let buf = Buffer.create std_length in
let pos = ref 0 in
let eof = ref false in
let rec next idx =
let bpos = idx - !pos in
if !eof then begin
None
end else if bpos < Buffer.length buf then begin
Some (Buffer.nth buf bpos)
end else begin
pos := !pos + Buffer.length buf;
Buffer.clear buf;
begin
try
rdr#input buf std_length;
with End_of_file ->
if Buffer.length buf = 0 then
eof := true
end;
next idx
end
in
Stream.from next
let read_all buf rdr =
try
while true do
rdr#input buf std_length
done
with End_of_file ->
()
class ['a] host_fs rootdir : ['a] fs =
object (self)
method private host_filename fn = Filename.concat rootdir fn
method string_of_filename = self#host_filename
method open_out ?(mode=Mode.text_out) ?(perm=0o666) fn =
let chn = open_out_gen mode perm (self#host_filename fn) in
object
method close = close_out chn
method output buf = Buffer.output_buffer chn buf
end
method open_in ?(mode=Mode.text_in) ?(perm=0o666) fn =
(* TODO: use Buffer.add_channel when minimal version of OCaml will
* be >= 4.03.0 (previous version was discarding last chars).
*)
let chn = open_in_gen mode perm (self#host_filename fn) in
let strm = Stream.of_channel chn in
object
method close = close_in chn
method input buf len =
let read = ref 0 in
try
for _i = 0 to len do
Buffer.add_char buf (Stream.next strm);
incr read
done
with Stream.Failure ->
if !read = 0 then
raise End_of_file
end
method file_exists fn = Sys.file_exists (self#host_filename fn)
method remove fn = Sys.remove (self#host_filename fn)
end
end
module OASISContext = struct
(* # 22 "src/oasis/OASISContext.ml" *)
open OASISGettext
type level =
[ `Debug
| `Info
| `Warning
| `Error]
type source
type source_filename = source OASISFileSystem.filename
let in_srcdir ufn = OASISFileSystem.of_unix_filename ufn
type t =
{
(* TODO: replace this by a proplist. *)
quiet: bool;
info: bool;
debug: bool;
ignore_plugins: bool;
ignore_unknown_fields: bool;
printf: level -> string -> unit;
srcfs: source OASISFileSystem.fs;
load_oasis_plugin: string -> bool;
}
let printf lvl str =
let beg =
match lvl with
| `Error -> s_ "E: "
| `Warning -> s_ "W: "
| `Info -> s_ "I: "
| `Debug -> s_ "D: "
in
prerr_endline (beg^str)
let default =
ref
{
quiet = false;
info = false;
debug = false;
ignore_plugins = false;
ignore_unknown_fields = false;
printf = printf;
srcfs = new OASISFileSystem.host_fs(Sys.getcwd ());
load_oasis_plugin = (fun _ -> false);
}
let quiet =
{!default with quiet = true}
let fspecs () =
(* TODO: don't act on default. *)
let ignore_plugins = ref false in
["-quiet",
Arg.Unit (fun () -> default := {!default with quiet = true}),
s_ " Run quietly";
"-info",
Arg.Unit (fun () -> default := {!default with info = true}),
s_ " Display information message";
"-debug",
Arg.Unit (fun () -> default := {!default with debug = true}),
s_ " Output debug message";
"-ignore-plugins",
Arg.Set ignore_plugins,
s_ " Ignore plugin's field.";
"-C",
Arg.String
(fun str ->
Sys.chdir str;
default := {!default with srcfs = new OASISFileSystem.host_fs str}),
s_ "dir Change directory before running (affects setup.{data,log})."],
fun () -> {!default with ignore_plugins = !ignore_plugins}
end
module PropList = struct
(* # 22 "src/oasis/PropList.ml" *)
open OASISGettext
type name = string
exception Not_set of name * string option
exception No_printer of name
exception Unknown_field of name * name
let () =
Printexc.register_printer
(function
| Not_set (nm, Some rsn) ->
Some
(Printf.sprintf (f_ "Field '%s' is not set: %s") nm rsn)
| Not_set (nm, None) ->
Some
(Printf.sprintf (f_ "Field '%s' is not set") nm)
| No_printer nm ->
Some
(Printf.sprintf (f_ "No default printer for value %s") nm)
| Unknown_field (nm, schm) ->
Some
(Printf.sprintf
(f_ "Field %s is not defined in schema %s") nm schm)
| _ ->
None)
module Data =
struct
type t =
(name, unit -> unit) Hashtbl.t
let create () =
Hashtbl.create 13
let clear t =
Hashtbl.clear t
(* # 77 "src/oasis/PropList.ml" *)
end
module Schema =
struct
type ('ctxt, 'extra) value =
{
get: Data.t -> string;
set: Data.t -> ?context:'ctxt -> string -> unit;
help: (unit -> string) option;
extra: 'extra;
}
type ('ctxt, 'extra) t =
{
name: name;
fields: (name, ('ctxt, 'extra) value) Hashtbl.t;
order: name Queue.t;
name_norm: string -> string;
}
let create ?(case_insensitive=false) nm =
{
name = nm;
fields = Hashtbl.create 13;
order = Queue.create ();
name_norm =
(if case_insensitive then
OASISString.lowercase_ascii
else
fun s -> s);
}
let add t nm set get extra help =
let key =
t.name_norm nm
in
if Hashtbl.mem t.fields key then
failwith
(Printf.sprintf
(f_ "Field '%s' is already defined in schema '%s'")
nm t.name);
Hashtbl.add
t.fields
key
{
set = set;
get = get;
help = help;
extra = extra;
};
Queue.add nm t.order
let mem t nm =
Hashtbl.mem t.fields nm
let find t nm =
try
Hashtbl.find t.fields (t.name_norm nm)
with Not_found ->
raise (Unknown_field (nm, t.name))
let get t data nm =
(find t nm).get data
let set t data nm ?context x =
(find t nm).set
data
?context
x
let fold f acc t =
Queue.fold
(fun acc k ->
let v =
find t k
in
f acc k v.extra v.help)
acc
t.order
let iter f t =
fold
(fun () -> f)
()
t
let name t =
t.name
end
module Field =
struct
type ('ctxt, 'value, 'extra) t =
{
set: Data.t -> ?context:'ctxt -> 'value -> unit;
get: Data.t -> 'value;
sets: Data.t -> ?context:'ctxt -> string -> unit;
gets: Data.t -> string;
help: (unit -> string) option;
extra: 'extra;
}
let new_id =
let last_id =
ref 0
in
fun () -> incr last_id; !last_id
let create ?schema ?name ?parse ?print ?default ?update ?help extra =
(* Default value container *)
let v =
ref None
in
(* If name is not given, create unique one *)
let nm =
match name with
| Some s -> s
| None -> Printf.sprintf "_anon_%d" (new_id ())
in
(* Last chance to get a value: the default *)
let default () =
match default with
| Some d -> d
| None -> raise (Not_set (nm, Some (s_ "no default value")))
in
(* Get data *)
let get data =
(* Get value *)
try
(Hashtbl.find data nm) ();
match !v with
| Some x -> x
| None -> default ()
with Not_found ->
default ()
in
(* Set data *)
let set data ?context x =
let x =
match update with
| Some f ->
begin
try
f ?context (get data) x
with Not_set _ ->
x
end
| None ->
x
in
Hashtbl.replace
data
nm
(fun () -> v := Some x)
in
(* Parse string value, if possible *)
let parse =
match parse with
| Some f ->
f
| None ->
fun ?context s ->
failwith
(Printf.sprintf
(f_ "Cannot parse field '%s' when setting value %S")
nm
s)
in
(* Set data, from string *)
let sets data ?context s =
set ?context data (parse ?context s)
in
(* Output value as string, if possible *)
let print =
match print with
| Some f ->
f
| None ->
fun _ -> raise (No_printer nm)
in
(* Get data, as a string *)
let gets data =
print (get data)
in
begin
match schema with
| Some t ->
Schema.add t nm sets gets extra help
| None ->
()
end;
{
set = set;
get = get;
sets = sets;
gets = gets;
help = help;
extra = extra;
}
let fset data t ?context x =
t.set data ?context x
let fget data t =
t.get data
let fsets data t ?context s =
t.sets data ?context s
let fgets data t =
t.gets data
end
module FieldRO =
struct
let create ?schema ?name ?parse ?print ?default ?update ?help extra =
let fld =
Field.create ?schema ?name ?parse ?print ?default ?update ?help extra
in
fun data -> Field.fget data fld
end
end
module OASISMessage = struct
(* # 22 "src/oasis/OASISMessage.ml" *)
open OASISGettext
open OASISContext
let generic_message ~ctxt lvl fmt =
let cond =
if ctxt.quiet then
false
else
match lvl with
| `Debug -> ctxt.debug
| `Info -> ctxt.info
| _ -> true
in
Printf.ksprintf
(fun str ->
if cond then
begin
ctxt.printf lvl str
end)
fmt
let debug ~ctxt fmt =
generic_message ~ctxt `Debug fmt
let info ~ctxt fmt =
generic_message ~ctxt `Info fmt
let warning ~ctxt fmt =
generic_message ~ctxt `Warning fmt
let error ~ctxt fmt =
generic_message ~ctxt `Error fmt
end
module OASISVersion = struct
(* # 22 "src/oasis/OASISVersion.ml" *)
open OASISGettext
type t = string
type comparator =
| VGreater of t
| VGreaterEqual of t
| VEqual of t
| VLesser of t
| VLesserEqual of t
| VOr of comparator * comparator
| VAnd of comparator * comparator
(* Range of allowed characters *)
let is_digit c = '0' <= c && c <= '9'
let is_alpha c = ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')
let is_special = function | '.' | '+' | '-' | '~' -> true | _ -> false
let rec version_compare v1 v2 =
if v1 <> "" || v2 <> "" then
begin
(* Compare ascii string, using special meaning for version
* related char
*)
let val_ascii c =
if c = '~' then -1
else if is_digit c then 0
else if c = '\000' then 0
else if is_alpha c then Char.code c
else (Char.code c) + 256
in
let len1 = String.length v1 in
let len2 = String.length v2 in
let p = ref 0 in
(** Compare ascii part *)
let compare_vascii () =
let cmp = ref 0 in
while !cmp = 0 &&
!p < len1 && !p < len2 &&
not (is_digit v1.[!p] && is_digit v2.[!p]) do
cmp := (val_ascii v1.[!p]) - (val_ascii v2.[!p]);
incr p
done;
if !cmp = 0 && !p < len1 && !p = len2 then
val_ascii v1.[!p]
else if !cmp = 0 && !p = len1 && !p < len2 then
- (val_ascii v2.[!p])
else
!cmp
in
(** Compare digit part *)
let compare_digit () =
let extract_int v p =
let start_p = !p in
while !p < String.length v && is_digit v.[!p] do
incr p
done;
let substr =
String.sub v !p ((String.length v) - !p)
in
let res =
match String.sub v start_p (!p - start_p) with
| "" -> 0
| s -> int_of_string s
in
res, substr
in
let i1, tl1 = extract_int v1 (ref !p) in
let i2, tl2 = extract_int v2 (ref !p) in
i1 - i2, tl1, tl2
in
match compare_vascii () with
| 0 ->
begin
match compare_digit () with
| 0, tl1, tl2 ->
if tl1 <> "" && is_digit tl1.[0] then
1
else if tl2 <> "" && is_digit tl2.[0] then
-1
else
version_compare tl1 tl2
| n, _, _ ->
n
end
| n ->
n
end
else begin
0
end
let version_of_string str = str
let string_of_version t = t
let chop t =
try
let pos =
String.rindex t '.'
in
String.sub t 0 pos
with Not_found ->
t
let rec comparator_apply v op =
match op with
| VGreater cv ->
(version_compare v cv) > 0
| VGreaterEqual cv ->
(version_compare v cv) >= 0
| VLesser cv ->
(version_compare v cv) < 0
| VLesserEqual cv ->
(version_compare v cv) <= 0
| VEqual cv ->
(version_compare v cv) = 0
| VOr (op1, op2) ->
(comparator_apply v op1) || (comparator_apply v op2)
| VAnd (op1, op2) ->
(comparator_apply v op1) && (comparator_apply v op2)
let rec string_of_comparator =
function
| VGreater v -> "> "^(string_of_version v)
| VEqual v -> "= "^(string_of_version v)
| VLesser v -> "< "^(string_of_version v)
| VGreaterEqual v -> ">= "^(string_of_version v)
| VLesserEqual v -> "<= "^(string_of_version v)
| VOr (c1, c2) ->
(string_of_comparator c1)^" || "^(string_of_comparator c2)
| VAnd (c1, c2) ->
(string_of_comparator c1)^" && "^(string_of_comparator c2)
let rec varname_of_comparator =
let concat p v =
OASISUtils.varname_concat
p
(OASISUtils.varname_of_string
(string_of_version v))
in
function
| VGreater v -> concat "gt" v
| VLesser v -> concat "lt" v
| VEqual v -> concat "eq" v
| VGreaterEqual v -> concat "ge" v
| VLesserEqual v -> concat "le" v
| VOr (c1, c2) ->
(varname_of_comparator c1)^"_or_"^(varname_of_comparator c2)
| VAnd (c1, c2) ->
(varname_of_comparator c1)^"_and_"^(varname_of_comparator c2)
end
module OASISLicense = struct
(* # 22 "src/oasis/OASISLicense.ml" *)
(** License for _oasis fields
@author Sylvain Le Gall
*)
type license = string
type license_exception = string
type license_version =
| Version of OASISVersion.t
| VersionOrLater of OASISVersion.t
| NoVersion
type license_dep_5_unit =
{
license: license;
excption: license_exception option;
version: license_version;
}
type license_dep_5 =
| DEP5Unit of license_dep_5_unit
| DEP5Or of license_dep_5 list
| DEP5And of license_dep_5 list
type t =
| DEP5License of license_dep_5
| OtherLicense of string (* URL *)
end
module OASISExpr = struct
(* # 22 "src/oasis/OASISExpr.ml" *)
open OASISGettext
open OASISUtils
type test = string
type flag = string
type t =
| EBool of bool
| ENot of t
| EAnd of t * t
| EOr of t * t
| EFlag of flag
| ETest of test * string
type 'a choices = (t * 'a) list
let eval var_get t =
let rec eval' =
function
| EBool b ->
b
| ENot e ->
not (eval' e)
| EAnd (e1, e2) ->
(eval' e1) && (eval' e2)
| EOr (e1, e2) ->
(eval' e1) || (eval' e2)
| EFlag nm ->
let v =
var_get nm
in
assert(v = "true" || v = "false");
(v = "true")
| ETest (nm, vl) ->
let v =
var_get nm
in
(v = vl)
in
eval' t
let choose ?printer ?name var_get lst =
let rec choose_aux =
function
| (cond, vl) :: tl ->
if eval var_get cond then
vl
else
choose_aux tl
| [] ->
let str_lst =
if lst = [] then
s_ "<empty>"
else
String.concat
(s_ ", ")
(List.map
(fun (cond, vl) ->
match printer with
| Some p -> p vl
| None -> s_ "<no printer>")
lst)
in
match name with
| Some nm ->
failwith
(Printf.sprintf
(f_ "No result for the choice list '%s': %s")
nm str_lst)
| None ->
failwith
(Printf.sprintf
(f_ "No result for a choice list: %s")
str_lst)
in
choose_aux (List.rev lst)
end
module OASISText = struct
(* # 22 "src/oasis/OASISText.ml" *)
type elt =
| Para of string
| Verbatim of string
| BlankLine
type t = elt list
end
module OASISSourcePatterns = struct
(* # 22 "src/oasis/OASISSourcePatterns.ml" *)
open OASISUtils
open OASISGettext
module Templater =
struct
(* TODO: use this module in BaseEnv.var_expand and BaseFileAB, at least. *)
type t =
{
atoms: atom list;
origin: string
}
and atom =
| Text of string
| Expr of expr
and expr =
| Ident of string
| String of string
| Call of string * expr
type env =
{
variables: string MapString.t;
functions: (string -> string) MapString.t;
}
let eval env t =
let rec eval_expr env =
function
| String str -> str
| Ident nm ->
begin
try
MapString.find nm env.variables
with Not_found ->
(* TODO: add error location within the string. *)
failwithf
(f_ "Unable to find variable %S in source pattern %S")
nm t.origin
end
| Call (fn, expr) ->
begin
try
(MapString.find fn env.functions) (eval_expr env expr)
with Not_found ->
(* TODO: add error location within the string. *)
failwithf
(f_ "Unable to find function %S in source pattern %S")
fn t.origin
end
in
String.concat ""
(List.map
(function
| Text str -> str
| Expr expr -> eval_expr env expr)
t.atoms)
let parse env s =
let lxr = Genlex.make_lexer [] in
let parse_expr s =
let st = lxr (Stream.of_string s) in
match Stream.npeek 3 st with
| [Genlex.Ident fn; Genlex.Ident nm] -> Call(fn, Ident nm)
| [Genlex.Ident fn; Genlex.String str] -> Call(fn, String str)
| [Genlex.String str] -> String str
| [Genlex.Ident nm] -> Ident nm
(* TODO: add error location within the string. *)
| _ -> failwithf (f_ "Unable to parse expression %S") s
in
let parse s =
let lst_exprs = ref [] in
let ss =
let buff = Buffer.create (String.length s) in
Buffer.add_substitute
buff
(fun s -> lst_exprs := (parse_expr s) :: !lst_exprs; "\000")
s;
Buffer.contents buff
in
let rec join =
function
| hd1 :: tl1, hd2 :: tl2 -> Text hd1 :: Expr hd2 :: join (tl1, tl2)
| [], tl -> List.map (fun e -> Expr e) tl
| tl, [] -> List.map (fun e -> Text e) tl
in
join (OASISString.nsplit ss '\000', List.rev (!lst_exprs))
in
let t = {atoms = parse s; origin = s} in
(* We rely on a simple evaluation for checking variables/functions.
It works because there is no if/loop statement.
*)
let _s : string = eval env t in
t
(* # 144 "src/oasis/OASISSourcePatterns.ml" *)
end
type t = Templater.t
let env ~modul () =
{
Templater.
variables = MapString.of_list ["module", modul];
functions = MapString.of_list
[
"capitalize_file", OASISUnixPath.capitalize_file;
"uncapitalize_file", OASISUnixPath.uncapitalize_file;
];
}
let all_possible_files lst ~path ~modul =
let eval = Templater.eval (env ~modul ()) in
List.fold_left
(fun acc pat -> OASISUnixPath.concat path (eval pat) :: acc)
[] lst
let to_string t = t.Templater.origin
end
module OASISTypes = struct
(* # 22 "src/oasis/OASISTypes.ml" *)
type name = string
type package_name = string
type url = string
type unix_dirname = string
type unix_filename = string (* TODO: replace everywhere. *)
type host_dirname = string (* TODO: replace everywhere. *)
type host_filename = string (* TODO: replace everywhere. *)
type prog = string
type arg = string
type args = string list
type command_line = (prog * arg list)
type findlib_name = string
type findlib_full = string
type compiled_object =
| Byte
| Native
| Best
type dependency =
| FindlibPackage of findlib_full * OASISVersion.comparator option
| InternalLibrary of name
type tool =
| ExternalTool of name
| InternalExecutable of name
type vcs =
| Darcs
| Git
| Svn
| Cvs
| Hg
| Bzr
| Arch
| Monotone
| OtherVCS of url
type plugin_kind =
[ `Configure
| `Build
| `Doc
| `Test
| `Install
| `Extra
]
type plugin_data_purpose =
[ `Configure
| `Build
| `Install
| `Clean
| `Distclean
| `Install
| `Uninstall
| `Test
| `Doc
| `Extra
| `Other of string
]
type 'a plugin = 'a * name * OASISVersion.t option
type all_plugin = plugin_kind plugin
type plugin_data = (all_plugin * plugin_data_purpose * (unit -> unit)) list
type 'a conditional = 'a OASISExpr.choices
type custom =
{
pre_command: (command_line option) conditional;
post_command: (command_line option) conditional;
}
type common_section =
{
cs_name: name;
cs_data: PropList.Data.t;
cs_plugin_data: plugin_data;
}
type build_section =
{
bs_build: bool conditional;
bs_install: bool conditional;
bs_path: unix_dirname;
bs_compiled_object: compiled_object;
bs_build_depends: dependency list;
bs_build_tools: tool list;
bs_interface_patterns: OASISSourcePatterns.t list;
bs_implementation_patterns: OASISSourcePatterns.t list;
bs_c_sources: unix_filename list;
bs_data_files: (unix_filename * unix_filename option) list;
bs_findlib_extra_files: unix_filename list;
bs_ccopt: args conditional;
bs_cclib: args conditional;
bs_dlllib: args conditional;
bs_dllpath: args conditional;
bs_byteopt: args conditional;
bs_nativeopt: args conditional;
}
type library =
{
lib_modules: string list;
lib_pack: bool;
lib_internal_modules: string list;
lib_findlib_parent: findlib_name option;
lib_findlib_name: findlib_name option;
lib_findlib_directory: unix_dirname option;
lib_findlib_containers: findlib_name list;
}
type object_ =
{
obj_modules: string list;
obj_findlib_fullname: findlib_name list option;
obj_findlib_directory: unix_dirname option;
}
type executable =
{
exec_custom: bool;
exec_main_is: unix_filename;
}
type flag =
{
flag_description: string option;
flag_default: bool conditional;
}
type source_repository =
{
src_repo_type: vcs;
src_repo_location: url;
src_repo_browser: url option;
src_repo_module: string option;
src_repo_branch: string option;
src_repo_tag: string option;
src_repo_subdir: unix_filename option;
}
type test =
{
test_type: [`Test] plugin;
test_command: command_line conditional;
test_custom: custom;
test_working_directory: unix_filename option;
test_run: bool conditional;
test_tools: tool list;
}
type doc_format =
| HTML of unix_filename (* TODO: source filename. *)
| DocText
| PDF
| PostScript
| Info of unix_filename (* TODO: source filename. *)
| DVI
| OtherDoc
type doc =
{
doc_type: [`Doc] plugin;
doc_custom: custom;
doc_build: bool conditional;
doc_install: bool conditional;
doc_install_dir: unix_filename; (* TODO: dest filename ?. *)
doc_title: string;
doc_authors: string list;
doc_abstract: string option;
doc_format: doc_format;
(* TODO: src filename. *)
doc_data_files: (unix_filename * unix_filename option) list;
doc_build_tools: tool list;
}
type section =
| Library of common_section * build_section * library
| Object of common_section * build_section * object_
| Executable of common_section * build_section * executable
| Flag of common_section * flag
| SrcRepo of common_section * source_repository
| Test of common_section * test
| Doc of common_section * doc
type section_kind =
[ `Library | `Object | `Executable | `Flag | `SrcRepo | `Test | `Doc ]
type package =
{
oasis_version: OASISVersion.t;
ocaml_version: OASISVersion.comparator option;
findlib_version: OASISVersion.comparator option;
alpha_features: string list;
beta_features: string list;
name: package_name;
version: OASISVersion.t;
license: OASISLicense.t;
license_file: unix_filename option; (* TODO: source filename. *)
copyrights: string list;
maintainers: string list;
authors: string list;
homepage: url option;
bugreports: url option;
synopsis: string;
description: OASISText.t option;
tags: string list;
categories: url list;
conf_type: [`Configure] plugin;
conf_custom: custom;
build_type: [`Build] plugin;
build_custom: custom;
install_type: [`Install] plugin;
install_custom: custom;
uninstall_custom: custom;
clean_custom: custom;
distclean_custom: custom;
files_ab: unix_filename list; (* TODO: source filename. *)
sections: section list;
plugins: [`Extra] plugin list;
disable_oasis_section: unix_filename list; (* TODO: source filename. *)
schema_data: PropList.Data.t;
plugin_data: plugin_data;
}
end
module OASISFeatures = struct
(* # 22 "src/oasis/OASISFeatures.ml" *)
open OASISTypes
open OASISUtils
open OASISGettext
open OASISVersion
module MapPlugin =
Map.Make
(struct
type t = plugin_kind * name
let compare = Pervasives.compare
end)
module Data =
struct
type t =
{
oasis_version: OASISVersion.t;
plugin_versions: OASISVersion.t option MapPlugin.t;
alpha_features: string list;
beta_features: string list;
}
let create oasis_version alpha_features beta_features =
{
oasis_version = oasis_version;
plugin_versions = MapPlugin.empty;
alpha_features = alpha_features;
beta_features = beta_features
}
let of_package pkg =
create
pkg.OASISTypes.oasis_version
pkg.OASISTypes.alpha_features
pkg.OASISTypes.beta_features
let add_plugin (plugin_kind, plugin_name, plugin_version) t =
{t with
plugin_versions = MapPlugin.add
(plugin_kind, plugin_name)
plugin_version
t.plugin_versions}
let plugin_version plugin_kind plugin_name t =
MapPlugin.find (plugin_kind, plugin_name) t.plugin_versions
let to_string t =
Printf.sprintf
"oasis_version: %s; alpha_features: %s; beta_features: %s; \
plugins_version: %s"
(OASISVersion.string_of_version (t:t).oasis_version)
(String.concat ", " t.alpha_features)
(String.concat ", " t.beta_features)
(String.concat ", "
(MapPlugin.fold
(fun (_, plg) ver_opt acc ->
(plg^
(match ver_opt with
| Some v ->
" "^(OASISVersion.string_of_version v)
| None -> ""))
:: acc)
t.plugin_versions []))
end
type origin =
| Field of string * string
| Section of string
| NoOrigin
type stage = Alpha | Beta
let string_of_stage =
function
| Alpha -> "alpha"
| Beta -> "beta"
let field_of_stage =
function
| Alpha -
gitextract_oes_fca_/
├── .gitignore
├── .gitmodules
├── .travis.yml
├── LICENSE
├── Makefile
├── README.md
├── ReleaseNotes.txt
├── __tests__/
│ └── compare-js-native.js
├── _oasis
├── _tags
├── bsconfig.json
├── doc/
│ ├── manifest.md
│ ├── semantics.md
│ ├── spec.tex
│ ├── testing-bytecode.md
│ └── tutorial.md
├── myocamlbuild.ml
├── opam/
│ ├── descr
│ └── opam
├── package.json
├── setup.ml
├── sketch/
│ ├── future.bbo
│ └── open_auction.bbo
└── src/
├── ast/
│ ├── META
│ ├── ast.mldylib
│ ├── ast.mllib
│ ├── ast_test.ml
│ ├── contract.ml
│ ├── contract.mli
│ ├── ethereum.ml
│ ├── ethereum.mli
│ ├── evm.ml
│ ├── evm.mli
│ ├── location.ml
│ ├── location.mli
│ ├── pseudoImm.ml
│ ├── pseudoImm.mli
│ ├── sideEffect.ml
│ ├── sideEffect.mli
│ ├── syntax.ml
│ ├── syntax.mli
│ ├── type.ml
│ ├── type.mli
│ ├── typeEnv.ml
│ └── typeEnv.mli
├── basics/
│ ├── META
│ ├── assoc.ml
│ ├── assoc.mli
│ ├── basics.mldylib
│ ├── basics.mllib
│ ├── hex_test.ml
│ ├── hexa.ml
│ ├── hexa.mli
│ ├── label.ml
│ ├── label.mli
│ ├── misc.ml
│ ├── misc.mli
│ ├── storage.ml
│ └── storage.mli
├── codegen/
│ ├── META
│ ├── codegen.ml
│ ├── codegen.mldylib
│ ├── codegen.mli
│ ├── codegen.mllib
│ ├── codegenEnv.ml
│ ├── codegenEnv.mli
│ ├── codegen_test.ml
│ ├── codegen_test2.ml
│ ├── entrypointDatabase.ml
│ ├── entrypointDatabase.mli
│ ├── layoutInfo.ml
│ ├── layoutInfo.mli
│ ├── layouts.txt
│ ├── locationEnv.ml
│ ├── locationEnv.mli
│ ├── parse.ml
│ └── parse.mli
├── cross-platform/
│ ├── META
│ ├── cross-platform.mldylib
│ ├── cross-platform.mllib
│ ├── rope.ml
│ ├── wrapBn.ml
│ ├── wrapBnNative.ml
│ ├── wrapCryptokit.ml
│ ├── wrapCryptokitNative.ml
│ ├── wrapList.ml
│ ├── wrapListNative.ml
│ ├── wrapOption.ml
│ ├── wrapString.ml
│ └── wrapStringNative.ml
├── cross-platform-for-ocamlbuild/
│ ├── META
│ ├── cross-platform.mldylib
│ ├── cross-platform.mllib
│ └── wrapOption.ml
├── exec/
│ ├── bamboo.ml
│ ├── compileFile.ml
│ ├── compileFile.mli
│ └── endToEnd.ml
├── exec-js/
│ └── bambooJs.ml
├── lib/
│ ├── META
│ └── lib_test.ml
├── parse/
│ ├── META
│ ├── README.md
│ ├── examples/
│ │ ├── 000nil.bbo
│ │ ├── 001empty.bbo
│ │ ├── 002comment.bbo
│ │ ├── 003default_abort.bbo
│ │ ├── 004simple_case_abort.bbo
│ │ ├── 005auction_start.bbo
│ │ ├── 006auction_first_case.bbo
│ │ ├── 007auction_first_case_more.bbo
│ │ ├── 008new_var.bbo
│ │ ├── 009new_var_auc.bbo
│ │ ├── 00a_auc_first_cast.bbo
│ │ ├── 00b_auction_more.bbo
│ │ ├── 00bbauction_first_named_case.bbo
│ │ ├── 00c_auction.bbo
│ │ ├── 00d_auction.bbo
│ │ ├── 00e_ecdsarecover.bbo
│ │ ├── 00f_bytes32.bbo
│ │ ├── 00g_int8.bbo
│ │ ├── 00h_payment_channel.bbo
│ │ ├── 00i_local_bool.bbo
│ │ ├── 010_logical_and.bbo
│ │ ├── 011_keccak256.bbo
│ │ ├── 013_iszero.bbo
│ │ ├── 014_ifelse.bbo
│ │ ├── 015_ifblock.bbo
│ │ ├── 016_void.bbo
│ │ ├── 017_return_void.bbo
│ │ ├── 018_mapmap.bbo
│ │ ├── 019_something.bbo
│ │ ├── 01a_event.bbo
│ │ ├── 01b_erc20better.bbo
│ │ ├── 020_plus_mult.bbo
│ │ ├── 021_land_neq.bbo
│ │ ├── 022_plus_gt.bbo
│ │ ├── 024_vault.bbo
│ │ ├── 024_vault_shorter.bbo
│ │ ├── 025_declit_numeric.bbo
│ │ ├── 026_abc.bbo
│ │ └── 027_counting.bbo
│ ├── lexer.mll
│ ├── negative_examples/
│ │ ├── bad_end.bbo
│ │ ├── duplicate_contract_names.bbo
│ │ ├── mixed_uints.bbo
│ │ ├── multi_default.bbo
│ │ ├── uint256_too_big.bbo
│ │ ├── uint8_too_big.bbo
│ │ ├── uint8_with_four_digits.bbo
│ │ ├── unknown_ctor_arg.bbo
│ │ ├── unknown_return.bbo
│ │ ├── unknown_type.bbo
│ │ ├── void_not_void.bbo
│ │ ├── void_some_return.bbo
│ │ ├── wrong_arg.bbo
│ │ └── wrong_return.bbo
│ ├── parse.mldylib
│ ├── parse.mllib
│ ├── parser.mly
│ └── parser_test.ml
└── run_tests.sh
Condensed preview — 162 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (764K chars).
[
{
"path": ".gitignore",
"chars": 155,
"preview": "*~\n*.native\n_build\nsetup.data\nsetup.log\n.DS_Store\n.merlin\n.bsb.lock\nnpm-debug.log\n/lib/bs/\n/lib/js/\n/node_modules/\nsrc/p"
},
{
"path": ".gitmodules",
"chars": 100,
"preview": "[submodule \"bamboo-tests\"]\n\tpath = bamboo-tests\n\turl = https://github.com/pirapira/bamboo-tests.git\n"
},
{
"path": ".travis.yml",
"chars": 2668,
"preview": "notifications:\n webhooks:\n urls:\n - https://webhooks.gitter.im/e/4f71b9fa80e108068016\n on_success: change #"
},
{
"path": "LICENSE",
"chars": 11342,
"preview": " Apache License\n Version 2.0, January 2004\n "
},
{
"path": "Makefile",
"chars": 657,
"preview": ".PHONY: test bamboo clean dep\n\nbamboo:\n\tnpm run build\n\ndep:\n\tnpm install\n\topam switch 4.02.3+buckle-master\n\teval `opam c"
},
{
"path": "README.md",
"chars": 3698,
"preview": "# Bamboo: a language for morphing smart contracts\n\nCornell Blockchain says they can now maintain the Bamboo compiler. ht"
},
{
"path": "ReleaseNotes.txt",
"chars": 465,
"preview": "Version 0.0.03 (2018-05-04)\n\n* fixes incorrect characters in the ABI https://github.com/pirapira/bamboo/issues/279\n* int"
},
{
"path": "__tests__/compare-js-native.js",
"chars": 797,
"preview": "// A small script to test if both versions (JS and native) output the same\n// string given the same programs as input\n//"
},
{
"path": "_oasis",
"chars": 1858,
"preview": "OASISFormat: 0.4\nName: bamboo\nVersion: 0.0.03\nSynopsis: A compiler targeting Ethereum Virtual Machine\nAuth"
},
{
"path": "_tags",
"chars": 2990,
"preview": "# OASIS_START\n# DO NOT EDIT (digest: c348eeadfb15aa1af2d805f976b82290)\n# Ignore VCS directories, you can use the same ki"
},
{
"path": "bsconfig.json",
"chars": 1772,
"preview": "{\n \"name\": \"bamboo\",\n \"version\": \"0.0.02\",\n \"bsc-flags\": \"-w -27 -g\",\n \"warnings\": {\n \"number\": \"-40+6+7-26-27+32"
},
{
"path": "doc/manifest.md",
"chars": 2847,
"preview": "# Bamboo Manifest\n\n## Problem\n\nSmart contracts should reduce surprises.\nThe code should reveal what can happen in which "
},
{
"path": "doc/semantics.md",
"chars": 20796,
"preview": "# Bamboo Semantics Sketch\n\nThis document describes the semantics of the Bamboo language. This is an informal sketch wri"
},
{
"path": "doc/spec.tex",
"chars": 15322,
"preview": "\\documentclass{book}\n\n\\usepackage{stmaryrd}\n\\usepackage{amsmath}\n\n\n\\newcommand{\\todo}[1]{\\underline{TODO: {#1}}}\n\\newcom"
},
{
"path": "doc/testing-bytecode.md",
"chars": 19580,
"preview": "Testing the Bytecode from bbo\n=============================\n\nGetting a Bytecode\n------------------\n\nAfter following the "
},
{
"path": "doc/tutorial.md",
"chars": 43079,
"preview": "# Bamboo 0.0.01 Tutorial\n\nThis document covers\n* installation of the Bamboo compiler\n* compilation and deployment of a B"
},
{
"path": "myocamlbuild.ml",
"chars": 24544,
"preview": "(* OASIS_START *)\n(* DO NOT EDIT (digest: 9311c1947cc1275785273cf40407014e) *)\nmodule OASISGettext = struct\n(* # 22 \"src"
},
{
"path": "opam/descr",
"chars": 407,
"preview": "A compiler targeting Ethereum Virtual Machine\n\nBamboo compiles a simple language to Ethereum Virtual Machine. The\nlangua"
},
{
"path": "opam/opam",
"chars": 982,
"preview": "opam-version: \"1.2\"\nmaintainer: \"Yoichi Hirai <i@yoichihirai.com>\"\nauthors: \"Yoichi Hirai <i@yoichihirai.com>\"\nname: \"ba"
},
{
"path": "package.json",
"chars": 876,
"preview": "{\n \"name\": \"bamboo\",\n \"version\": \"0.0.02\",\n \"description\": \"A compiler targeting Ethereum Virtual Machine\",\n \"keywor"
},
{
"path": "setup.ml",
"chars": 231321,
"preview": "(* setup.ml generated for the first time by OASIS v0.4.10 *)\n\n(* OASIS_START *)\n(* DO NOT EDIT (digest: e49f9499c8ae75ca"
},
{
"path": "sketch/future.bbo",
"chars": 301,
"preview": "contract A() {\n case (bool a()) {\n return (true) then become B();\n }\n}\ncontract B() {\n case (bool b()) {"
},
{
"path": "sketch/open_auction.bbo",
"chars": 1956,
"preview": "contract auction\n\t(address _beneficiary\n\t,uint256 _bidding_time\n\t,address => bool _bids\n\t,uint256 _highest_bid)\n{\n\tcase "
},
{
"path": "src/ast/META",
"chars": 348,
"preview": "# OASIS_START\n# DO NOT EDIT (digest: 48b4bddcf78ccaf67607c0efb8f15589)\nversion = \"0.0.03\"\ndescription = \"A compiler targ"
},
{
"path": "src/ast/ast.mldylib",
"chars": 145,
"preview": "# OASIS_START\n# DO NOT EDIT (digest: 857e7a85bbf5c81d7dc95b28750b7723)\nContract\nSyntax\nTypeEnv\nType\nPseudoImm\nEvm\nLocati"
},
{
"path": "src/ast/ast.mllib",
"chars": 145,
"preview": "# OASIS_START\n# DO NOT EDIT (digest: 857e7a85bbf5c81d7dc95b28750b7723)\nContract\nSyntax\nTypeEnv\nType\nPseudoImm\nEvm\nLocati"
},
{
"path": "src/ast/ast_test.ml",
"chars": 958,
"preview": "open Lexer\nopen Lexing\nopen Printf\n\n(* The following two functions comes from\n * https://github.com/realworldocaml/examp"
},
{
"path": "src/ast/contract.ml",
"chars": 3262,
"preview": "type case_interface = Ethereum.function_signature\n\nlet case_interface_of (raw : 'exp Syntax.case) : case_interface =\n m"
},
{
"path": "src/ast/contract.mli",
"chars": 736,
"preview": "type case_interface = Ethereum.function_signature\n\nval case_interface_of : 'exp Syntax.case -> case_interface\n\ntype cont"
},
{
"path": "src/ast/ethereum.ml",
"chars": 8989,
"preview": "let word_bits = 256\nlet signature_bits = 32\n\ntype interface_typ =\n | InterfaceUint of int\n | InterfaceBytes of int\n |"
},
{
"path": "src/ast/ethereum.mli",
"chars": 2448,
"preview": "val word_bits : int\nval signature_bits : int\n\ntype interface_typ =\n | InterfaceUint of int\n | InterfaceBytes of int\n "
},
{
"path": "src/ast/evm.ml",
"chars": 8037,
"preview": "type 'imm instruction =\n | PUSH1 of 'imm\n | PUSH4 of 'imm\n | PUSH32 of 'imm\n | NOT\n | TIMESTAMP\n | EQ\n | ISZERO\n "
},
{
"path": "src/ast/evm.mli",
"chars": 1946,
"preview": "type 'imm instruction =\n | PUSH1 of 'imm\n | PUSH4 of 'imm\n | PUSH32 of 'imm\n | NOT\n | TIMESTAMP\n | EQ\n | ISZERO\n "
},
{
"path": "src/ast/location.ml",
"chars": 1390,
"preview": "type 'imm memory_range =\n { memory_start : 'imm (* In byte as in EVM *)\n ; memory_size : 'imm (* In byte *)\n }\n\ntype"
},
{
"path": "src/ast/location.mli",
"chars": 1165,
"preview": "(* This module annotates idents with the locations of the data *)\n\ntype 'imm memory_range =\n { memory_start : 'imm (* I"
},
{
"path": "src/ast/pseudoImm.ml",
"chars": 2144,
"preview": "(* pseudo immediate value *)\n\ntype pseudo_imm =\n | Big of WrapBn.t\n | Int of int\n | DestLabel of Label.label\n | Stor"
},
{
"path": "src/ast/pseudoImm.mli",
"chars": 1361,
"preview": "(* pseudo immediate value *)\n\ntype pseudo_imm =\n | Big of WrapBn.t\n | Int of int\n | DestLabel of Label.label\n | Stor"
},
{
"path": "src/ast/sideEffect.ml",
"chars": 96,
"preview": "type location = Storage | External | Balance\ntype kind = Read | Write\n\ntype t = location * kind\n"
},
{
"path": "src/ast/sideEffect.mli",
"chars": 96,
"preview": "type location = Storage | External | Balance\ntype kind = Read | Write\n\ntype t = location * kind\n"
},
{
"path": "src/ast/syntax.ml",
"chars": 13405,
"preview": "type typ =\n | VoidType\n | Uint256Type\n | Uint8Type\n | Bytes32Type\n | AddressType\n | BoolType\n | ReferenceType of\n"
},
{
"path": "src/ast/syntax.mli",
"chars": 5241,
"preview": "type typ =\n | VoidType (** the result of calling address.default() *)\n | Uint256Type\n | Uint8Type\n | Bytes32Type\n |"
},
{
"path": "src/ast/type.ml",
"chars": 30326,
"preview": "open Syntax\n\n\nlet ident_lookup_type\n (contract_interfaces : Contract.contract_interface Assoc.contract_id_assoc)\n "
},
{
"path": "src/ast/type.mli",
"chars": 120,
"preview": "val assign_types :\n unit Syntax.toplevel Assoc.contract_id_assoc -> Syntax.typ Syntax.toplevel Assoc.contract_id_assoc\n"
},
{
"path": "src/ast/typeEnv.ml",
"chars": 2065,
"preview": "(** The first element is the context for the innermost block *)\ntype type_env =\n { identifiers: Syntax.arg list list\n "
},
{
"path": "src/ast/typeEnv.mli",
"chars": 648,
"preview": "type type_env\n\nval empty_type_env : type_env\nval forget_innermost : type_env -> type_env\nval add_empty_block : type_env "
},
{
"path": "src/basics/META",
"chars": 357,
"preview": "# OASIS_START\n# DO NOT EDIT (digest: 3b4490fa7dbdc2ad5da8665d7c5224d8)\nversion = \"0.0.03\"\ndescription = \"A compiler targ"
},
{
"path": "src/basics/assoc.ml",
"chars": 1210,
"preview": "type contract_id = int\n\ntype 'a contract_id_assoc = (contract_id * 'a) list\n\nlet list_to_contract_id_assoc (lst : 'a lis"
},
{
"path": "src/basics/assoc.mli",
"chars": 998,
"preview": "type contract_id = int\n(* Currently, the location in [contracts] *)\n\ntype 'a contract_id_assoc = (contract_id * 'a) list"
},
{
"path": "src/basics/basics.mldylib",
"chars": 114,
"preview": "# OASIS_START\n# DO NOT EDIT (digest: 544c3466c83774053c2a71824a587891)\nAssoc\nHexa\nLabel\nMisc\nStorage\n# OASIS_STOP\n"
},
{
"path": "src/basics/basics.mllib",
"chars": 114,
"preview": "# OASIS_START\n# DO NOT EDIT (digest: 544c3466c83774053c2a71824a587891)\nAssoc\nHexa\nLabel\nMisc\nStorage\n# OASIS_STOP\n"
},
{
"path": "src/basics/hex_test.ml",
"chars": 515,
"preview": "open Hexa\nopen Evm\n\nlet _ =\n let () = Printf.printf \"testing hex\\n\" in\n let () = assert (string_of_hex empty_hex = \"\")"
},
{
"path": "src/basics/hexa.ml",
"chars": 826,
"preview": "type hex = Rope.t\n\nlet empty_hex = Rope.empty\nlet concat_hex = Rope.concat2\nlet length_of_hex h = Rope.length h / 2\nlet "
},
{
"path": "src/basics/hexa.mli",
"chars": 637,
"preview": "type hex\n\nval empty_hex : hex\nval concat_hex : hex -> hex -> hex\n\n(** [length_of_hex h] returns the length of [h] as the"
},
{
"path": "src/basics/label.ml",
"chars": 695,
"preview": "type label = int\n\nlet debug_label = false\n\n(* internal data not accessible from outside of the module. *)\nlet next_fresh"
},
{
"path": "src/basics/label.mli",
"chars": 577,
"preview": "(* A label is typically put on a jump destination.\n *)\n\ntype label\n\n(** [new label ()] returns a new label each time it "
},
{
"path": "src/basics/misc.ml",
"chars": 403,
"preview": "let rec first_some f lst =\n match lst with\n | [] -> None\n | h :: t ->\n begin match f h with\n | None -> first_"
},
{
"path": "src/basics/misc.mli",
"chars": 335,
"preview": "(** If any element is mapped to [Some x], return the first such one. Otherwise return [None]. *)\nval first_some : ('a ->"
},
{
"path": "src/basics/storage.ml",
"chars": 28,
"preview": "type storage_location = int\n"
},
{
"path": "src/basics/storage.mli",
"chars": 28,
"preview": "type storage_location = int\n"
},
{
"path": "src/codegen/META",
"chars": 364,
"preview": "# OASIS_START\n# DO NOT EDIT (digest: 5601d8fffa94038ded43ae8629ffa980)\nversion = \"0.0.03\"\ndescription = \"A compiler targ"
},
{
"path": "src/codegen/codegen.ml",
"chars": 75587,
"preview": "open PseudoImm\nopen CodegenEnv\nopen Evm\nopen Syntax\n\nlet copy_storage_range_to_stack_top le ce (range : PseudoImm.pseudo"
},
{
"path": "src/codegen/codegen.mldylib",
"chars": 151,
"preview": "# OASIS_START\n# DO NOT EDIT (digest: 2e0624f260757657eae4c2d0f51f273f)\nCodegenEnv\nCodegen\nEntrypointDatabase\nLayoutInfo\n"
},
{
"path": "src/codegen/codegen.mli",
"chars": 2311,
"preview": "type alignment = LeftAligned | RightAligned\n\n(** [codegen_exp original_env exp]\n * is a new codegenEnv where a stack ele"
},
{
"path": "src/codegen/codegen.mllib",
"chars": 151,
"preview": "# OASIS_START\n# DO NOT EDIT (digest: 2e0624f260757657eae4c2d0f51f273f)\nCodegenEnv\nCodegen\nEntrypointDatabase\nLayoutInfo\n"
},
{
"path": "src/codegen/codegenEnv.ml",
"chars": 1714,
"preview": "type t =\n { ce_stack_size: int\n ; ce_program: PseudoImm.pseudo_imm Evm.program\n ; ce_cid_lookup : string -> Assoc.con"
},
{
"path": "src/codegen/codegenEnv.mli",
"chars": 685,
"preview": "(* codegenEnv remembers the current stack size,\n initial storage assumtion, and\n accumulated instructions. *)\ntype t"
},
{
"path": "src/codegen/codegen_test.ml",
"chars": 698,
"preview": "open Syntax\nopen Codegen\n\n(* The following two functions comes from\n * https://github.com/realworldocaml/examples/tree/m"
},
{
"path": "src/codegen/codegen_test2.ml",
"chars": 2349,
"preview": "open Lexer\nopen Lexing\nopen Printf\nopen Syntax\nopen Codegen\n\nlet _ =\n let lexbuf = Lexing.from_channel stdin in\n let c"
},
{
"path": "src/codegen/entrypointDatabase.ml",
"chars": 336,
"preview": "type entrypoint =\n | Contract of Assoc.contract_id\n | Case of Assoc.contract_id * Syntax.case_header\n\nlet store : (ent"
},
{
"path": "src/codegen/entrypointDatabase.mli",
"chars": 214,
"preview": "type entrypoint =\n | Contract of Assoc.contract_id\n | Case of Assoc.contract_id * Syntax.case_header\n\nval register_ent"
},
{
"path": "src/codegen/layoutInfo.ml",
"chars": 10254,
"preview": "(* Layout information that should be available after the constructor compilation finishes *)\ntype layout_info =\n { cont"
},
{
"path": "src/codegen/layoutInfo.mli",
"chars": 4154,
"preview": "(* Layout information that should be available after the constructor compilation finishes *)\ntype layout_info =\n { cont"
},
{
"path": "src/codegen/layouts.txt",
"chars": 526,
"preview": "Storage:\n000: program counter (which contract is it running now?)\n001: n = number of words used in ABI arguments\n002 - 0"
},
{
"path": "src/codegen/locationEnv.ml",
"chars": 3920,
"preview": "open PseudoImm\n\ntype t =\n (string * Location.location) list list\n\nlet size l =\n WrapList.sum (List.map List.length l)\n"
},
{
"path": "src/codegen/locationEnv.mli",
"chars": 1766,
"preview": "type t\n\nval empty_env : t\nval forget_innermost : t -> t\nval add_empty_block : t -> t\n\n(** should maintain the uniqueless"
},
{
"path": "src/codegen/parse.ml",
"chars": 691,
"preview": "open Lexer\nopen Lexing\nopen Printf\n\n(* The following two functions comes from\n * https://github.com/realworldocaml/examp"
},
{
"path": "src/codegen/parse.mli",
"chars": 66,
"preview": "val parse_with_error : Lexing.lexbuf -> unit Syntax.toplevel list\n"
},
{
"path": "src/cross-platform/META",
"chars": 406,
"preview": "# OASIS_START\n# DO NOT EDIT (digest: c13f891232d5c3e0d504b5e1b0eb0164)\nversion = \"0.0.02\"\ndescription = \"A compiler targ"
},
{
"path": "src/cross-platform/cross-platform.mldylib",
"chars": 154,
"preview": "# OASIS_START\n# DO NOT EDIT (digest: 54339adac6e4801bdd3f49aa4a6fd723)\nRope\nWrapBnNative\nWrapCryptokitNative\nWrapListNat"
},
{
"path": "src/cross-platform/cross-platform.mllib",
"chars": 154,
"preview": "# OASIS_START\n# DO NOT EDIT (digest: 54339adac6e4801bdd3f49aa4a6fd723)\nRope\nWrapBnNative\nWrapCryptokitNative\nWrapListNat"
},
{
"path": "src/cross-platform/rope.ml",
"chars": 46587,
"preview": "(* Mostly copied from https://github.com/Chris00/ocaml-rope/blob/master/src/rope.ml\nParts that are modified are marked w"
},
{
"path": "src/cross-platform/wrapBn.ml",
"chars": 464,
"preview": "#if BSB_BACKEND = \"js\" then\n type t = Bn.t\n let to_string_in_hexa = Bn.toString ~base:16\n let string_of_big_int = Bn."
},
{
"path": "src/cross-platform/wrapBnNative.ml",
"chars": 454,
"preview": " type t = Big_int.big_int\n let to_string_in_hexa = BatBig_int.to_string_in_hexa\n let string_of_big_int = Big_int.stri"
},
{
"path": "src/cross-platform/wrapCryptokit.ml",
"chars": 1177,
"preview": "#if BSB_BACKEND = \"js\" then\n (* TODO: Create keccak BuckleScript bindings as a separate module *)\n type keccakInit\n t"
},
{
"path": "src/cross-platform/wrapCryptokitNative.ml",
"chars": 1137,
"preview": " module Hash = Cryptokit.Hash\n let string_keccak str : string =\n let sha3_256 = Hash.keccak 256 in\n let () = sha"
},
{
"path": "src/cross-platform/wrapList.ml",
"chars": 1281,
"preview": "#if BSB_BACKEND = \"js\" then\n let range i j =\n let rec aux n acc = if n < i then acc else aux (n - 1) (n :: acc) in\n "
},
{
"path": "src/cross-platform/wrapListNative.ml",
"chars": 160,
"preview": " let range i j = BatList.(range i `To j)\n let sum = BatList.sum\n let filter_map = BatList.filter_map\n let last = Bat"
},
{
"path": "src/cross-platform/wrapOption.ml",
"chars": 342,
"preview": "#if BSB_BACKEND = \"js\" then\n include Js.Option\n (* Js.Option.map expects the callback to be uncurried\n https://buckle"
},
{
"path": "src/cross-platform/wrapString.ml",
"chars": 107,
"preview": "#if BSB_BACKEND = \"js\" then\n let starts_with = Js.String.startsWith\n#else\n include WrapStringNative\n#end\n"
},
{
"path": "src/cross-platform/wrapStringNative.ml",
"chars": 42,
"preview": " let starts_with = BatString.starts_with\n"
},
{
"path": "src/cross-platform-for-ocamlbuild/META",
"chars": 411,
"preview": "# OASIS_START\n# DO NOT EDIT (digest: ee11ff5ab0dcdc3283bfdeea5feb58b8)\nversion = \"0.0.03\"\ndescription = \"A compiler targ"
},
{
"path": "src/cross-platform-for-ocamlbuild/cross-platform.mldylib",
"chars": 136,
"preview": "# OASIS_START\n# DO NOT EDIT (digest: 5f3e3f97fec314fba146c24e67ee5ea3)\nWrapBn\nWrapCryptokit\nWrapList\nWrapString\nWrapOpti"
},
{
"path": "src/cross-platform-for-ocamlbuild/cross-platform.mllib",
"chars": 136,
"preview": "# OASIS_START\n# DO NOT EDIT (digest: 5f3e3f97fec314fba146c24e67ee5ea3)\nWrapBn\nWrapCryptokit\nWrapList\nWrapString\nWrapOpti"
},
{
"path": "src/cross-platform-for-ocamlbuild/wrapOption.ml",
"chars": 18,
"preview": "include BatOption\n"
},
{
"path": "src/exec/bamboo.ml",
"chars": 2681,
"preview": "open Lexer\nopen Lexing\nopen Printf\nopen Syntax\nopen Codegen\n\n(* The following two functions comes from\n * https://github"
},
{
"path": "src/exec/compileFile.ml",
"chars": 1119,
"preview": "open Codegen\n\nlet compile_file (file : string) : string =\n BatFile.with_file_in\n file\n (fun channel ->\n let "
},
{
"path": "src/exec/compileFile.mli",
"chars": 127,
"preview": "(** [compile_file filename] compiles the source of filename into a constructor bytecode *)\nval compile_file : string -> "
},
{
"path": "src/exec/endToEnd.ml",
"chars": 49239,
"preview": "(* below is largely based on ocaml-rpc *)\n\n(*\n * Copyright (c) 2006-2009 Citrix Systems Inc.\n * Copyright (c) 2006-2014 "
},
{
"path": "src/exec-js/bambooJs.ml",
"chars": 1761,
"preview": "open Lexer\nopen Syntax\nopen Codegen\n\nlet parse_with_error lexbuf =\n try Parser.file Lexer.read lexbuf with\n | SyntaxEr"
},
{
"path": "src/lib/META",
"chars": 315,
"preview": "# OASIS_START\n# DO NOT EDIT (digest: ee03fbfcb0883e448492600c58692ce0)\nversion = \"0.0.01\"\ndescription = \"A compiler targ"
},
{
"path": "src/lib/lib_test.ml",
"chars": 1196,
"preview": "let case0 = (\"pay(address)\", \"0c11dedd\")\n\nlet case1_case : Syntax.usual_case_header =\n Syntax.(\n { case_return_typ = ["
},
{
"path": "src/parse/META",
"chars": 351,
"preview": "# OASIS_START\n# DO NOT EDIT (digest: 82d5d9184cfb0635001b4f2d55e8449d)\nversion = \"0.0.03\"\ndescription = \"A compiler targ"
},
{
"path": "src/parse/README.md",
"chars": 173,
"preview": "# a parser for the Bamboo language\n\nThe basic set up is based on [Real World OCaml Chapter 16](https://realworldocaml.or"
},
{
"path": "src/parse/examples/000nil.bbo",
"chars": 0,
"preview": ""
},
{
"path": "src/parse/examples/001empty.bbo",
"chars": 19,
"preview": "\n\ncontract C() { }\n"
},
{
"path": "src/parse/examples/002comment.bbo",
"chars": 44,
"preview": "\n\ncontract C() {\n// a comment is ignored.\n}\n"
},
{
"path": "src/parse/examples/003default_abort.bbo",
"chars": 50,
"preview": "\n\ncontract C() {\n\tdefault\n {\n\t\tabort;\n }\n}\n\n"
},
{
"path": "src/parse/examples/004simple_case_abort.bbo",
"chars": 99,
"preview": "\n\ncontract C() {\ncase (uint256 f(uint256 _x, uint256 _y))\n{\n abort;\n}\ndefault\n{\n abort;\n}\n}\n\n"
},
{
"path": "src/parse/examples/005auction_start.bbo",
"chars": 119,
"preview": "\n\ncontract auction\n (address _beneficiary\n ,uint256 _bidding_time\n,address => bool _bids\n\t,uint256 _highest_bid)\n{\n}\n"
},
{
"path": "src/parse/examples/006auction_first_case.bbo",
"chars": 229,
"preview": "\n\ncontract auction\n (address _beneficiary\n ,uint256 _bidding_time\n ,address => bool _bids\n ,uint256 _highest_bid)\n{\n"
},
{
"path": "src/parse/examples/007auction_first_case_more.bbo",
"chars": 263,
"preview": "\n\ncontract auction\n (address _beneficiary\n ,uint256 _bidding_time\n,address => bool _bids\n\t,uint256 _highest_bid)\n{\n "
},
{
"path": "src/parse/examples/008new_var.bbo",
"chars": 176,
"preview": "\n\ncontract auction\n (address _beneficiary\n ,uint256 _bidding_time\n,address => bool _bids\n\t,uint256 _highest_bid)\n{\n "
},
{
"path": "src/parse/examples/009new_var_auc.bbo",
"chars": 462,
"preview": "\n\ncontract auction\n (address _beneficiary\n ,uint256 _bidding_time\n,address => bool _bids\n\t,uint256 _highest_bid)\n{\n "
},
{
"path": "src/parse/examples/00a_auc_first_cast.bbo",
"chars": 685,
"preview": "\n\ncontract auction\n (address _beneficiary\n ,uint256 _bidding_time\n,address => bool _bids\n\t,uint256 _highest_bid)\n{\n "
},
{
"path": "src/parse/examples/00b_auction_more.bbo",
"chars": 1104,
"preview": "contract auction\n\t(address _beneficiary\n\t,uint256 _bidding_time\n\t,address => bool _bids\n\t,uint256 _highest_bid)\n{\n\tcase "
},
{
"path": "src/parse/examples/00bbauction_first_named_case.bbo",
"chars": 278,
"preview": "\n\ncontract auction\n (uint256 _highest_bid)\n{\n case(bool bid())\n {\n\tbid new_bid =\n\t\tdeploy bid(sender(msg)) with val"
},
{
"path": "src/parse/examples/00c_auction.bbo",
"chars": 1638,
"preview": "contract auction\n\t(address _beneficiary\n\t,uint256 _bidding_time\n\t,address => bool _bids\n\t,uint256 _highest_bid)\n{\n\tcase "
},
{
"path": "src/parse/examples/00d_auction.bbo",
"chars": 2379,
"preview": "// The contract signature auction(address,uint256,bool[address],uint256) can be used as a continuation\n// of a contract."
},
{
"path": "src/parse/examples/00e_ecdsarecover.bbo",
"chars": 138,
"preview": "contract A() {\n\tcase (address a(bytes32 x, uint8 b, bytes32 c, bytes32 d)) {\n\t\treturn (pre_ecdsarecover(x, b, c, d)) the"
},
{
"path": "src/parse/examples/00f_bytes32.bbo",
"chars": 88,
"preview": "contract A () {\n case(bool f(bytes32 a)) {\n return (true) then become A();\n }\n}"
},
{
"path": "src/parse/examples/00g_int8.bbo",
"chars": 86,
"preview": "contract A () {\n case(bool f(uint8 a)) {\n return (true) then become A();\n }\n}"
},
{
"path": "src/parse/examples/00h_payment_channel.bbo",
"chars": 1013,
"preview": "// based on https://medium.com/@matthewdif/ethereum-payment-channel-in-50-lines-of-code-a94fad2704bc\n\ncontract Channel\n("
},
{
"path": "src/parse/examples/00i_local_bool.bbo",
"chars": 104,
"preview": "contract A () {\n case(bool f(uint8 a)) {\n bool x = true;\n return (x) then become A();\n }\n}"
},
{
"path": "src/parse/examples/010_logical_and.bbo",
"chars": 97,
"preview": "contract A () {\n case (bool f(bool a, bool b)) {\n return (a && b) then become A();\n }\n}"
},
{
"path": "src/parse/examples/011_keccak256.bbo",
"chars": 107,
"preview": "contract A() {\n case(bytes32 f(address a, bytes32 b)) {\n return(keccak256(a, b)) then become A();\n }\n}"
},
{
"path": "src/parse/examples/013_iszero.bbo",
"chars": 94,
"preview": "contract A () {\n case (bool a(bytes32 x))\n {\n return (iszero(x)) then become A();\n }\n}"
},
{
"path": "src/parse/examples/014_ifelse.bbo",
"chars": 167,
"preview": "contract A () {\n case (bool f(bool x, bool y)) {\n if (x) return (true) then become A ();\n else if (y) { return "
},
{
"path": "src/parse/examples/015_ifblock.bbo",
"chars": 113,
"preview": "contract A () {\n case (bool f(bool x)) {\n if(x) {\n return(true) then become A();\n }\n abort;\n }\n}\n"
},
{
"path": "src/parse/examples/016_void.bbo",
"chars": 178,
"preview": "contract A () {\n case(bool pass(address rec, uint256 amount)) {\n void = rec.default() with amount reentrance {"
},
{
"path": "src/parse/examples/017_return_void.bbo",
"chars": 79,
"preview": "contract A () {\n case (void f()) {\n return then become A ();\n }\n}\n"
},
{
"path": "src/parse/examples/018_mapmap.bbo",
"chars": 223,
"preview": "contract A(bool => address => bool mat)\n{\n\tcase (void set(bool x, address y, bool v))\n\t{\n\t\tmat[x][y] = v;\n\t\treturn then "
},
{
"path": "src/parse/examples/019_something.bbo",
"chars": 868,
"preview": "contract PreToken\n(uint256 totalSupply\n,address initialOwner\n,address => uint256 balances\n)\n{\n\tdefault\n\t{\n\t\tbalances[ini"
},
{
"path": "src/parse/examples/01a_event.bbo",
"chars": 140,
"preview": "event E(uint256 indexed a);\n\ncontract A ()\n{\n case(void e(uint256 v)) {\n log E(v);\n return then"
},
{
"path": "src/parse/examples/01b_erc20better.bbo",
"chars": 4066,
"preview": "contract PreToken\n(uint256 totalSupply\n,address => uint256 balances\n,address => address => uint256 allowances\n)\n{\n de"
},
{
"path": "src/parse/examples/020_plus_mult.bbo",
"chars": 117,
"preview": "contract A () {\n case (uint256 f(uint256 a, uint256 b, uint256 c)) {\n return a + b * c then become A();\n }\n}"
},
{
"path": "src/parse/examples/021_land_neq.bbo",
"chars": 95,
"preview": "contract A () {\n case (bool f()) {\n return true && false != true then become A();\n }\n}"
},
{
"path": "src/parse/examples/022_plus_gt.bbo",
"chars": 106,
"preview": "contract A ()\n{\n\tcase(bool f(uint256 a, uint256 b, uint256 c))\n\t{\n\t\treturn a + b < c then become A();\n\t}\n}"
},
{
"path": "src/parse/examples/024_vault.bbo",
"chars": 1318,
"preview": "// Based on http://www.blunderingcode.com/ether-vaults/\n\ncontract Vault(address vaultKey, address recoveryKey) {\n case("
},
{
"path": "src/parse/examples/024_vault_shorter.bbo",
"chars": 1301,
"preview": "// Based on http://www.blunderingcode.com/ether-vaults/\n\ncontract Vault(address vaultKey, address recoveryKey) {\n case("
},
{
"path": "src/parse/examples/025_declit_numeric.bbo",
"chars": 1043,
"preview": "contract A ()\n{\n case(bool f(uint256 a))\n {\n return a < 5 then become A();\n }\n case(uint256 g(uint256"
},
{
"path": "src/parse/examples/026_abc.bbo",
"chars": 246,
"preview": "contract A()\n{\n case (uint256 f()) {\n return 0 then become B();\n }\n}\ncontract B()\n{\n case (uint256 f()) "
},
{
"path": "src/parse/examples/027_counting.bbo",
"chars": 113,
"preview": "contract A(uint256 counter)\n{\n case (uint256 f()) {\n return counter then become A(counter + 1);\n }\n}"
},
{
"path": "src/parse/lexer.mll",
"chars": 1965,
"preview": "(* Some code in this file comes from\n * https://github.com/realworldocaml/examples/tree/master/code/parsing-test\n * whic"
},
{
"path": "src/parse/negative_examples/bad_end.bbo",
"chars": 98,
"preview": "contract A () {\n default {\n void = sender(msg).default() reentrance { abort; };\n }\n}\n"
},
{
"path": "src/parse/negative_examples/duplicate_contract_names.bbo",
"chars": 34,
"preview": "contract C() { }\ncontract C() { }\n"
},
{
"path": "src/parse/negative_examples/mixed_uints.bbo",
"chars": 98,
"preview": "contract A ()\n{\n case(bool f(uint256 a))\n {\n return a < 5u8 then become A();\n }\n}\n"
},
{
"path": "src/parse/negative_examples/multi_default.bbo",
"chars": 78,
"preview": "contract A() {\n default {\n abort;\n }\n\n default {\n abort;\n }\n}\n"
},
{
"path": "src/parse/negative_examples/uint256_too_big.bbo",
"chars": 173,
"preview": "contract A ()\n{\n case(bool f(uint256 a))\n {\n return a < 115792089237316195423570985008687907853269984665640"
},
{
"path": "src/parse/negative_examples/uint8_too_big.bbo",
"chars": 98,
"preview": "contract A ()\n{\n case(bool f(uint8 a))\n {\n return a < 300u8 then become A();\n }\n}\n"
},
{
"path": "src/parse/negative_examples/uint8_with_four_digits.bbo",
"chars": 99,
"preview": "contract A ()\n{\n case(bool f(uint8 a))\n {\n return a < 1029u8 then become A();\n }\n}\n"
},
{
"path": "src/parse/negative_examples/unknown_ctor_arg.bbo",
"chars": 19,
"preview": "contract A(k x) {\n}"
},
{
"path": "src/parse/negative_examples/unknown_return.bbo",
"chars": 138,
"preview": "contract A() {\n\tcase (xyzxyz a(bytes32 x, bytes32 b, uint8 c, bytes32 d)) {\n\t\treturn (pre_ecdsarecover(x, b, c, d)) then"
},
{
"path": "src/parse/negative_examples/unknown_type.bbo",
"chars": 97,
"preview": "contract unknown () {\n case(bool f(xyz k)) {\n return (true) then become unknown();\n }\n}"
},
{
"path": "src/parse/negative_examples/void_not_void.bbo",
"chars": 81,
"preview": "contract A () {\n default {\n void = sender(msg);\n abort;\n }\n}\n"
},
{
"path": "src/parse/negative_examples/void_some_return.bbo",
"chars": 92,
"preview": "contract A () {\n case (void f(address a)) {\n return (a) then become A ();\n }\n}\n"
},
{
"path": "src/parse/negative_examples/wrong_arg.bbo",
"chars": 136,
"preview": "contract A() {\n\tcase (address a(uint8 x, uint8 b, bytes32 c, bytes32 d)) {\n\t\treturn (pre_ecdsarecover(x, b, c, d)) then "
},
{
"path": "src/parse/negative_examples/wrong_return.bbo",
"chars": 85,
"preview": "contract A () {\n case(bool f(uint256 x)) {\n return x then become A();\n }\n}\n"
},
{
"path": "src/parse/parse.mldylib",
"chars": 90,
"preview": "# OASIS_START\n# DO NOT EDIT (digest: c99c8065d9a0587b2171ca8644cac62d)\nLexer\n# OASIS_STOP\n"
},
{
"path": "src/parse/parse.mllib",
"chars": 90,
"preview": "# OASIS_START\n# DO NOT EDIT (digest: c99c8065d9a0587b2171ca8644cac62d)\nLexer\n# OASIS_STOP\n"
},
{
"path": "src/parse/parser.mly",
"chars": 6254,
"preview": "%token CONTRACT\n%token <string> IDENT\n%token <WrapBn.t> DECLIT256\n%token <WrapBn.t> DECLIT8\n%token ADDRESS\n%token UINT25"
},
{
"path": "src/parse/parser_test.ml",
"chars": 819,
"preview": "open Lexer\nopen Lexing\nopen Printf\n\n(* The following two functions comes from\n * https://github.com/realworldocaml/examp"
},
{
"path": "src/run_tests.sh",
"chars": 672,
"preview": "npm run build\nlib_path=\"../lib/bs/native/\"\n$lib_path\"codegen_test.native\" || exit 1\n$lib_path\"lib_test.native\" || exit 1"
}
]
About this extraction
This page contains the full source code of the pirapira/bamboo GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 162 files (710.1 KB), approximately 197.8k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.