Syntax errors in Main.daml

2019-07-15 03:56发布

问题:

My Main.daml code is as follows:

daml 1.2
module Main where

type CarId = ContractId Car -- for return type on controller actions

template Car
  with
    dealer : Party
    insurer : Party
    vin: Text
    date_vehicle_added: Date
    daily_insurance_rate: Decimal
    daily_rate_APD: Decimal
    covered: Bool --initialize to false and set to true when added
    observers : [Party]
  where
    signatory dealer

    agreement
      toText dealer <> " agrees to pay " <> toText insurer <> " at daily rate of " 

    controller dealer can
      Add_Car : CarId
        with
           startCoverage: Date
        do
        -- Return this car with the start date provided by the dealer
        create this with date_vehicle_added = startCoverage, covered = True


      Remove_Car 
        do
          archive this

setup = scenario do
  dealer1 <- getParty "Clevland_Heights"
  insurance1 <- getParty "Ins"

  car1AddCid <- submit dealer1 do
    carCid <- create Car with
      dealer = dealer1
      insurer = insurance1
      vin = "1A"
      daily_insurance_rate = 1.5 
      daily_rate_APD = 0.16
      covered = False 
      observers = [insurance1]
      date_vehicle_added = "date 1970 Jan 1"  -- must be initialized

    exercise carCid Add_Car with startCoverage = "date 2019 Apr 5"

  submit dealer1 do
    exercise car1AddCid Remove_Car

I am seeing two errors in the 'PROBLEMS' window"

1. error: parse error on input 'do' (43,9).  

This is the line right after the "Remove_Car" choice.

2. error: Data contructor not in scope:Remove_Car

This is the last line of the program.

I tried to pattern the syntax and spacing in my code after Main.daml and Ion.daml of the quickstart application. What is causing these errors?

回答1:

Your Remove_Car choice has a couple of issues.

  1. It's missing a return type. Since it's not returning anything, the return type is Unit, written (): Return_Car : ().
  2. this isn't a contract, it's the body of the contract on which the choice is exercised. Since it's not a contract, it can't be archived. There is, in fact, another keyword self, which does refer to the current contract, but using that wouldn't work either. You'd be archiving the contract within a consuming choice, thus consuming the contract twice -- the sort of double spend DAML stops from happening.

To fix 2., you have three options:

  1. Remove it altogether. Every contract has an inbuilt Archive choice which is authorized by all signatories. As the controller of your Remove_Car choice is the same as the signatory of the contract, it just duplicates Archive.
  2. Just use the consuming nature of a consuming choice:
    Remove_Car : ()
      do return ()
    
  3. Use a nonconsuming choice and the self keyword:
    nonconsuming Remove_Car : ()
      do archive self
    

Stylistically, I would choose option 1 whenever possible and option 2 if I need to give a subset of signatories a way to archive a contract. Using the self keyword is hard to reason about so it's best avoided unless absolutely necessary.



标签: daml