Skip to content

Latest commit

 

History

History
283 lines (217 loc) · 7.98 KB

docs.org

File metadata and controls

283 lines (217 loc) · 7.98 KB

Dasy Docs

Current Status

Dasy is currently in pre-alpha. The language’s core is still being designed and implemented.

Syntax

Dasy has a clojure-inspired lisp syntax with some influences from python. Some constructs are dasy-specific. Most vyper code can be translated by wrapping in parentheses properly. For example, you can assume that for arr.append(10) in Vyper, the equivalent Dasy is (.append arr 10)

Tuples

Tuples are represented by a quoted list such as '(1 2 3)

The vyper equivalent is (1, 2, 3)

Arrays

Arrays are represented by a bracketed list, such as [1 2 3]

The vyper equivalent is [1, 2, 3]

Types

Dasy has all of Vyper’s types. Base types such as uint256 are represented with a dasy ‘keyword’, which uses a colon and an identifier. Complex types are represented with a function-call syntax. Arrays are created with array, or dyn-array for dynamic arrays.

VyperDasy
uint256:uint256
bool:bool
bytes32:bytes32
String[10](string 10)
uint256[10](array :uint256 10)
HashMap[uint256, bool](hash-map :uint256 :bool)
DynArray[uint256, 5](dyn-array :uint256 5)

Operators

Dasy has mostly identical operators and builtins as Vyper. There are a few small differences.

Built-in chaining

Binary operations are chained by default in Dasy. This allows you to specify more than two arguments at at time.

Because of this, in Dasy, + functions like a sum operator.

VyperDasy
2 + 3 + 4 + 5(+ 2 3 4 5)
x < y and y < z and z < a(< x y z a)

Core Forms

defn

(defn fn-name args [return-type] visibility & body)

This special form declares and defines a function within a smart contract.

The args list may be an empty list, but must be present. Returning multiple values requires declaring the return type as a tuple.

The return-type object is optional. If present, it may be a single keyword representing the return type, or it may be a tuple of keywords for returning multiple values.

The visibility object may also be a keyword or list of keywords. Valid values are:

  • :external
  • :internal
  • :payable
  • :view
  • :pure
  • (nonreentrant "lock-name")
(defn noArgs [] :external (pass))

(defn setNum [:uint256 x] :external (pass))

(defn addNums [:uint256 x y] :uint256 [:external :pure]
  (+ x y))

(defn addAndSub [:uint256 x y] '(:uint256 :uint256) [:external :pure]
  '((+ x y) (- x y)))

defvar

(defvar variable-name type [value])

This special form declares and optionally assigns a value to a variable.

Outside of a defn form, variables are stored in storage and accessible via self.variable-name.

Inside a defn form, variables are stored in memory and accessible directly.

The value form is optional.

(defvar owner (public :address))
(defvar enabled :bool)

(defn foo [] :external
  (defvar owner_memory :address self/owner)) ;; declare copy in memory

set

(set name value)

This special form assigns a value to a name. It is roughly equivalent to the equal sign = in Vyper.

;; Create a string variable that can store maximum 100 characters
(defvar greet (public (string 100)))

(defn __init__ [] :external
    (set self/greet "Hello World")) ;; in vyper: self.greet = "Hello World"

definterface

(definterface name & fns)

This special form declares an interface.

(definterface TestInterface
  (defn owner [] :address :view)
  (defn setOwner [:address owner] :nonpayable)
  (defn sendEth [] :payable)
  (defn setOwnerAndSendEth [:address owner] :payable))

defstruct

(defstruct name & variables)

This special form declares a struct. Variables should be declared in pairs of name and type

(defstruct Person
  name (string 100)
  age :uint256)

defevent

(defevent name & fields)

This special form declares an event. Fields should be declared in pairs of name and type

(defevent Transfer
  sender (indexed :address)
  receiver (indexed :address)
  amount :uint256)

defconst

(defconst name value)

This special form defines a constant. The value must be provided when defined. This value can never change.

(defconst MIN_AMT 100)
(defconst GREETING "Hello")

defmacro

(defmacro name args & body)

This special form defines a macro. Macros are functions that run at compile time. Their inputs are code, and their outputs are code. They transform your code as it is built.

Macros can be used to implement convenient shorthand syntaxes. They can also be used to pull in information from the outside world into your contract at build time.

In the most simple terms, macros allow you to extend the Dasy compiler yourself in whichever way you see fit.

;; (set-at myArr 0 100) -> (set (subscript myArr 0) 100)
(defmacro set-at [array index new-val] `(set (subscript ~array ~index) ~new-val))

;; (doto obj (.append 10) (.append 20)) -> (do (.append obj 10) (.append obj 20))
(defmacro doto [ obj #*cmds]
  (lfor c cmds
        `(~(get c 0) ~obj ~@(cut c 1 None))))

Control Structures

If

(if test body else-body) If executes a test, and depending on the result, either executes the body or the else-body.

(if (x < 100)
*** (return 1) (return 0))

Loops

For Loops

for loops can operate on arrays directly, or on a range

(for [i nums]
  (+= sum i))

(for [i [1 2 3 4 5]]
  (+= sum i))

(for [i (range 10)]
  (+= sum i))

In a for loop’s body, continue and break behave the same as they do in Vyper.

(for [i (range 10)]
  (if (== i 5)
    (continue))
  (+= sum i))

Errors

assert

assert behaves as it does in Vyper. It expects a test and an optional error message.

(assert (< x 100) "x must be less than 100")

raise

raise behaves as it does in Vyper. It expects a message.

(if (>= x 100)
  (raise "x must be less than 100"))

Built-in Macros

/

(set self/foo bar)

Access object attributes. obj/name is shorthand for (. obj name)

cond

(cond & body)

cond saves you from having too many nested if/elses

(if (< x 100)
  100
  (if (< x 1000)
      1000
      (if (< x 10000)
          10000)))

;; this is equivalent
(cond
  (< x 100) 100
  (< x 1000) 1000
  (< x 10000) 10000)

set-at

(set-at obj index val)

Sets a value at an index within an object. This object can be an array, dynamic array, or hashmap.

This expands to (set (subscript array index) new-val)

The vyper equivalent looks like obj[index] = val

(defvar arr (array :uint256 10)
        myMap (hash-map :addr :bool))
(set-at arr 0 100) ;; arr[0] = 100
(set-at myMap 0x1234.... True) ;; myMap[0x1234....] = True

set-in

(set-in obj attr val)

Sets the value of an attribute of an object. This object is usually a struct.

This expands to (set (. obj attr) val)

(defstruct Person
  name (string 10)
  age :uint256)

(defvar p Person)
(set-in p age 40)
(set-in p name "Vitalik")

doto

(doto obj & body)

Call multiple functions on the same object. Allows for shorter code.

(doto obj (.foo 10) (.bar 100)) expands to (do (.foo obj 10) (.bar obj 100))

;; above example rewritten with doto
(defstruct Person
  name (string 10)
  age :uint256)

(doto p
  (defvar Person)
  (set-in age 40)
  (set-in name "Vitalik"))