src/scriptobject/type/ClassBuilder.ps1
# Copyright 2019, Adam Edwards # # 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. # The ClassBuilder translates a system-indepenent class definition into a type # that can be used to create objects of that type in the type system. class ClassBuilder { ClassBuilder([string] $className, [ScriptBlock] $classblock, [string] $constructorName) { $this.className = $className $this.classBlock = $classBlock $this.systemMethodBlocks = @{} $this.systemProperties = @{} $this.constructorName = $constructorName } ClassBuilder([ClassDefinitionContext] $context) { $this.definitionContext = $context $this.className = $context.classDefinition.name $this.classBlock = $null $this.systemMethodBlocks = @{} $this.systemProperties = @{} $this.constructorName = $context.classDefinition.constructorMethodName } [ClassInfo] ToClassInfo([object[]] $classArguments) { $context = if ( $this.definitionContext ) { if ( $classArguments ) { throw 'Class arguments may not be specified when generating class information from an existing definition' } $this.definitionContext } else { $dsl = [ClassDsl]::new($false, $this.systemMethodBlocks, $this.constructorName) $this.definitionContext = $dsl.NewClassDefinitionContext($this.className, $this.classBlock, $classArguments, $null) $this.definitionContext } $basePrototype = $context.classDefinition.ToPrototype($false) $prototype = $this.GetPrototypeObject($basePrototype) $classInfo = [ClassInfo]::new($context.classDefinition, $prototype, $context.module) return $classInfo } [void] AddSystemMethod([string] $methodName, [ScriptBlock] $methodBlock ) { $this.systemMethodBlocks.Add($methodName, $methodBlock) } [void] AddSystemProperty([string] $propertyName, $type, $value) { $this.systemProperties.Add($propertyName, @{name=$propertyName; type=$type; value=$value}) } hidden [object] GetPrototypeObject($basePrototype) { $builder = [NativeObjectBuilder]::new($null, $basePrototype, [NativeObjectBuilderMode]::Modify) if ( $this.systemProperties ) { $this.systemProperties.values | foreach { $builder.AddProperty($_.name, $_.type, $_.value, $_.isReadOnly) } } return $builder.GetObject() } [string] $className = $null [string] $constructorName = $null [ScriptBlock] $classBlock = $null [HashTable] $systemMethodBlocks = $null [HashTable] $systemProperties = $null [ClassDefinitionContext] $definitionContext = $null } |