Documentation
¶
Overview ¶
Copyright Consensys Software Inc.
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.
SPDX-License-Identifier: Apache-2.0
Copyright Consensys Software Inc.
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.
SPDX-License-Identifier: Apache-2.0
Copyright Consensys Software Inc.
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.
SPDX-License-Identifier: Apache-2.0
Copyright Consensys Software Inc.
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.
SPDX-License-Identifier: Apache-2.0
Copyright Consensys Software Inc.
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.
SPDX-License-Identifier: Apache-2.0
Copyright Consensys Software Inc.
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.
SPDX-License-Identifier: Apache-2.0
Copyright Consensys Software Inc.
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.
SPDX-License-Identifier: Apache-2.0
Copyright Consensys Software Inc.
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.
SPDX-License-Identifier: Apache-2.0
Copyright Consensys Software Inc.
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.
SPDX-License-Identifier: Apache-2.0
Copyright Consensys Software Inc.
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.
SPDX-License-Identifier: Apache-2.0
Index ¶
- Variables
- func ImprovedAllocator(allocation RegisterAllocation)
- func LegacyAllocator(allocation RegisterAllocation)
- func RegisterAccessOf(module register.Map, name string, shift int) *hir.RegisterAccess
- func ResolveCircuit(srcmap *source.Maps[ast.Node], circuit *ast.Circuit) (*ModuleScope, []SyntaxError)
- type AllocationComparator
- type BindingId
- type Config
- type DeclPredicate
- type Environment
- type GlobalEnvironment
- func (p GlobalEnvironment) ColumnsOf(register uint) []string
- func (p GlobalEnvironment) Module(mid uint) string
- func (p GlobalEnvironment) ModuleOf(module string) uint
- func (p GlobalEnvironment) Register(index uint) *Register
- func (p GlobalEnvironment) RegisterOf(column *file.Path) uint
- func (p GlobalEnvironment) RegistersOf(module string) []uint
- type GlobalResolution
- type IntrinsicDefinition
- func (p *IntrinsicDefinition) Arity() util.Option[uint]
- func (p *IntrinsicDefinition) Binding() ast.Binding
- func (p *IntrinsicDefinition) IsFinalised() bool
- func (p *IntrinsicDefinition) IsNative() bool
- func (p *IntrinsicDefinition) IsPure() bool
- func (p *IntrinsicDefinition) IsRecursive() bool
- func (p *IntrinsicDefinition) Lisp() sexp.SExp
- func (p *IntrinsicDefinition) Name() string
- func (p *IntrinsicDefinition) Path() *file.Path
- func (p *IntrinsicDefinition) Signature() *ast.FunctionSignature
- type LocalScope
- func (p LocalScope) Bind(symbol ast.Symbol) bool
- func (p LocalScope) Bindings(path file.Path) []BindingId
- func (p *LocalScope) DeclareLocal(name string, binding *ast.LocalVariableBinding) uint
- func (p LocalScope) FixContext(context ast.Context) bool
- func (p LocalScope) IsConstant() bool
- func (p LocalScope) IsGlobal() bool
- func (p LocalScope) IsPure() bool
- func (p LocalScope) IsVisible(symbol ast.Symbol) bool
- func (p LocalScope) IsWithin(path file.Path) bool
- func (p LocalScope) NestedConstScope() LocalScope
- func (p LocalScope) NestedScope() LocalScope
- type ModuleBuilder
- type ModuleResolution
- type ModuleScope
- func (p *ModuleScope) Alias(alias string, symbol ast.Symbol) bool
- func (p *ModuleScope) Bind(symbol ast.Symbol) bool
- func (p *ModuleScope) Binding(name string, arity util.Option[uint]) ast.Binding
- func (p *ModuleScope) Bindings(path file.Path) []BindingId
- func (p *ModuleScope) Children() []*ModuleScope
- func (p *ModuleScope) CloseDefinition(symbol ast.SymbolDefinition)
- func (p *ModuleScope) Declare(submodule string, selector util.Option[string], public bool) bool
- func (p *ModuleScope) Define(symbol ast.SymbolDefinition) bool
- func (p *ModuleScope) DestructuredColumns() []RegisterSource
- func (p *ModuleScope) DestructuredConstants() []ast.ConstantBinding
- func (p *ModuleScope) Enter(submodule string) *ModuleScope
- func (p *ModuleScope) Flatten() []*ModuleScope
- func (p *ModuleScope) IsPublic() bool
- func (p *ModuleScope) IsRoot() bool
- func (p *ModuleScope) IsVisible(symbol ast.Symbol) bool
- func (p *ModuleScope) IsWithin(path file.Path) bool
- func (p *ModuleScope) Name() string
- func (p *ModuleScope) OpenDefinition(symbol ast.SymbolDefinition)
- func (p *ModuleScope) Owner() *ModuleScope
- func (p *ModuleScope) Path() *file.Path
- func (p *ModuleScope) Selector() util.Option[string]
- func (p *ModuleScope) Virtual() bool
- type NativeColumn
- type NativeDefinition
- func (p *NativeDefinition) Apply(args []NativeColumn) []NativeColumn
- func (p *NativeDefinition) Arity() util.Option[uint]
- func (p *NativeDefinition) Binding() ast.Binding
- func (p *NativeDefinition) IsFinalised() bool
- func (p *NativeDefinition) IsNative() bool
- func (p *NativeDefinition) IsPure() bool
- func (p *NativeDefinition) IsRecursive() bool
- func (p *NativeDefinition) Lisp() sexp.SExp
- func (p *NativeDefinition) Name() string
- func (p *NativeDefinition) Path() *file.Path
- func (p *NativeDefinition) Signature() *ast.FunctionSignature
- type Parser
- type Register
- type RegisterAllocation
- type RegisterAllocationView
- type RegisterAllocator
- type RegisterGroup
- func (p *RegisterGroup) Assign(slot uint, reg uint)
- func (p *RegisterGroup) Available(slot uint) bool
- func (p *RegisterGroup) Disjoint(other *RegisterGroup) bool
- func (p *RegisterGroup) IsEmpty() bool
- func (p *RegisterGroup) Merge(other *RegisterGroup)
- func (p *RegisterGroup) String() string
- func (p *RegisterGroup) Target() uint
- type RegisterSlot
- type RegisterSource
- type SchemaBuilder
- type Scope
- type SyntaxError
- func ParseSourceFiles(files []source.File, config Config) (ast.Circuit, *source.Maps[ast.Node], []SyntaxError)
- func PreprocessCircuit(debug bool, srcmap *source.Maps[ast.Node], circuit *ast.Circuit) []SyntaxError
- func TranslateCircuit(env Environment, srcmap *source.Maps[ast.Node], circuit *ast.Circuit, ...) (asm.MicroHirProgram, []SyntaxError)
- func TypeCheckCircuit(srcmap *source.Maps[ast.Node], circuit *ast.Circuit) []SyntaxError
Constants ¶
This section is empty.
Variables ¶
var DEFAULT_ALLOCATOR func(RegisterAllocation) = LegacyAllocator
DEFAULT_ALLOCATOR determines the register allocation algorithm to use by default.
var INTRINSICS []IntrinsicDefinition = []IntrinsicDefinition{
{"+", 1, intrinsicAdd},
{"+", 2, intrinsicAdd},
{"+", 3, intrinsicAdd},
{"+", 4, intrinsicAdd},
{"-", 1, intrinsicSub},
{"-", 2, intrinsicSub},
{"-", 3, intrinsicSub},
{"-", 4, intrinsicSub},
{"*", 1, intrinsicMul},
{"*", 2, intrinsicMul},
{"*", 3, intrinsicMul},
{"*", 4, intrinsicMul},
}
INTRINSICS identifies all of the built-in functions used within the corset language, such as "+", "*", etc. This is needed for two reasons: firstly, so we can alias them; secondly, so they can be used in reductions.
var NATIVE_SIGNATURES []NativeDefinition = []NativeDefinition{
{"id", 1, nativeId},
{"filter", 2, nativeFilter},
{"map-if", 3, nativeMapIf},
{"map-if", 4, nativeMapIf},
{"map-if", 5, nativeMapIf},
{"map-if", 6, nativeMapIf},
{"map-if", 7, nativeMapIf},
{"map-if", 8, nativeMapIf},
{"map-if", 9, nativeMapIf},
{"map-if", 10, nativeMapIf},
{"map-if", 11, nativeMapIf},
{"map-if", 12, nativeMapIf},
{"map-if", 13, nativeMapIf},
{"map-if", 14, nativeMapIf},
{"map-if", 15, nativeMapIf},
{"map-if", 16, nativeMapIf},
{"fwd-changes-within", 2, nativeChangeWithin},
{"fwd-changes-within", 3, nativeChangeWithin},
{"fwd-changes-within", 4, nativeChangeWithin},
{"fwd-changes-within", 5, nativeChangeWithin},
{"fwd-changes-within", 6, nativeChangeWithin},
{"fwd-changes-within", 7, nativeChangeWithin},
{"fwd-changes-within", 8, nativeChangeWithin},
{"fwd-changes-within", 9, nativeChangeWithin},
{"fwd-changes-within", 10, nativeChangeWithin},
{"fwd-changes-within", 11, nativeChangeWithin},
{"fwd-changes-within", 12, nativeChangeWithin},
{"fwd-changes-within", 13, nativeChangeWithin},
{"fwd-changes-within", 14, nativeChangeWithin},
{"fwd-changes-within", 15, nativeChangeWithin},
{"fwd-changes-within", 16, nativeChangeWithin},
{"fwd-unchanged-within", 2, nativeChangeWithin},
{"fwd-unchanged-within", 3, nativeChangeWithin},
{"fwd-unchanged-within", 4, nativeChangeWithin},
{"fwd-unchanged-within", 5, nativeChangeWithin},
{"fwd-unchanged-within", 6, nativeChangeWithin},
{"fwd-unchanged-within", 7, nativeChangeWithin},
{"fwd-unchanged-within", 8, nativeChangeWithin},
{"fwd-unchanged-within", 9, nativeChangeWithin},
{"fwd-unchanged-within", 10, nativeChangeWithin},
{"fwd-unchanged-within", 11, nativeChangeWithin},
{"fwd-unchanged-within", 12, nativeChangeWithin},
{"fwd-unchanged-within", 13, nativeChangeWithin},
{"fwd-unchanged-within", 14, nativeChangeWithin},
{"fwd-unchanged-within", 15, nativeChangeWithin},
{"fwd-unchanged-within", 16, nativeChangeWithin},
{"bwd-changes-within", 2, nativeChangeWithin},
{"bwd-changes-within", 3, nativeChangeWithin},
{"bwd-changes-within", 4, nativeChangeWithin},
{"bwd-changes-within", 5, nativeChangeWithin},
{"bwd-changes-within", 6, nativeChangeWithin},
{"bwd-changes-within", 7, nativeChangeWithin},
{"bwd-changes-within", 8, nativeChangeWithin},
{"bwd-changes-within", 9, nativeChangeWithin},
{"bwd-changes-within", 10, nativeChangeWithin},
{"bwd-changes-within", 11, nativeChangeWithin},
{"bwd-changes-within", 12, nativeChangeWithin},
{"bwd-changes-within", 13, nativeChangeWithin},
{"bwd-changes-within", 14, nativeChangeWithin},
{"bwd-changes-within", 15, nativeChangeWithin},
{"bwd-changes-within", 16, nativeChangeWithin},
{"fwd-fill-within", 3, nativeFillWithin},
{"bwd-fill-within", 3, nativeFillWithin},
}
NATIVE_SIGNATURES identifies all built-in native computations which can be used in defcomputed assignments.
Functions ¶
func ImprovedAllocator ¶
func ImprovedAllocator(allocation RegisterAllocation)
ImprovedAllocator provides an improved register allocation algorithm over the legacy allocator. However, it is not safe to use at this time.
func LegacyAllocator ¶
func LegacyAllocator(allocation RegisterAllocation)
LegacyAllocator is the original register allocation algorithm used in Corset. This is retained for backwards compatibility reasons, but should eventually be dropped.
func RegisterAccessOf ¶
RegisterAccessOf returns a register accessor for the register with the given name.
func ResolveCircuit ¶
func ResolveCircuit(srcmap *source.Maps[ast.Node], circuit *ast.Circuit) (*ModuleScope, []SyntaxError)
ResolveCircuit resolves all symbols declared and used within a circuit, producing an environment which can subsequently be used to look up the relevant module or column identifiers. This process can fail, of course, if a symbol (e.g. a column) is referred to which doesn't exist. Likewise, if two modules or columns with identical names are declared in the same scope, etc.
Types ¶
type AllocationComparator ¶
type AllocationComparator = func(*RegisterGroup, *RegisterGroup) bool
AllocationComparator is a binary predicate over register groups used to determine when two groups can be merged.
type BindingId ¶
type BindingId struct {
// contains filtered or unexported fields
}
BindingId is an identifier is used to distinguish different forms of binding, as some forms are known from their use. Specifically, at the current time, only functions are distinguished from other categories (e.g. columns, parameters, etc).
func (BindingId) IsFunction ¶
IsFunction checks whether or not this binding identifier refers to a function definition or not.
type Config ¶
type Config struct {
// Enable standard library
Stdlib bool
// Enable debug constraints
Debug bool
// Enable legacy register allocator
Legacy bool
// Enforce all types by default
EnforceTypes bool
// Enforce types for all limbs arising from splitting registers
EnforceLimbTypes bool
// Target field configuration. This is only used to assist in reporting
// errors which are specific to the given field configuration.
Field field.Config
}
Config encapsulates various options which can affect compilation.
type DeclPredicate ¶
type DeclPredicate = array.Predicate[ast.Declaration]
DeclPredicate is a shorthand notation.
type Environment ¶
type Environment interface {
// Register returns the name of the given module.
Module(index uint) string
// Module returns information about a given module, such as its module
// identifier.
ModuleOf(module string) uint
// Register returns information about a given register, based on its index
// (i.e. underlying HIR column identifier).
Register(index uint) *Register
// RegisterOf identifies the register (i.e. underlying (HIR) column) to
// which a given source-level (i.e. corset) column is allocated. This
// expects an absolute path.
RegisterOf(path *file.Path) uint
// RegistersOf identifies the set of registers (i.e. underlying (HIR)
// columns) associated with a given module.
RegistersOf(module string) []uint
}
Environment provides an interface into the global scope which can be used for simply resolving column identifiers.
type GlobalEnvironment ¶
type GlobalEnvironment struct {
// contains filtered or unexported fields
}
GlobalEnvironment is a wrapper around a global scope. The point, really, is to signal the change between a global scope whose columns have yet to be allocated, from an environment whose columns are allocated.
func NewGlobalEnvironment ¶
func NewGlobalEnvironment(root *ModuleScope, allocator func(RegisterAllocation)) GlobalEnvironment
NewGlobalEnvironment constructs a new global environment from a global scope by allocating appropriate identifiers to all columns. This process is parameterised upon a given register allocator, thus enabling different allocation algorithms.
func (GlobalEnvironment) ColumnsOf ¶
func (p GlobalEnvironment) ColumnsOf(register uint) []string
ColumnsOf returns the set of registers allocated to a given column.
func (GlobalEnvironment) Module ¶
func (p GlobalEnvironment) Module(mid uint) string
Module returns information about a given module, such as its module identifier.
func (GlobalEnvironment) ModuleOf ¶
func (p GlobalEnvironment) ModuleOf(module string) uint
ModuleOf returns the internal index of the given module.
func (GlobalEnvironment) Register ¶
func (p GlobalEnvironment) Register(index uint) *Register
Register returns information about a given register, based on its index (i.e. underlying HIR column identifier).
func (GlobalEnvironment) RegisterOf ¶
func (p GlobalEnvironment) RegisterOf(column *file.Path) uint
RegisterOf identifies the register (i.e. underlying (HIR) column) to which a given source-level (i.e. corset) column is allocated.
func (GlobalEnvironment) RegistersOf ¶
func (p GlobalEnvironment) RegistersOf(module string) []uint
RegistersOf identifies the set of registers (i.e. underlying (HIR) columns) associated with a given module.
type GlobalResolution ¶
type GlobalResolution struct {
// contains filtered or unexported fields
}
GlobalResolution maintains detailed state about the ongoing attempt to resolve all declarations in a given circuit.
func NewGlobalResolution ¶
NewGlobalResolution simply initialises an appropriate state object for the given circuit.
func (*GlobalResolution) BeginIteration ¶
func (p *GlobalResolution) BeginIteration()
BeginIteration signals that a new iteration is beginning.
func (*GlobalResolution) Continue ¶
func (p *GlobalResolution) Continue() bool
Continue determines whether or not to continue onto another iteration.
func (*GlobalResolution) Enter ¶
func (p *GlobalResolution) Enter(index int) ModuleResolution
Enter returns the state for a given module.
func (*GlobalResolution) Errors ¶
func (p *GlobalResolution) Errors() []SyntaxError
Errors simply returns any error messages arising.
type IntrinsicDefinition ¶
type IntrinsicDefinition struct {
// contains filtered or unexported fields
}
IntrinsicDefinition is a SymbolDefinition for an intrinsic (i.e. built-in) operation, such as "+", "-", etc. These are needed for two reasons: firstly, so we can alias them; secondly, so they can be used in reductions.
func (*IntrinsicDefinition) Arity ¶
func (p *IntrinsicDefinition) Arity() util.Option[uint]
Arity indicates whether or not this is a function and, if so, what arity (i.e. how many arguments) the function has.
func (*IntrinsicDefinition) Binding ¶
func (p *IntrinsicDefinition) Binding() ast.Binding
Binding returns the binding associated with this intrinsic.
func (*IntrinsicDefinition) IsFinalised ¶
func (p *IntrinsicDefinition) IsFinalised() bool
IsFinalised checks whether this binding has been finalised yet or not.
func (*IntrinsicDefinition) IsNative ¶
func (p *IntrinsicDefinition) IsNative() bool
IsNative checks whether this function binding is native (or not).
func (*IntrinsicDefinition) IsPure ¶
func (p *IntrinsicDefinition) IsPure() bool
IsPure checks whether this pure (which intrinsics always are).
func (*IntrinsicDefinition) IsRecursive ¶
func (p *IntrinsicDefinition) IsRecursive() bool
IsRecursive implementation for Binding interface.
func (*IntrinsicDefinition) Lisp ¶
func (p *IntrinsicDefinition) Lisp() sexp.SExp
Lisp returns a lisp representation of this intrinsic.
func (*IntrinsicDefinition) Name ¶
func (p *IntrinsicDefinition) Name() string
Name returns the name of the intrinsic being defined.
func (*IntrinsicDefinition) Path ¶
func (p *IntrinsicDefinition) Path() *file.Path
Path returns the qualified name (i.e. absolute path) of this symbol. For example, "m1.X" for a column X defined in module m1.
func (*IntrinsicDefinition) Signature ¶
func (p *IntrinsicDefinition) Signature() *ast.FunctionSignature
Signature returns the function signature for this binding.
type LocalScope ¶
type LocalScope struct {
// contains filtered or unexported fields
}
LocalScope represents a simple implementation of scope in which local variables can be declared. A local scope must have a single context associated with it, and this will be inferred by resolving those expressions which must be evaluated within.
func NewLocalScope ¶
func NewLocalScope(enclosing Scope, global bool, pure bool, constant bool) LocalScope
NewLocalScope constructs a new local scope within a given enclosing scope. A local scope can have local variables declared within it. A local scope can also be "global" in the sense that accessing symbols from other modules is permitted.
func (LocalScope) Bind ¶
func (p LocalScope) Bind(symbol ast.Symbol) bool
Bind looks up a given variable or function being referenced either within the enclosing scope (module==nil) or within a specified module.
func (LocalScope) Bindings ¶
func (p LocalScope) Bindings(path file.Path) []BindingId
Bindings returns all binding identifiers within a given path.
func (*LocalScope) DeclareLocal ¶
func (p *LocalScope) DeclareLocal(name string, binding *ast.LocalVariableBinding) uint
DeclareLocal registers a new local variable (e.g. a parameter).
func (LocalScope) FixContext ¶
func (p LocalScope) FixContext(context ast.Context) bool
FixContext fixes the context for this scope. Since every scope requires exactly one context, this fails if we fix it to incompatible contexts.
func (LocalScope) IsConstant ¶
func (p LocalScope) IsConstant() bool
IsConstant determines whether or not this scope is defining a constant. This places some restrictions on what variables can be accessed, etc.
func (LocalScope) IsGlobal ¶
func (p LocalScope) IsGlobal() bool
IsGlobal determines whether symbols can be accessed in modules other than the enclosing module.
func (LocalScope) IsPure ¶
func (p LocalScope) IsPure() bool
IsPure determines whether or not this scope is pure. That is, whether or not expressions in this scope are permitted to access columns (either directly, or indirectly via impure invocations).
func (LocalScope) IsVisible ¶
func (p LocalScope) IsVisible(symbol ast.Symbol) bool
IsVisible implemention for Scope interface.
func (LocalScope) IsWithin ¶
func (p LocalScope) IsWithin(path file.Path) bool
IsWithin checks whether a given path is local to the enclosing module, or not.
func (LocalScope) NestedConstScope ¶
func (p LocalScope) NestedConstScope() LocalScope
NestedConstScope creates a nested scope within this local scope which, in addition, is always pure and expects a constant value.
func (LocalScope) NestedScope ¶
func (p LocalScope) NestedScope() LocalScope
NestedScope creates a nested scope within this local scope.
type ModuleBuilder ¶
type ModuleBuilder = ir.ModuleBuilder[word.BigEndian, hir.Constraint, hir.Term]
ModuleBuilder is used within this translator for building the various modules which are contained within the mixed HIR schema.
type ModuleResolution ¶
type ModuleResolution struct {
// contains filtered or unexported fields
}
ModuleResolution provides a handy interface for resolving declarations within a given module. It is really just a wrapper around the global resolution state.
func (*ModuleResolution) AlreadyFailed ¶
func (p *ModuleResolution) AlreadyFailed(decl int) bool
AlreadyFailed can be used to determine whether a given declaration within the module already failed in a previous iteration. This is useful to prevent reattempts to resolve the declaration (which would lead to duplicate errors, etc).
func (*ModuleResolution) Completed ¶
func (p *ModuleResolution) Completed(decl int)
Completed indicates a given declaration within the module has been resolved.
func (*ModuleResolution) Failed ¶
func (p *ModuleResolution) Failed(decl int, errs []SyntaxError)
Failed indicates a given declaration within the module has failed resolution and generated one or more errors.
type ModuleScope ¶
type ModuleScope struct {
// contains filtered or unexported fields
}
ModuleScope defines recursive tree of scopes where symbols can be resolved and bound. The primary goal is to handle the various ways in which a symbol's qualified name (i.e. path) can be expressed. For example, a symbol can be given an absolute name (which is resolved from the root of the scope tree), or it can be relative (in which case it is resolved relative to a given module).
func NewModuleScope ¶
func NewModuleScope(public bool) *ModuleScope
NewModuleScope constructs an initially empty top-level scope.
func (*ModuleScope) Alias ¶
func (p *ModuleScope) Alias(alias string, symbol ast.Symbol) bool
Alias constructs an alias for an existing symbol. If the symbol does not exist, then this returns false.
func (*ModuleScope) Bind ¶
func (p *ModuleScope) Bind(symbol ast.Symbol) bool
Bind looks up a given variable being referenced within a given module. For a root context, this is either a column, an alias or a function declaration.
func (*ModuleScope) Binding ¶
Binding returns information about the binding of a particular symbol defined in this module.
func (*ModuleScope) Bindings ¶
func (p *ModuleScope) Bindings(path file.Path) []BindingId
Bindings returns all binding identifiers within a given path.
func (*ModuleScope) Children ¶
func (p *ModuleScope) Children() []*ModuleScope
Children returns the set of submodules defined within this module.
func (*ModuleScope) CloseDefinition ¶
func (p *ModuleScope) CloseDefinition(symbol ast.SymbolDefinition)
CloseDefinition indicates that the given symbol has now been defined.
func (*ModuleScope) Declare ¶
Declare a new submodule at the given (absolute) path within this tree scope. Submodules can be declared as "virtual" which indicates the submodule is simply a subset of rows of its enclosing module. A virtual module is indicated by a non-zero selector, which signals when the virtual module is active. This returns true if this succeeds, otherwise returns false (i.e. a matching submodule already exists).
func (*ModuleScope) Define ¶
func (p *ModuleScope) Define(symbol ast.SymbolDefinition) bool
Define a new symbol within this scope.
func (*ModuleScope) DestructuredColumns ¶
func (p *ModuleScope) DestructuredColumns() []RegisterSource
DestructuredColumns returns the set of (destructured) columns defined within this module scope. That is, source-level columns which are broken down into their atomic components.
func (*ModuleScope) DestructuredConstants ¶
func (p *ModuleScope) DestructuredConstants() []ast.ConstantBinding
DestructuredConstants returns the set of (destructured) constant definitions within this module scope.
func (*ModuleScope) Enter ¶
func (p *ModuleScope) Enter(submodule string) *ModuleScope
Enter returns a given submodule within this module.
func (*ModuleScope) Flatten ¶
func (p *ModuleScope) Flatten() []*ModuleScope
Flatten flattens the tree into a flat array of modules, such that a module always comes before its own submodules.
func (*ModuleScope) IsPublic ¶
func (p *ModuleScope) IsPublic() bool
IsPublic determines whether or not this is an externally visible module.
func (*ModuleScope) IsRoot ¶
func (p *ModuleScope) IsRoot() bool
IsRoot checks whether or not this is the root of the module tree.
func (*ModuleScope) IsVisible ¶
func (p *ModuleScope) IsVisible(symbol ast.Symbol) bool
IsVisible implemention for Scope interface.
func (*ModuleScope) IsWithin ¶
func (p *ModuleScope) IsWithin(path file.Path) bool
IsWithin checks whether a given path is local to the enclosing module, or not.
func (*ModuleScope) Name ¶
func (p *ModuleScope) Name() string
Name returns the name of the given module.
func (*ModuleScope) OpenDefinition ¶
func (p *ModuleScope) OpenDefinition(symbol ast.SymbolDefinition)
OpenDefinition indicates that the given symbol is in the process of being defined. This allows us to identify recursive uses of the given symbol (i.e. which arise during the period in which it being defined).
func (*ModuleScope) Owner ¶
func (p *ModuleScope) Owner() *ModuleScope
Owner returns the enclosing non-virtual module of this module. Observe that, if this is a non-virtual module, then it is returned.
func (*ModuleScope) Path ¶
func (p *ModuleScope) Path() *file.Path
Path returns the absolute path of this module.
func (*ModuleScope) Selector ¶
func (p *ModuleScope) Selector() util.Option[string]
Selector gets an MIR unit expression which evaluates to a non-zero value when this module is active. This can be nil if there is no selector (i.e. this is a non-virtual module).
func (*ModuleScope) Virtual ¶
func (p *ModuleScope) Virtual() bool
Virtual identifies whether or not this is a virtual module.
type NativeColumn ¶
type NativeColumn struct {
// contains filtered or unexported fields
}
NativeColumn provides information about a column acting as a parameter or return in a given native function.
type NativeDefinition ¶
type NativeDefinition struct {
// contains filtered or unexported fields
}
NativeDefinition describes a native function, such as specifying how many arguments it requires, etc.
func (*NativeDefinition) Apply ¶
func (p *NativeDefinition) Apply(args []NativeColumn) []NativeColumn
Apply returns the output columns given a set of input columns.
func (*NativeDefinition) Arity ¶
func (p *NativeDefinition) Arity() util.Option[uint]
Arity indicates whether or not this is a function and, if so, what arity (i.e. how many arguments) the function has.
func (*NativeDefinition) Binding ¶
func (p *NativeDefinition) Binding() ast.Binding
Binding returns the binding associated with this intrinsic.
func (*NativeDefinition) IsFinalised ¶
func (p *NativeDefinition) IsFinalised() bool
IsFinalised checks whether this binding has been finalised yet or not.
func (*NativeDefinition) IsNative ¶
func (p *NativeDefinition) IsNative() bool
IsNative checks whether this function binding is native (or not).
func (*NativeDefinition) IsPure ¶
func (p *NativeDefinition) IsPure() bool
IsPure checks whether this pure (which intrinsics always are).
func (*NativeDefinition) IsRecursive ¶
func (p *NativeDefinition) IsRecursive() bool
IsRecursive implementation for Binding interface.
func (*NativeDefinition) Lisp ¶
func (p *NativeDefinition) Lisp() sexp.SExp
Lisp returns a lisp representation of this intrinsic.
func (*NativeDefinition) Name ¶
func (p *NativeDefinition) Name() string
Name returns the name of the intrinsic being defined.
func (*NativeDefinition) Path ¶
func (p *NativeDefinition) Path() *file.Path
Path returns the qualified name (i.e. absolute path) of this symbol. For example, "m1.X" for a column X defined in module m1.
func (*NativeDefinition) Signature ¶
func (p *NativeDefinition) Signature() *ast.FunctionSignature
Signature returns the function signature for this binding.
type Parser ¶
type Parser struct {
// contains filtered or unexported fields
}
Parser implements a simple parser for the Corset language. The parser itself is relatively simplistic and simply packages up the relevant lisp constructs into their corresponding AST forms. This can fail in various ways, such as e.g. a "defconstraint" not having exactly three arguments, etc. However, the parser does not attempt to perform more complex forms of validation (e.g. ensuring that expressions are well-typed, etc) --- that is left up to the compiler.
type Register ¶
type Register struct {
// Context (i.e. module + multiplier) of this register.
Context ast.Context
// Underlying width of this register.
Bitwidth uint
// Common padding value
Padding big.Int
// Source columns of this register
Sources []RegisterSource
// contains filtered or unexported fields
}
Register encapsulates information about a "register" in the underlying constraint system. The rough analogy is that "register allocation" is applied to map Corset columns down to HIR columns (a.k.a. registers). The distinction between columns at the Corset level, and registers at the HIR level is necessary for two reasons: firstly, one corset column can expand to several HIR registers; secondly, register allocation is applied to columns in different perspectives of the same module.
func (*Register) Deactivate ¶
func (r *Register) Deactivate()
Deactivate marks a given register as no longer being required. This happens when one register is merged into another.
func (*Register) IsActive ¶
IsActive determines whether or not this register is "active". Inactive registers should not generally be visible outside of register allocation.
func (*Register) IsInput ¶
IsInput determines whether or not this register represents an input column, or not. NOTE: there is currently an implicit assumption that columns allocated to the same register always have the same "visibility" (i.e. are either all input, or all computed, etc).
type RegisterAllocation ¶
type RegisterAllocation interface {
// Access the set of registers being considered for allocation.
Registers() iter.Iterator[uint]
// Access information about a specific register.
Register(uint) *Register
// Merge one register (src) into another (dst). This marks the source
// register as inactive, but does not otherwise update the register
// assignment. Thus, existing register ids remain valid throughout register
// allocation. Once register allocation is complete, inactive registers are
// then discarded.
Merge(dst uint, src uint)
}
RegisterAllocation is a generic interface to support different "regsiter allocation" algorithms. More specifically, register allocation is the process of allocating columns to their underlying HIR columns (a.k.a registers). This is straightforward when there is a 1-1 mapping from a Corset column to an HIR column. However, this is not always the case. For example, array columns at the Corset level map to multiple columns at the HIR level. Likewise, perspectives allow columns to be reused, meaning that multiple columns at the Corset level can be mapped down to just a single column at the HIR level.
Notes:
* Arrays. These are allocated consecutive columns, as determined by their "width". That is, the size of the array.
* Perspectives. This is where the main challenge lies. Columns in different perspectives can be merged together, but this is only done when they have compatible underlying types.
type RegisterAllocationView ¶
type RegisterAllocationView struct {
// contains filtered or unexported fields
}
RegisterAllocationView provides a view of an environment for the purposes of register allocation, such that only registers in this view will be considered for allocation. This is necessary because we must not attempt to allocate registers across different modules (indeed, contexts) together. Instead, we must allocate registers on a module-by-module basis, etc.
func (*RegisterAllocationView) Len ¶
func (p *RegisterAllocationView) Len() uint
Len returns the number of allocated registers.
func (*RegisterAllocationView) Merge ¶
func (p *RegisterAllocationView) Merge(dst uint, src uint)
Merge one register (src) into another (dst). This will remove the src register, and automatically update all column assignments. Therefore, any register identifier can be potenitally invalided by this operation. This will panic if the registers are incompatible (i.e. have different contexts).
func (*RegisterAllocationView) Register ¶
func (p *RegisterAllocationView) Register(index uint) *Register
Register accesses information about a specific register in this window.
type RegisterAllocator ¶
type RegisterAllocator struct {
// contains filtered or unexported fields
}
RegisterAllocator is a simple, but reasonably effective high-level approach to register allocation. Essentially, perspective columns are sorted by type and then allocated based on their "compatibility". Here, compatibility determines when two registers can be merged (i.e. when they are "compatible"_. This allocator is parameterised over the notion of compatibility in order to support different top-level allocation algorithms.
func NewRegisterAllocator ¶
func NewRegisterAllocator(allocation RegisterAllocation) *RegisterAllocator
NewRegisterAllocator initialises a new greedy sort allocator from an initial allocation with a given compatibility function.
func (*RegisterAllocator) CompactBy ¶
func (p *RegisterAllocator) CompactBy(predicate AllocationComparator)
CompactBy Greedily compact the given allocation using a given "compabitility" comparator.
func (*RegisterAllocator) Finalise ¶
func (p *RegisterAllocator) Finalise()
Finalise the register allocation by merging allocated registers in the same slot.
func (*RegisterAllocator) Width ¶
func (p *RegisterAllocator) Width() uint
Width returns the current number of non-empty groups.
type RegisterGroup ¶
type RegisterGroup struct {
// contains filtered or unexported fields
}
RegisterGroup represents a group of registers which (eventually) will be allocated to the same column. The intuition is that, initially, we begin with a single group for each register. Then, groups are merged together according to the high-level allocation algorithm.
func NewRegisterGroup ¶
func NewRegisterGroup(bitwidth uint, mustProve bool) RegisterGroup
NewRegisterGroup constructs a new (and empty) register group.
func (*RegisterGroup) Assign ¶
func (p *RegisterGroup) Assign(slot uint, reg uint)
Assign a register to a given slot in this group. If the slot is already taken, then this will panic.
func (*RegisterGroup) Available ¶
func (p *RegisterGroup) Available(slot uint) bool
Available determines whether a given slot has been set already.
func (*RegisterGroup) Disjoint ¶
func (p *RegisterGroup) Disjoint(other *RegisterGroup) bool
Disjoint checks whether this allocation and another are disjoint. That is, they do not have registers allocated to the same slot.
func (*RegisterGroup) IsEmpty ¶
func (p *RegisterGroup) IsEmpty() bool
IsEmpty checks whether this group is empty or not. Groups can become empty when they are merged into others.
func (*RegisterGroup) Merge ¶
func (p *RegisterGroup) Merge(other *RegisterGroup)
Merge another allocation into this allocation. This leaves the other allocation in the unused state (i.e. it will be ignored from now on).
func (*RegisterGroup) String ¶
func (p *RegisterGroup) String() string
func (*RegisterGroup) Target ¶
func (p *RegisterGroup) Target() uint
Target returns the register with the least index within this allocation.
type RegisterSlot ¶
type RegisterSlot struct {
// contains filtered or unexported fields
}
RegisterSlot represents a register in a given "slot". The intuition is that each perspective is allocated its own slot. Thus, the goal of register allocation is to group compatible registers in different perspectives (i.e. slots).
func (RegisterSlot) Cmp ¶
func (p RegisterSlot) Cmp(other RegisterSlot) int
Cmp implements the necessary comparator for register slots.
type RegisterSource ¶
type RegisterSource struct {
// Context is a prefix of name which, when they differ, indicates a virtual
// column (i.e. one which is subject to register allocation).
Context file.Path
// Fully qualified (i.e. absolute) Name of source-level column.
Name file.Path
// Length Multiplier of source-level column.
Multiplier uint
// Underlying bitwidth of the source-level column.
Bitwidth uint
// Provability requirement for source-level column.
MustProve bool
// Determines whether this is a Computed column.
Computed bool
// Determines value used for padding
Padding big.Int
// Display modifier
Display string
}
RegisterSource provides necessary information about source-level columns allocated to a given register.
func (*RegisterSource) IsVirtual ¶
func (p *RegisterSource) IsVirtual() bool
IsVirtual indicates whether or not this is a "virtual" column. That is, something which is subject to register allocation (i.e. because it is declared in a perspective).
func (*RegisterSource) Perspective ¶
func (p *RegisterSource) Perspective() string
Perspective returns the name of the "virtual perspective" in which this column exists.
type SchemaBuilder ¶
type SchemaBuilder = ir.SchemaBuilder[word.BigEndian, hir.Constraint, hir.Term]
SchemaBuilder is used within this translator for building the final mixed HIR schema.
type Scope ¶
type Scope interface {
// Attempt to bind a given symbol within this scope. If successful, the
// symbol is then resolved with the appropriate binding. Return value
// indicates whether successful or not.
Bind(ast.Symbol) bool
// Bindings returns all binding identifiers within a given path.
Bindings(file.Path) []BindingId
// Check whether a given path is within the enclosing module, or not.
IsWithin(file.Path) bool
// Check whether the given symbol is in the process of being defined in the
// enclose scope. Thus, if we encounter an this symbol within e.g. some
// expression whilst it is being defined ... we know its a recursive access.
// Depending on how the symbol is defined this may (or may not) result in an
// error.
IsVisible(ast.Symbol) bool
}
Scope represents a region of code in which an expression can be evaluated. The purpose of a scope is to assist with determining what, exactly, a given variable used within an expression refers to. For example, a variable can refer to a column, or a parameter, etc.
type SyntaxError ¶
type SyntaxError = source.SyntaxError
SyntaxError defines the kind of errors that can be reported by this compiler. Syntax errors are always associated with some line in one of the original source files. For simplicity, we reuse existing notion of syntax error from the S-Expression library.
func ParseSourceFiles ¶
func ParseSourceFiles(files []source.File, config Config) (ast.Circuit, *source.Maps[ast.Node], []SyntaxError)
ParseSourceFiles parses zero or more source files producing zero or more modules. Observe that, since a given module can be spread over multiple files, there can be far few modules created than there are source files. This function does more than just parse the individual files, because it additional combines all fragments of the same module together into one place. Thus, you should never expect to see duplicate module names in the returned array.
func PreprocessCircuit ¶
func PreprocessCircuit(debug bool, srcmap *source.Maps[ast.Node], circuit *ast.Circuit) []SyntaxError
PreprocessCircuit performs preprocessing prior to final translation. Specifically, it expands all invocations, reductions and for loops. Thus, final translation is greatly simplified after this step.
func TranslateCircuit ¶
func TranslateCircuit( env Environment, srcmap *source.Maps[ast.Node], circuit *ast.Circuit, config Config) (asm.MicroHirProgram, []SyntaxError)
TranslateCircuit translates the components of a Corset circuit and add them to the schema. By the time we get to this point, all malformed source files should have been rejected already and the translation should go through easily. Thus, whilst syntax errors can be returned here, this should never happen. The mechanism is supported, however, to simplify development of new features, etc.
func TypeCheckCircuit ¶
TypeCheckCircuit performs a type checking pass over the circuit to ensure types are used correctly. Additionally, this resolves some ambiguities arising from the possibility of overloading function calls, etc.