| {{/* |
| * Copyright (C) 2015 The Android Open Source Project |
| * |
| * 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. |
| */}} |
| |
| {{Include "common.tmpl"}} |
| |
| |
| {{/* |
| ------------------------------------------------------------------------------- |
| Emits the fully qualified name (prefixed with the package) of the specified |
| type or variable. |
| ------------------------------------------------------------------------------- |
| */}} |
| {{define "Go.QualifiedName"}}{{Global "module"}}{{$.Name}}{{end}} |
| |
| |
| {{/* |
| ------------------------------------------------------------------------------- |
| Emits the go type for the provided AST type or expression. |
| ------------------------------------------------------------------------------- |
| */}} |
| {{define "Go.Type"}} |
| {{if not (IsType $)}}{{Template "Go.Type" (TypeOf $)}} |
| {{else if IsAny $}}interface{} |
| {{else if IsPseudonym $}}{{Template "Go.QualifiedName" $}} |
| {{else if IsStaticArray $}}{{Template "Go.QualifiedName" $}} |
| {{else if IsMap $}}{{Template "Go.QualifiedName" $}} |
| {{else if IsClass $}}{{Template "Go.QualifiedName" $}} |
| {{else if IsEnum $}}{{Template "Go.QualifiedName" $}} |
| {{else if IsPointer $}}{{Template "Go.QualifiedName" $}} |
| {{else if IsSlice $}}{{Template "Go.QualifiedName" $}} |
| {{else if IsReference $}}(*{{Template "Go.Type" $.To}}) |
| {{else if IsBool $}}bool |
| {{else if IsInt $}}int64 |
| {{else if IsUint $}}uint64 |
| {{else if IsChar $}}byte |
| {{else if IsU8 $}}uint8 |
| {{else if IsS8 $}}int8 |
| {{else if IsU16 $}}uint16 |
| {{else if IsS16 $}}int16 |
| {{else if IsF32 $}}float32 |
| {{else if IsU32 $}}uint32 |
| {{else if IsS32 $}}int32 |
| {{else if IsF64 $}}float64 |
| {{else if IsU64 $}}uint64 |
| {{else if IsS64 $}}int64 |
| {{else if IsString $}}string |
| {{else if IsVoid $}}void |
| {{else}}{{Error "macro Type called with unsupported type: %s" $.Name}} |
| {{end}} |
| {{end}} |
| |
| |
| {{/* |
| ------------------------------------------------------------------------------- |
| Emits the go default value for the provided AST type. |
| ------------------------------------------------------------------------------- |
| */}} |
| {{define "Go.Null"}} |
| {{AssertType $ "Type"}} |
| {{ if IsPointer $}}{{Template "Go.Type" $}}{} |
| {{else if IsReference $}}{{Template "Go.Type" $}}(nil) |
| {{else if IsBool $}}false |
| {{else if IsInt $}}int(0) |
| {{else if IsUint $}}uint(0) |
| {{else if IsS8 $}}int8(0) |
| {{else if IsU8 $}}uint8(0) |
| {{else if IsS16 $}}int16(0) |
| {{else if IsU16 $}}uint16(0) |
| {{else if IsS32 $}}int32(0) |
| {{else if IsU32 $}}uint32(0) |
| {{else if IsF32 $}}float32(0) |
| {{else if IsS64 $}}int64(0) |
| {{else if IsU64 $}}uint64(0) |
| {{else if IsF64 $}}float64(0) |
| {{else if IsString $}}"" |
| {{else if IsPseudonym $}}{{Template "Go.Type" $}}({{Template "Go.Null" $.To}}) |
| {{else}}{{Error "macro Type called with unsupported type: %s" $.Name}} |
| {{end}} |
| {{end}} |
| |
| |
| {{/* |
| ------------------------------------------------------------------------------- |
| Emits the logic to decode the specified type and variable name. |
| ErrHandler can control what should happen if there's a decode error. By |
| default ErrHandler is set to "return err". |
| ------------------------------------------------------------------------------- |
| */}} |
| {{define "Go.Decode"}} |
| {{AssertType $.Type "Type" }} |
| {{AssertType $.Name "string" }} |
| {{AssertType $.ErrHandler "string" "nil"}} |
| |
| {{ if not $.ErrHandler}}{{Template "Go.Decode" "Type" $.Type "Name" $.Name "ErrHandler" "return err"}} |
| {{else if IsStaticArray $.Type}}if err := d.Value(&{{$.Name}}); err != nil { {{$.ErrHandler}} } |
| {{else if IsMap $.Type}}if err := d.Value(&{{$.Name}}); err != nil { {{$.ErrHandler}} } |
| {{else if IsClass $.Type}}if err := d.Value(&{{$.Name}}); err != nil { {{$.ErrHandler}} } |
| {{else if IsPointer $.Type}}if err := d.Value(&{{$.Name}}); err != nil { {{$.ErrHandler}} } |
| {{else if IsPseudonym $.Type}} |
| {{$ty := $.Type.To}} |
| {{ if IsStaticArray $ty}}if err := d.Value(&{{$.Name}}); err != nil { {{$.ErrHandler}} } |
| {{else if IsMap $ty}}if err := d.Value(&{{$.Name}}); err != nil { {{$.ErrHandler}} } |
| {{else if IsClass $ty}}if err := d.Value(&{{$.Name}}); err != nil { {{$.ErrHandler}} } |
| {{else if IsPointer $ty}}if err := d.Value(&{{$.Name}}); err != nil { {{$.ErrHandler}} } |
| {{else}}{{Template "Go.DecodePOD" "Type" $ty "Name" $.Name "ErrHandler" $.ErrHandler "Cast" $.Type}} |
| {{end}} |
| {{else}}{{Template "Go.DecodePOD" "Type" $.Type "Name" $.Name "ErrHandler" $.ErrHandler}} |
| {{end}} |
| {{end}} |
| |
| |
| {{/* |
| ------------------------------------------------------------------------------- |
| Emits the logic to decode the specified Plain-Old-Data type and variable name. |
| ErrHandler can control what should happen if there's a decode error. By |
| default ErrHandler is set to "return err". |
| Cast can be used to cast the value type before assigment to Name. |
| ------------------------------------------------------------------------------- |
| */}} |
| {{define "Go.DecodePOD_cast"}}{{if $}}{{Template "Go.Type" $}}(ϟv){{else}}ϟv{{end}}{{end}} |
| {{define "Go.DecodePOD"}} |
| {{AssertType $.Type "Type" }} |
| {{AssertType $.Name "string" }} |
| {{AssertType $.ErrHandler "string" "nil"}} |
| {{AssertType $.Cast "Type" "nil"}} |
| |
| {{$v := Macro "Go.DecodePOD_cast" $.Cast}} |
| {{$int_size := "ϟs.Architecture.IntegerSize*8"}} |
| |
| {{ if IsEnum $.Type}}if ϟv, err := d.Uint32(); err == nil { {{$.Name}} = {{$.Type.Name}}(ϟv) } else { {{$.ErrHandler}} } |
| {{else if IsBool $.Type}}if ϟv, err := d.Bool(); err == nil { {{$.Name}} = {{$v}} } else { {{$.ErrHandler}} } |
| {{else if IsChar $.Type}}if ϟv, err := d.Uint8(); err == nil { {{$.Name}} = {{$v}} } else { {{$.ErrHandler}} } |
| {{else if IsU8 $.Type}}if ϟv, err := d.Uint8(); err == nil { {{$.Name}} = {{$v}} } else { {{$.ErrHandler}} } |
| {{else if IsS8 $.Type}}if ϟv, err := d.Int8(); err == nil { {{$.Name}} = {{$v}} } else { {{$.ErrHandler}} } |
| {{else if IsU16 $.Type}}if ϟv, err := d.Uint16(); err == nil { {{$.Name}} = {{$v}} } else { {{$.ErrHandler}} } |
| {{else if IsS16 $.Type}}if ϟv, err := d.Int16(); err == nil { {{$.Name}} = {{$v}} } else { {{$.ErrHandler}} } |
| {{else if IsF32 $.Type}}if ϟv, err := d.Float32(); err == nil { {{$.Name}} = {{$v}} } else { {{$.ErrHandler}} } |
| {{else if IsU32 $.Type}}if ϟv, err := d.Uint32(); err == nil { {{$.Name}} = {{$v}} } else { {{$.ErrHandler}} } |
| {{else if IsS32 $.Type}}if ϟv, err := d.Int32(); err == nil { {{$.Name}} = {{$v}} } else { {{$.ErrHandler}} } |
| {{else if IsF64 $.Type}}if ϟv, err := d.Float64(); err == nil { {{$.Name}} = {{$v}} } else { {{$.ErrHandler}} } |
| {{else if IsU64 $.Type}}if ϟv, err := d.Uint64(); err == nil { {{$.Name}} = {{$v}} } else { {{$.ErrHandler}} } |
| {{else if IsS64 $.Type}}if ϟv, err := d.Int64(); err == nil { {{$.Name}} = {{$v}} } else { {{$.ErrHandler}} } |
| {{else if IsString $.Type}}if ϟv, err := d.String(); err == nil { {{$.Name}} = {{$v}} } else { {{$.ErrHandler}} } |
| {{else if IsInt $.Type}}if ϟv, err := binary.ReadInt(d, {{$int_size}}); err == nil { {{$.Name}} = {{$v}} } else { {{$.ErrHandler}} } |
| {{else if IsUint $.Type}}if ϟv, err := binary.ReadUint(d, {{$int_size}}); err == nil { {{$.Name}} = {{$v}} } else { {{$.ErrHandler}} } |
| {{else if IsVoid $.Type}} |
| {{else}}{{Error "macro Go.DecodePOD '%v' called with unsupported type: %v" $.Name $.Type.Name}} |
| {{end}} |
| {{end}} |
| |
| |
| {{/* |
| ------------------------------------------------------------------------------- |
| Emits the logic to encode the specified type and variable name. |
| ErrHandler can control what should happen if there's a encode error. By |
| default ErrHandler is set to "return err". |
| ------------------------------------------------------------------------------- |
| */}} |
| {{define "Go.Encode"}} |
| {{AssertType $.Type "Type" }} |
| {{AssertType $.Name "string" }} |
| {{AssertType $.ErrHandler "string" "nil"}} |
| |
| {{$ty := $.Type | Underlying}} |
| {{$int_size := "ϟs.Architecture.IntegerSize*8"}} |
| |
| {{ if not $.ErrHandler}}{{Template "Go.Decode" "Type" $.Type "Name" $.Name "ErrHandler" "return err"}} |
| {{else if IsStaticArray $ty}}if err := e.Value(&{{$.Name}}); err != nil { {{$.ErrHandler}} } |
| {{else if IsMap $ty}}if err := e.Value(&{{$.Name}}); err != nil { {{$.ErrHandler}} } |
| {{else if IsClass $ty}}if err := e.Value(&{{$.Name}}); err != nil { {{$.ErrHandler}} } |
| {{else if IsPointer $ty}}if err := e.Value(&{{$.Name}}); err != nil { {{$.ErrHandler}} } |
| {{else if IsEnum $ty}}if err := e.Uint32(uint32({{$.Name}})); err != nil { {{$.ErrHandler}} } |
| {{else if IsBool $ty}}if err := e.Bool(bool({{$.Name}})); err != nil { {{$.ErrHandler}} } |
| {{else if IsChar $ty}}if err := e.Uint8(uint8({{$.Name}})); err != nil { {{$.ErrHandler}} } |
| {{else if IsU8 $ty}}if err := e.Uint8(uint8({{$.Name}})); err != nil { {{$.ErrHandler}} } |
| {{else if IsS8 $ty}}if err := e.Int8(int8({{$.Name}})); err != nil { {{$.ErrHandler}} } |
| {{else if IsU16 $ty}}if err := e.Uint16(uint16({{$.Name}})); err != nil { {{$.ErrHandler}} } |
| {{else if IsS16 $ty}}if err := e.Int16(int16({{$.Name}})); err != nil { {{$.ErrHandler}} } |
| {{else if IsF32 $ty}}if err := e.Float32(float32({{$.Name}})); err != nil { {{$.ErrHandler}} } |
| {{else if IsU32 $ty}}if err := e.Uint32(uint32({{$.Name}})); err != nil { {{$.ErrHandler}} } |
| {{else if IsS32 $ty}}if err := e.Int32(int32({{$.Name}})); err != nil { {{$.ErrHandler}} } |
| {{else if IsF64 $ty}}if err := e.Float64(float64({{$.Name}})); err != nil { {{$.ErrHandler}} } |
| {{else if IsU64 $ty}}if err := e.Uint64(uint64({{$.Name}})); err != nil { {{$.ErrHandler}} } |
| {{else if IsS64 $ty}}if err := e.Int64(int64({{$.Name}})); err != nil { {{$.ErrHandler}} } |
| {{else if IsString $ty}}if err := e.String(string({{$.Name}})); err != nil { {{$.ErrHandler}} } |
| {{else if IsInt $ty}}if err := binary.WriteInt(e, {{$int_size}}, int64({{$.Name}})); err != nil { {{$.ErrHandler}} } |
| {{else if IsUint $ty}}if err := binary.WriteUint(e, {{$int_size}}, uint64({{$.Name}})); err != nil { {{$.ErrHandler}} } |
| {{else if IsVoid $ty}} |
| {{else}}{{Error "macro Go.Encode '%v' called with unsupported type: %v" $.Name $.Type.Name}} |
| {{end}} |
| {{end}} |
| |
| |
| {{/* |
| ------------------------------------------------------------------------------- |
| Transforms the given string or identifier into a format used for a public Go |
| type or field. Example: |
| this_is_go_public -> ThisIsGoPublic |
| ------------------------------------------------------------------------------- |
| */}} |
| {{define "Go.Public"}} |
| {{AssertType $ "string"}} |
| |
| {{$ | SplitOn "_" | Title}} |
| {{end}} |
| |
| |
| {{/* |
| ------------------------------------------------------------------------------- |
| Transforms the given string or identifier into a format used for a private Go |
| type or field. Example: |
| this_is_go_private -> thisIsGoPrivate |
| ------------------------------------------------------------------------------- |
| */}} |
| {{define "Go.Private"}} |
| {{AssertType $ "string"}} |
| |
| {{$ | SplitOn "_" | Title | Join | Untitle}} |
| {{end}} |
| |
| |
| {{/* |
| ------------------------------------------------------------------------------- |
| Emits the expression to lookup the given parameter. |
| ------------------------------------------------------------------------------- |
| */}} |
| {{define "Go.Parameter"}}{{AssertType $ "Parameter"}}{{Template "Go.Public" $.Name}}{{end}} |
| |
| |
| {{/* |
| ------------------------------------------------------------------------------- |
| Emits the name of the specified command's structure. |
| ------------------------------------------------------------------------------- |
| */}} |
| {{define "Go.CmdName"}} |
| {{AssertType $ "Function"}} |
| |
| {{Macro "CmdName" $ | Title}} |
| {{end}} |
| |
| |
| {{/* |
| ------------------------------------------------------------------------------- |
| Emits the Go logic to simulate the given command. |
| ------------------------------------------------------------------------------- |
| */}} |
| {{define "Go.CommandLogic"}} |
| {{AssertType $ "Function"}} |
| |
| ϟa.observations.ApplyReads(ϟs.Memory[memory.ApplicationPool]) |
| {{Template "Go.Block" $.Block}} |
| {{end}} |
| |
| |
| {{/* |
| ------------------------------------------------------------------------------- |
| Emits all the statements in the given block |
| ------------------------------------------------------------------------------- |
| */}} |
| {{define "Go.Block"}} |
| {{ForEach $.Statements "Go.Statement" | JoinWith "\n"}} |
| {{/* Assign each local variable of the block to a blank identifier, in case it hasn't been used. */}} |
| {{if $locals := ForEach $.Statements "Go.LocalNames"}} |
| {{ForEach $locals "Go.Blank" | JoinWith ", "}} = {{$locals | JoinWith ", "}} |
| {{end}} |
| {{end}} |
| |
| |
| {{/* |
| ------------------------------------------------------------------------------- |
| Emits the Go logic to execute the given statement. |
| If the global "Go.Statement.Override" is specified then this the macro with |
| the specified name is called, otherwise the macro delegates to |
| "Go.Statement.Default". |
| ------------------------------------------------------------------------------- |
| */}} |
| {{define "Go.Statement"}} |
| {{if $override := Global "Go.Statement.Override"}} |
| {{Template $override $}} |
| {{else}} |
| {{Template "Go.Statement.Default" $}} |
| {{end}} |
| {{end}} |
| |
| |
| {{/* |
| ------------------------------------------------------------------------------- |
| Emits the Go logic to execute the given statement. |
| ------------------------------------------------------------------------------- |
| */}} |
| {{define "Go.Statement.Default"}} |
| {{ if IsDeclareLocal $}}{{$.Local.Name}} := {{Template "Go.Read" $.Local.Value}} {{Template "Go.TypeComment" (TypeOf $.Local)}} |
| {{else if IsAssert $}} |
| {{else if IsAssign $}}{{Template "Go.Assign" "LHS" $.LHS "Operator" $.Operator "RHS" $.RHS}} |
| {{else if IsArrayAssign $}}{{Template "Go.ArrayAssign" $}} |
| {{else if IsMapAssign $}}{{Template "Go.MapAssign" $}} |
| {{else if IsSliceAssign $}}{{Template "Go.SliceAssign" $}} |
| {{else if IsCopy $}}{{Error "Copy statement found outside of a Fence"}} |
| {{else if IsReturn $}}{{Template "Go.Assign" "LHS" $.Function.Return "Operator" "=" "RHS" $.Value}} |
| {{else if IsIteration $}}{{Template "Go.Iteration" $}} |
| {{else if IsCall $}}{{Template "Go.Call" $}} |
| {{else if IsRead $}}{{Template "Go.Read" $.Slice}}.OnRead(ϟa, ϟs, ϟd, ϟl, ϟb) |
| {{else if IsWrite $}}{{Template "Go.Read" $.Slice}}.OnWrite(ϟa, ϟs, ϟd, ϟl, ϟb) |
| {{else if IsFence $}}{{Template "Go.Fence" $}} |
| {{else if IsBranch $}}{{Template "Go.Branch" $}} |
| {{else if IsSwitch $}}{{Template "Go.Switch" $}} |
| {{else}}{{Error "unsupported statement %T: %v" $ $}} |
| {{end}} |
| {{end}} |
| |
| |
| {{/* |
| ------------------------------------------------------------------------------- |
| Emits the logic to execute an iteration statement |
| ------------------------------------------------------------------------------- |
| */}} |
| {{define "Go.Range"}} |
| {{AssertType $.Name "string"}} |
| {{AssertType $.Range "BinaryOp"}} |
| for {{$.Name}} := {{Template "Go.Type" $.Range.RHS}}({{Template "Go.Read" $.Range.LHS}}); {{$.Name}} < {{Template "Go.Read" $.Range.RHS}}; {{$.Name}}++ |
| {{end}} |
| |
| {{define "Go.Iteration"}} |
| {{AssertType $ "Iteration"}} |
| {{ if IsBinaryOp $.Iterable}} |
| {{Template "Go.Range" "Name" $.Iterator.Name "Range" $.Iterable}} { |
| {{Template "Go.Block" $.Block}} |
| } |
| {{else}} |
| for _, {{$.Iterator.Name}} := range {{Template "Go.Read" $.Iterable}}.Range() { |
| {{Template "Go.Block" $.Block}} |
| } |
| {{end}} |
| {{end}} |
| |
| |
| {{/* |
| ------------------------------------------------------------------------------- |
| Emits the logic to execute a call statement |
| ------------------------------------------------------------------------------- |
| */}} |
| {{define "Go.Call"}} |
| {{AssertType $ "Call"}} |
| {{$args := ForEach $.Arguments "Go.Read" | JoinWith ", "}} |
| {{if $.Target.Object}} |
| {{Template "Go.Read" $.Target.Object}}.{{$.Target.Function.Name}}({{$args}}) |
| {{else}} |
| externs{ϟa, ϟs, ϟd, ϟl, ϟb}.{{$.Target.Function.Name}}({{$args}}) |
| {{end}} |
| {{end}} |
| |
| |
| {{/* |
| ------------------------------------------------------------------------------- |
| Emits the logic to execute a fence statement |
| ------------------------------------------------------------------------------- |
| */}} |
| {{define "Go.Fence"}} |
| {{AssertType $ "Fence"}} |
| ϟa.observations.ApplyWrites(ϟs.Memory[memory.ApplicationPool]) |
| {{if not (IsNil $.Statement)}} |
| {{if IsCopy $.Statement}} {{/* Copies are only allowed in fences */}} |
| {{Template "Go.Read" $.Statement.Dst}}.Copy({{Template "Go.Read" $.Statement.Src}}, ϟa, ϟs, ϟd, ϟl, ϟb) |
| {{else}} |
| {{Template "Go.Statement" $.Statement}} |
| {{end}} |
| {{end}} |
| {{end}} |
| |
| |
| {{/* |
| ------------------------------------------------------------------------------- |
| Emits the logic to execute a branch statement |
| ------------------------------------------------------------------------------- |
| */}} |
| {{define "Go.Branch"}} |
| {{AssertType $ "Branch"}} |
| if {{Template "Go.Read" $.Condition}} { |
| {{Template "Go.Block" $.True}} |
| {{if len $.False.Statements}} |
| } else { |
| {{Template "Go.Block" $.False}} |
| {{end}} |
| } |
| {{end}} |
| |
| |
| {{/* |
| ------------------------------------------------------------------------------- |
| Emits the logic to execute a switch statement |
| ------------------------------------------------------------------------------- |
| */}} |
| {{define "Go.Switch"}} |
| {{AssertType $ "Switch"}} |
| switch {{Template "Go.Read" $.Value}} { |
| {{range $c := $.Cases}} |
| case {{range $i, $cond := $c.Conditions}}§ |
| {{if $i}}, {{end}}{{Template "Go.Read" $cond}}§ |
| {{end}}: |
| {{Template "Go.Block" $c.Block}} |
| {{end}} |
| default: |
| v := {{Template "Go.Read" $.Value}} |
| return fmt.Errorf("Missing switch case handler for value %T %v", v, v) |
| } |
| {{end}} |
| |
| |
| {{/* |
| ------------------------------------------------------------------------------- |
| Emits the logic to assign the RHS to the LHS |
| ------------------------------------------------------------------------------- |
| */}} |
| {{define "Go.Assign"}} |
| {{if IsIgnore $.LHS}} |
| {{if ne $.Operator "="}}{{Error "Compound assignments to '_' are not supported (%s)" $.Operator}}{{end}} |
| _ = {{Template "Go.Read" $.RHS}} |
| {{else}} |
| {{Template "Go.Read" $.LHS}} {{$.Operator}} {{Template "Go.Read" $.RHS}} |
| {{end}} |
| {{end}} |
| |
| |
| {{/* |
| ------------------------------------------------------------------------------- |
| Emits the logic to assign a value to a static-array index |
| ------------------------------------------------------------------------------- |
| */}} |
| {{define "Go.ArrayAssign"}} |
| {{AssertType $ "ArrayAssign"}} |
| {{Template "Go.Read" $.To.Array}}.Elements[{{Template "Go.Read" $.To.Index}}] {{$.Operator}} {{Template "Go.Read" $.Value}} |
| {{end}} |
| |
| |
| {{/* |
| ------------------------------------------------------------------------------- |
| Emits the logic to assign a value to a map index |
| ------------------------------------------------------------------------------- |
| */}} |
| {{define "Go.MapAssign"}} |
| {{AssertType $ "MapAssign"}} |
| {{if eq $.Operator "="}} |
| {{if IsNull $.Value}} |
| delete({{Template "Go.Read" $.To.Map}}, {{Template "Go.Read" $.To.Index}}) |
| {{else}} |
| {{Template "Go.Read" $.To.Map}}[{{Template "Go.Read" $.To.Index}}] = {{Template "Go.Read" $.Value}} |
| {{end}} |
| {{else}} |
| {{Error "Unsupported MapAssign operator %s" $.Operator}} |
| {{end}} |
| {{end}} |
| |
| |
| {{/* |
| ------------------------------------------------------------------------------- |
| Emits the logic to assign a value to a slice index |
| ------------------------------------------------------------------------------- |
| */}} |
| {{define "Go.SliceAssign"}} |
| {{AssertType $ "SliceAssign"}} |
| {{if ne $.Operator "="}}{{Error "Compound assignments to pointers are not supported (%s)" $.Operator}}{{end}} |
| {{Template "Go.Read" $.To.Slice}}.Index({{Template "Go.Read" $.To.Index}}, ϟs).Write({{Template "Go.Read" $.Value}}, ϟa, ϟs, ϟd, ϟl, ϟb) |
| {{end}} |
| |
| |
| {{/* |
| ------------------------------------------------------------------------------- |
| Emits the Go logic to read the value of the specified expression. |
| If the global "Go.Read.Override" is specified then this the macro with the |
| specified name is called, otherwise the macro delegates to "Go.Read.Default". |
| ------------------------------------------------------------------------------- |
| */}} |
| {{define "Go.Read"}} |
| {{if $override := Global "Go.Read.Override"}} |
| {{Template $override $}} |
| {{else}} |
| {{Template "Go.Read.Default" $}} |
| {{end}} |
| {{end}} |
| |
| |
| {{/* |
| ------------------------------------------------------------------------------- |
| Emits the Go logic to read a slice or pointer, with special handling for |
| inferred expressions. |
| ------------------------------------------------------------------------------- |
| */}} |
| {{define "Go.Memory.Read"}} |
| {{if Global "Go.InferredExpression"}} |
| {{/* |
| If the expression is inferred, then it is the output of a command. |
| When building a replay, Read with ϟb would replace the output memory with |
| observed memory which is undesirable, so instead just map the memory and |
| perform regular (non-replay-builder) read logic. |
| */}} |
| MapMemory(ϟa, ϟs, ϟd, ϟl, ϟb).Read(ϟa, ϟs, ϟd, ϟl, nil) |
| {{else}} |
| Read(ϟa, ϟs, ϟd, ϟl, ϟb) |
| {{end}} |
| {{end}} |
| |
| |
| {{/* |
| ------------------------------------------------------------------------------- |
| Emits the Go logic to execute the given statement. |
| ------------------------------------------------------------------------------- |
| */}} |
| {{define "Go.Read.Default"}} |
| {{ if IsBoolValue $}}{{$}} |
| {{else if IsNumericValue $}}{{Template "Go.Type" $}}({{$}}) |
| {{else if IsUnaryOp $}}{{$.Operator}}({{Template "Go.Read" $.Expression}}) |
| {{else if IsStringValue $}}{{printf "%q" $}} |
| {{else if IsEnumEntry $}}{{$.Owner.Name}}_{{$.Name}} |
| {{else if IsLocal $}}{{$.Name}} |
| {{else if IsBitTest $}}(({{Template "Go.Read" $.Bits}}) & ({{Template "Go.Read" $.Bitfield}}) != 0) |
| {{else if IsBinaryOp $}}({{Template "Go.Read" $.LHS}}) {{$.Operator}} ({{Template "Go.Read" $.RHS}}) |
| {{else if IsCast $}}{{Template "Go.Cast" $}} |
| {{else if IsCall $}}{{Template "Go.Call" $}} |
| {{else if IsUnknown $}}{{Global "Go.InferredExpression" "1"}}{{Template "Go.Read" $.Inferred}}{{Global "Go.InferredExpression" ""}} |
| {{else if IsObserved $}}{{Template "Go.ReadParameter" $.Parameter}} |
| {{else if IsMember $}}{{Template "Go.Read" $.Object}}.{{Template "Go.Public" $.Field.Name}} |
| {{else if IsGlobal $}}ϟc.{{Title $.Name}} |
| {{else if IsParameter $}}{{Template "Go.ReadParameter" $}} |
| {{else if IsMapIndex $}}{{Template "Go.Read" $.Map}}.Get({{Template "Go.Read" $.Index}}) |
| {{else if IsMapContains $}}{{Template "Go.Read" $.Map}}.Contains({{Template "Go.Read" $.Key}}) |
| {{else if IsLength $}}{{Template "Go.Type" $.Type}}({{Template "Go.ReadLength" "Type" (TypeOf $.Object) "Value" $.Object}}) |
| {{else if IsNull $}}{{Template "Go.Null" $.Type}} |
| {{else if IsNew $}}new {{Template "Go.Type" $.Type}} |
| {{else if IsSliceIndex $}}{{Template "Go.Read" $.Slice }}.Index({{Template "Go.Read" $.Index}}, ϟs).{{Macro "Go.Memory.Read"}} |
| {{else if IsSliceRange $}}{{Template "Go.Read" $.Slice }}.Slice({{Template "Go.Read" $.Range.LHS}}, {{Template "Go.Read" $.Range.RHS}}, ϟs) |
| {{else if IsPointerRange $}}{{Template "Go.Read" $.Pointer}}.Slice({{Template "Go.Read" $.Range.LHS}}, {{Template "Go.Read" $.Range.RHS}}, ϟs) |
| {{else if IsClone $}}{{Template "Go.Read" $.Slice }}.Clone(ϟa, ϟs, ϟd, ϟl, ϟb) |
| {{else if IsMake $}}Make{{Template "Go.Type" $.Type}}({{Template "Go.Read" $.Size}}, ϟs) |
| {{else if IsSelect $}}{{Template "Go.Select" $}} |
| {{else if IsArrayInitializer $}}{{Template "Go.ArrayInitializer" $}} |
| {{else if IsClassInitializer $}}{{Template "Go.ClassInitializer" $}} |
| {{else if IsCreate $}}{{Template "Go.Create" $}} |
| {{else}}{{Error "macro Go.Read called with unsupported type: %T" $}} |
| {{end}} |
| {{end}} |
| |
| |
| {{/* |
| ------------------------------------------------------------------------------- |
| Emits the logic to cast a value to another type. |
| ------------------------------------------------------------------------------- |
| */}} |
| {{define "Go.Cast"}} |
| {{AssertType $ "Cast"}} |
| |
| {{$src_ty := $.Object | TypeOf | Underlying | Unpack}} |
| {{$dst_ty := $.Type | Underlying}} |
| {{$src := Macro "Go.Read" $.Object}} |
| |
| {{/* T* -> number */}}{{if and (IsPointer $src_ty) (IsNumericType $dst_ty)}} |
| {{Template "Go.Type" $.Type}}({{$src}}.Address) |
| {{/* A[] -> B[] */}}{{else if and (IsSlice $src_ty) (IsSlice $dst_ty)}} |
| As{{Template "Go.Type" $.Type}}({{$src}}, ϟs) |
| {{/* T[] -> T* */}}{{else if and (IsSlice $src_ty) (IsPointer $dst_ty)}} |
| {{Template "Go.Type" $.Type}}({{$src}}.Index(0, ϟs)) |
| {{/* char* -> string */}}{{else if and (IsPointer $src_ty) (IsString $dst_ty)}} |
| strings.TrimRight(string({{$src}}.StringSlice(ϟs, ϟd, ϟl).{{Macro "Go.Memory.Read"}}), "\x00") |
| {{/* char[] -> string */}}{{else if and (IsSlice $src_ty) (IsString $dst_ty)}} |
| string({{$src}}.{{Macro "Go.Memory.Read"}}) |
| {{/* string[] -> char[] */}}{{else if and (IsString $src_ty) (IsSlice $dst_ty)}} |
| Make{{Template "Go.Type" $.Type}}FromString({{$src}}, ϟs) |
| {{else}} |
| {{Template "Go.Type" $.Type}}({{$src}}) |
| {{end}} |
| {{end}} |
| |
| |
| {{/* |
| ------------------------------------------------------------------------------- |
| Emits the logic to read the value of the specified expression. |
| ------------------------------------------------------------------------------- |
| */}} |
| {{define "Go.ReadParameter"}} |
| {{AssertType $ "Parameter"}} |
| |
| ϟa.{{Template "Go.Public" $.Name}} |
| {{end}} |
| |
| |
| {{/* |
| ------------------------------------------------------------------------------- |
| Emits the logic to perform a select experssion. |
| ------------------------------------------------------------------------------- |
| */}} |
| {{define "Go.Select"}} |
| {{AssertType $ "Select"}} |
| |
| func() (result {{Template "Go.Type" $}}) { |
| switch {{Template "Go.Read" $.Value}} { |
| {{range $c := $.Choices}} |
| case {{range $i, $cond := $c.Conditions}}§ |
| {{if $i}}, {{end}}{{Template "Go.Read" $cond}}§ |
| {{end}}: |
| return {{Template "Go.Read" $c.Expression}} |
| {{end}} |
| default: |
| // TODO: better unmatched handling |
| panic(fmt.Errorf("Unmatched switch(%v) in atom %T", {{Template "Go.Read" $.Value}}, ϟa)) |
| return result |
| } |
| }() |
| {{end}} |
| |
| |
| {{/* |
| ------------------------------------------------------------------------------- |
| Emits the logic to initialize a new instance of an array. |
| ------------------------------------------------------------------------------- |
| */}} |
| {{define "Go.ArrayInitializer"}} |
| {{AssertType $ "ArrayInitializer"}} |
| |
| {{$a := $.Array | Underlying | Unpack}} |
| {{Template "Go.Type" $}}{ Elements: [{{$a.Size}}]{{Template "Go.Type" $a.ValueType}}{ {{ForEach $.Values "Go.Read" | JoinWith ", "}} } } |
| {{end}} |
| |
| |
| {{/* |
| ------------------------------------------------------------------------------- |
| Emits the logic to initialize a new instance of a class. |
| ------------------------------------------------------------------------------- |
| */}} |
| {{define "Go.ClassInitializer"}} |
| {{AssertType $ "ClassInitializer"}} |
| |
| func(){{Template "Go.Type" $}}{ |
| s := {{Template "Go.Type" $}}{} |
| s.Init() |
| {{range $f := $.Fields}} |
| s.{{$f.Field.Name}} = {{Template "Go.Read" $f.Value}} |
| {{end}} |
| return s |
| }() |
| {{end}} |
| |
| |
| {{/* |
| ------------------------------------------------------------------------------- |
| Emits the logic to return a pointer to a new instance of a class. |
| ------------------------------------------------------------------------------- |
| */}} |
| {{define "Go.Create"}} |
| {{AssertType $ "Create"}} |
| |
| func(){{Template "Go.Type" $}}{ |
| s := &{{Template "Go.Type" (Unpack $.Type).To}}{} |
| s.Init() |
| {{range $f := $.Initializer.Fields}} |
| s.{{$f.Field.Name}} = {{Template "Go.Read" $f.Value}} |
| {{end}} |
| return s |
| }() |
| {{end}} |
| |
| |
| {{/* |
| ------------------------------------------------------------------------------- |
| Emits a comment displaying the specified type. |
| ------------------------------------------------------------------------------- |
| */}} |
| {{define "Go.TypeComment"}} |
| {{AssertType $ "Type"}} |
| |
| // {{$.Name}} |
| {{end}} |
| |
| |
| {{/* |
| ------------------------------------------------------------------------------- |
| Emits the logic to read the length of the specified expression by |
| Value and Type. |
| ------------------------------------------------------------------------------- |
| */}} |
| {{define "Go.ReadLength"}} |
| {{AssertType $.Type "Type"}} |
| |
| {{$ty := Unpack $.Type}} |
| {{ if IsPseudonym $ty}}{{Template "Go.ReadLength" "Type" $ty.To "Value" $.Value}} |
| {{else if IsSlice $ty}}{{Template "Go.Read" $.Value}}.Count |
| {{else if IsString $ty}}len({{Template "Go.Read" $.Value}}) |
| {{else if IsMap $ty}}len({{Template "Go.Read" $.Value}}) |
| {{else }}{{Error "macro Go.ReadLength called with unsupported type: %v" $.Type}} |
| {{end}} |
| {{end}} |
| |
| |
| {{/* |
| ------------------------------------------------------------------------------- |
| If the given statement is a local variable declaration, return its name. |
| ------------------------------------------------------------------------------- |
| */}} |
| {{define "Go.LocalNames"}} |
| {{if IsDeclareLocal $}}{{$.Local.Name}} |
| {{else if IsFence $}}{{Template "Go.LocalNames" $.Statement}} |
| {{end}} |
| {{end}} |
| |
| |
| {{/* |
| ------------------------------------------------------------------------------- |
| Emits a Go blank identifier, _. |
| ------------------------------------------------------------------------------- |
| */}} |
| {{define "Go.Blank"}}_{{end}} |
| |
| |
| {{/* |
| ------------------------------------------------------------------------------- |
| Emits the size in bytes of the specified type as a uint64 |
| ------------------------------------------------------------------------------- |
| */}} |
| {{define "Go.SizeOf"}} |
| {{AssertType $ "Type"}} |
| |
| {{ if IsPseudonym $}}{{Template "Go.SizeOf" $.To}} |
| {{else if IsVoid $}}uint64(1) |
| {{else if IsBool $}}uint64(1) |
| {{else if IsChar $}}uint64(1) |
| {{else if IsU8 $}}uint64(1) |
| {{else if IsS8 $}}uint64(1) |
| {{else if IsU16 $}}uint64(2) |
| {{else if IsS16 $}}uint64(2) |
| {{else if IsF32 $}}uint64(4) |
| {{else if IsU32 $}}uint64(4) |
| {{else if IsS32 $}}uint64(4) |
| {{else if IsF64 $}}uint64(8) |
| {{else if IsU64 $}}uint64(8) |
| {{else if IsS64 $}}uint64(8) |
| {{else if IsEnum $}}uint64(4) |
| {{else if IsString $}}uint64(ϟs.Architecture.PointerSize) |
| {{else if IsPointer $}}uint64(ϟs.Architecture.PointerSize) |
| {{else if IsInt $}}uint64(ϟs.Architecture.IntegerSize) |
| {{else if IsUint $}}uint64(ϟs.Architecture.IntegerSize) |
| {{else if IsStaticArray $}}{{Template "Go.SizeOf" $.ValueType}}*{{$.Size}} |
| {{else if IsClass $}}func() uint64 { panic("Sizeof class is not yet implemented") }() |
| {{else }}{{Error "macro Go.SizeOf called with unsupported type: %v" $}} |
| {{end}} |
| {{end}} |
| |
| |
| {{/* |
| ------------------------------------------------------------------------------- |
| Returns the replay builder Value holding the specified variable. |
| ------------------------------------------------------------------------------- |
| */}} |
| {{define "Go.Replay.Value"}} |
| {{AssertType $.Type "Type"}} |
| {{AssertType $.Name "string"}} |
| |
| {{if (GetAnnotation $.Type "replay_custom_value")}}{{$.Name}}.value(ϟb, ϟa, ϟs) |
| {{else if IsBool $.Type}}value.Bool({{$.Name}}) |
| {{else if IsS8 $.Type}}value.S8({{$.Name}}) |
| {{else if IsU8 $.Type}}value.U8({{$.Name}}) |
| {{else if IsS16 $.Type}}value.S16({{$.Name}}) |
| {{else if IsU16 $.Type}}value.U16({{$.Name}}) |
| {{else if IsF32 $.Type}}value.F32({{$.Name}}) |
| {{else if IsU32 $.Type}}value.U32({{$.Name}}) |
| {{else if IsS32 $.Type}}value.S32({{$.Name}}) |
| {{else if IsF64 $.Type}}value.F64({{$.Name}}) |
| {{else if IsU64 $.Type}}value.U64({{$.Name}}) |
| {{else if IsS64 $.Type}}value.S64({{$.Name}}) |
| {{else if IsInt $.Type}}value.S64({{$.Name}}) |
| {{else if IsUint $.Type}}value.U64({{$.Name}}) |
| {{else if IsString $.Type}}ϟb.String({{$.Name}}) |
| {{else if IsPointer $.Type}}{{$.Name}}.value() |
| {{else if IsEnum $.Type}}value.U32({{$.Name}}) |
| {{else if IsStaticArray $.Type}}{{$.Name}}.value(ϟb, ϟa, ϟs) |
| {{else if IsPseudonym $.Type}}{{$.Name}}.value(ϟb, ϟa, ϟs) |
| {{else if IsClass $.Type}}{{$.Name}}.value(ϟb, ϟa, ϟs) |
| {{else }}{{Error "macro Go.Replay.Value '%v' called with unsupported type: %s" $.Name $.Type.Name}} |
| {{end}} |
| {{end}} |
| |
| |
| {{/* |
| ------------------------------------------------------------------------------- |
| Emits the replay builder type for the given command return type. |
| ------------------------------------------------------------------------------- |
| */}} |
| {{define "Go.Replay.Type"}} |
| {{AssertType $ "Type"}} |
| |
| {{ if IsPseudonym $}}{{Template "Go.Replay.Type" $.To}} |
| {{else if IsEnum $}}protocol.TypeUint32 |
| {{else if IsBool $}}protocol.TypeBool |
| {{else if IsInt $}}protocol.TypeInt64 |
| {{else if IsUint $}}protocol.TypeUint64 |
| {{else if IsS8 $}}protocol.TypeInt8 |
| {{else if IsU8 $}}protocol.TypeUint8 |
| {{else if IsS16 $}}protocol.TypeInt16 |
| {{else if IsU16 $}}protocol.TypeUint16 |
| {{else if IsS32 $}}protocol.TypeInt32 |
| {{else if IsU32 $}}protocol.TypeUint32 |
| {{else if IsF32 $}}protocol.TypeFloat |
| {{else if IsS64 $}}protocol.TypeInt64 |
| {{else if IsU64 $}}protocol.TypeUint64 |
| {{else if IsF64 $}}protocol.TypeDouble |
| {{else if IsVoid $}}protocol.TypeVoid |
| {{else if IsString $}}protocol.TypeVolatilePointer |
| {{else if IsPointer $}}protocol.TypeVolatilePointer {{/* TODO: Might be absolute... */}} |
| {{else}}{{Error "macro Go.Replay.Type called with unsupported type: %s" $.Name}} |
| {{end}} |
| {{end}} |
| |
| |
| {{/* |
| ------------------------------------------------------------------------------- |
| Emits a comment stating that the file is automatically generated. |
| ------------------------------------------------------------------------------- |
| */}} |
| {{define "Go.GeneratedHeader"}} |
| {{Copyright "generated" "apic"}}¶ |
| package {{$}}; |
| {{end}} |
| |
| |
| {{/* |
| ------------------------------------------------------------------------------- |
| Emits a comment block containing the specified text. |
| ------------------------------------------------------------------------------- |
| */}} |
| {{define "Go.CommentHeader"}} |
| {{AssertType $ "string"}} {{/* The comment block body text */}} |
| //////////////////////////////////////////////////////////////////////////////// |
| // {{.}} |
| //////////////////////////////////////////////////////////////////////////////// |
| {{end}} |