yapcad.dsl package
Subpackages
- yapcad.dsl.runtime package
- Submodules
- yapcad.dsl.runtime.builtins module
- yapcad.dsl.runtime.context module
ExecutionContextExecutionContext.add_error()ExecutionContext.add_require_failure()ExecutionContext.add_warning()ExecutionContext.clear_return()ExecutionContext.command_nameExecutionContext.current_scopeExecutionContext.diagnosticsExecutionContext.emit_resultExecutionContext.get_variable()ExecutionContext.has_errorsExecutionContext.has_warningsExecutionContext.module_nameExecutionContext.new_scope()ExecutionContext.parametersExecutionContext.require_failuresExecutionContext.return_valueExecutionContext.set_emit()ExecutionContext.set_variable()ExecutionContext.should_returnExecutionContext.signal_return()ExecutionContext.source_linesExecutionContext.update_variable()
Scopecreate_context()
- yapcad.dsl.runtime.interpreter module
- yapcad.dsl.runtime.provenance module
- yapcad.dsl.runtime.values module
EmitResultRequireFailureValueassembly_val()bool_val()check_type()coerce_numeric()dict_val()edge_list_val()float_val()int_val()list_val()none_val()path3d_val()point_val()region2d_val()shell_val()solid_val()string_val()surface_val()transform_val()unwrap_value()unwrap_values()vector_val()wrap_value()
- Module contents
- yapcad.dsl.transforms package
- Submodules
- yapcad.dsl.transforms.base module
AstTransformIdentityTransformTransformPipelineTreeTransformTreeTransform.transform()TreeTransform.visit_assignment()TreeTransform.visit_binary_op()TreeTransform.visit_block()TreeTransform.visit_command()TreeTransform.visit_dict_literal()TreeTransform.visit_emit()TreeTransform.visit_expr_statement()TreeTransform.visit_expression()TreeTransform.visit_for()TreeTransform.visit_function_call()TreeTransform.visit_identifier()TreeTransform.visit_if_expr()TreeTransform.visit_index_access()TreeTransform.visit_lambda()TreeTransform.visit_let()TreeTransform.visit_list_comprehension()TreeTransform.visit_list_literal()TreeTransform.visit_literal()TreeTransform.visit_match_expr()TreeTransform.visit_member_access()TreeTransform.visit_method_call()TreeTransform.visit_module()TreeTransform.visit_python_block()TreeTransform.visit_python_expr()TreeTransform.visit_range()TreeTransform.visit_require()TreeTransform.visit_return()TreeTransform.visit_statement()TreeTransform.visit_unary_op()
- yapcad.dsl.transforms.metadata module
- Module contents
Submodules
yapcad.dsl.ast module
Abstract Syntax Tree (AST) node definitions for the yapCAD DSL v2 (Pythonic Syntax).
The AST represents the structure of a parsed DSL program, which can then be type-checked and compiled/interpreted.
Changes from v1: - FunctionDef replaces Command (uses ‘def’ keyword) - VarDecl replaces LetStatement (no ‘let’ keyword, optional type annotation) - AssertStatement replaces RequireStatement - NativeFunction for @native decorated functions - Added PassStatement, WhileStatement, ElifBranch
- class yapcad.dsl.ast.AssertStatement(span: SourceSpan, condition: Expression, message: Expression | None = None)[source]
Bases:
StatementAn assert statement (e.g., assert x > 0, “x must be positive”).
- condition: Expression
- message: Expression | None = None
- class yapcad.dsl.ast.AssignmentStatement(span: SourceSpan, target: Expression, value: Expression)[source]
Bases:
StatementAn assignment to an existing variable (e.g., x = 5).
- target: Expression
- value: Expression
- class yapcad.dsl.ast.AstNode(span: SourceSpan)[source]
Bases:
ABCBase class for all AST nodes.
- accept(visitor: AstVisitor) Any[source]
Accept a visitor for traversal.
- span: SourceSpan
- class yapcad.dsl.ast.BinaryOp(span: SourceSpan, left: Expression, operator: TokenType, right: Expression)[source]
Bases:
ExpressionA binary operation (e.g., a + b, x and y).
- left: Expression
- right: Expression
- class yapcad.dsl.ast.Block(span: SourceSpan, statements: List[Statement], final_expression: Expression | None = None)[source]
Bases:
AstNodeA block of statements (indented block).
In Pythonic syntax, blocks are delimited by indentation (INDENT/DEDENT) rather than braces.
- final_expression: Expression | None = None
- yapcad.dsl.ast.Command
alias of
FunctionDef
- class yapcad.dsl.ast.ComprehensionClause(span: SourceSpan, variable: str, iterable: Expression, conditions: List[Expression] = <factory>)[source]
Bases:
AstNodeA single for clause in a list comprehension.
Represents: for variable in iterable [if condition1] [if condition2] …
Multiple if conditions are allowed per clause, all must be true.
- conditions: List[Expression]
- iterable: Expression
- variable: str
- class yapcad.dsl.ast.ConditionalExpr(span: SourceSpan, condition: Expression, true_branch: Expression, false_branch: Expression)[source]
Bases:
ExpressionA ternary conditional expression (e.g., x if condition else y).
- Unlike IfExpr (which uses blocks), this is for inline expressions:
value: float = a if condition else b
Both branches must be expressions and the else is required.
- condition: Expression
- false_branch: Expression
- true_branch: Expression
- class yapcad.dsl.ast.Decorator(span: SourceSpan, name: str, arguments: List[Expression] = <factory>)[source]
Bases:
AstNodeA decorator (e.g., @native).
- arguments: List[Expression]
- name: str
- class yapcad.dsl.ast.DictLiteral(span: SourceSpan, entries: dict[str, Expression])[source]
Bases:
ExpressionA dictionary literal (e.g., {“key”: value, …}).
- entries: dict[str, Expression]
- class yapcad.dsl.ast.ElifBranch(span: SourceSpan, condition: Expression, body: Block)[source]
Bases:
AstNodeAn elif branch in an if expression/statement.
- condition: Expression
- class yapcad.dsl.ast.EmitStatement(span: SourceSpan, value: Expression, metadata: dict[str, ~yapcad.dsl.ast.Expression]=<factory>)[source]
Bases:
StatementAn emit statement with optional metadata kwargs.
- Syntax:
emit gear # Simple emit emit gear, name=”spur”, material=”steel” # With metadata
- metadata: dict[str, Expression]
- value: Expression
- class yapcad.dsl.ast.ExportStatement(span: SourceSpan, name: str)[source]
Bases:
AstNodeAn export statement (e.g., export function_name).
- name: str
- class yapcad.dsl.ast.ExportUseStatement(span: SourceSpan, module_path: List[str])[source]
Bases:
AstNodeAn export use statement (e.g., export use other.module).
- module_path: List[str]
- class yapcad.dsl.ast.Expression(span: SourceSpan)[source]
Bases:
AstNodeBase class for all expressions.
- class yapcad.dsl.ast.ExpressionStatement(span: SourceSpan, expression: Expression)[source]
Bases:
StatementAn expression used as a statement.
- expression: Expression
- class yapcad.dsl.ast.ForStatement(span: SourceSpan, variable: str, iterable: Expression, body: Block)[source]
Bases:
StatementA for loop (e.g., for i in range(n):).
- iterable: Expression
- variable: str
- class yapcad.dsl.ast.FunctionCall(span: ~yapcad.dsl.tokens.SourceSpan, callee: ~yapcad.dsl.ast.Expression, arguments: ~typing.List[~yapcad.dsl.ast.Expression], named_arguments: dict[str, ~yapcad.dsl.ast.Expression] = <factory>)[source]
Bases:
ExpressionA function or constructor call (e.g., point(1, 2, 3)).
- arguments: List[Expression]
- callee: Expression
- named_arguments: dict[str, Expression]
- class yapcad.dsl.ast.FunctionDef(span: ~yapcad.dsl.tokens.SourceSpan, name: str, parameters: ~typing.List[~yapcad.dsl.ast.Parameter], return_type: ~yapcad.dsl.ast.TypeNode | None, body: ~yapcad.dsl.ast.Block, decorators: ~typing.List[~yapcad.dsl.ast.Decorator] = <factory>, meta_hint: dict | None = None)[source]
Bases:
AstNodeA function definition (uses ‘def’ keyword).
- Syntax:
- def function_name(param1: type1, param2: type2) -> return_type:
…
Replaces the old ‘command’ syntax.
- meta_hint: dict | None = None
- name: str
- class yapcad.dsl.ast.GenericType(span: SourceSpan, name: str, type_args: List[TypeNode])[source]
Bases:
TypeNodeA generic type like ‘list[point3d]’ or ‘dict[str, int]’.
- name: str
- class yapcad.dsl.ast.Identifier(span: SourceSpan, name: str)[source]
Bases:
ExpressionA variable or function name reference.
- name: str
- class yapcad.dsl.ast.IdentifierPattern(span: SourceSpan, name: str)[source]
Bases:
PatternA binding pattern (e.g., ‘match x { case n: … }’).
- name: str
- class yapcad.dsl.ast.IfExpr(span: SourceSpan, condition: Expression, then_branch: Block, elif_branches: List[ElifBranch] = <factory>, else_branch: Block | None = None)[source]
Bases:
ExpressionAn if-else expression (returns a value).
- condition: Expression
- elif_branches: List[ElifBranch]
- class yapcad.dsl.ast.IfStatement(span: SourceSpan, condition: Expression, then_branch: Block, elif_branches: List[ElifBranch] = <factory>, else_branch: Block | None = None)[source]
Bases:
StatementAn if statement (doesn’t return a value).
- Syntax:
- if condition:
…
- elif condition:
…
- else:
…
- condition: Expression
- elif_branches: List[ElifBranch]
- class yapcad.dsl.ast.IndexAccess(span: SourceSpan, object: Expression, index: Expression)[source]
Bases:
ExpressionIndex access (e.g., list[0]).
- index: Expression
- object: Expression
- class yapcad.dsl.ast.LambdaExpr(span: SourceSpan, parameters: List[str], body: Expression)[source]
Bases:
ExpressionA lambda/anonymous function (e.g., (x) => x * 2).
- body: Expression
- parameters: List[str]
- class yapcad.dsl.ast.ListComprehension(span: SourceSpan, element_expr: Expression, clauses: List[ComprehensionClause] = <factory>)[source]
Bases:
ExpressionA list comprehension with one or more for clauses.
- Single clause (original):
[f(x) for x in items if cond]
- Multiple clauses (nested):
[f(x, y) for x in xs for y in ys] [f(x, y) for x in xs for y in ys if x < y] [f(x, y) for x in xs if x > 0 for y in ys if y < 10]
The clauses are evaluated left-to-right as nested loops.
- clauses: List[ComprehensionClause]
- property condition: Expression | None
Get first condition (for single-clause compatibility).
- element_expr: Expression
- classmethod from_single(span: SourceSpan, element_expr: Expression, variable: str, iterable: Expression, condition: Expression | None = None) ListComprehension[source]
Create a single-clause comprehension (backward compatibility).
- property iterable: Expression
Get iterable (for single-clause compatibility).
- property variable: str
Get variable name (for single-clause compatibility).
- class yapcad.dsl.ast.ListLiteral(span: SourceSpan, elements: List[Expression])[source]
Bases:
ExpressionA list literal (e.g., [1, 2, 3]).
- elements: List[Expression]
- class yapcad.dsl.ast.Literal(span: SourceSpan, value: int | float | str | bool, literal_type: TokenType)[source]
Bases:
ExpressionA literal value (int, float, string, bool).
- value: int | float | str | bool
- class yapcad.dsl.ast.LiteralPattern(span: SourceSpan, value: Literal)[source]
Bases:
PatternA literal pattern (e.g., ‘match x { case 42: … }’).
- class yapcad.dsl.ast.MatchArm(span: SourceSpan, pattern: Pattern, body: Expression)[source]
Bases:
AstNodeA single arm of a match expression.
- body: Expression
- class yapcad.dsl.ast.MatchExpr(span: SourceSpan, subject: Expression, arms: List[MatchArm])[source]
Bases:
ExpressionA match expression.
- subject: Expression
- class yapcad.dsl.ast.MemberAccess(span: SourceSpan, object: Expression, member: str)[source]
Bases:
ExpressionMember access (e.g., point.x).
- member: str
- object: Expression
- class yapcad.dsl.ast.MethodCall(span: ~yapcad.dsl.tokens.SourceSpan, object: ~yapcad.dsl.ast.Expression, method: str, arguments: ~typing.List[~yapcad.dsl.ast.Expression], named_arguments: dict[str, ~yapcad.dsl.ast.Expression] = <factory>)[source]
Bases:
ExpressionA method call (e.g., curve.at(0.5)).
- arguments: List[Expression]
- method: str
- named_arguments: dict[str, Expression]
- object: Expression
- class yapcad.dsl.ast.Module(span: SourceSpan, name: str | None, uses: List[UseStatement | ExportUseStatement] = <factory>, native_blocks: List[NativeBlock] = <factory>, native_functions: List[NativeFunction] = <factory>, functions: List[FunctionDef] = <factory>, exports: List[ExportStatement] = <factory>)[source]
Bases:
AstNodeA complete DSL module.
- Syntax:
module module_name
use other.module
@native def native_func(…):
…
- def my_function(…):
…
- property commands: List[FunctionDef]
Backward compatibility alias for functions.
- exports: List[ExportStatement]
- functions: List[FunctionDef]
- name: str | None
- native_blocks: List[NativeBlock]
- native_functions: List[NativeFunction]
- uses: List[UseStatement | ExportUseStatement]
- class yapcad.dsl.ast.NativeBlock(span: SourceSpan, code: str, exports: List[NativeFunctionDecl])[source]
Bases:
AstNodeA native Python block with exported function declarations (legacy).
- Syntax:
- native python {
# Python code here
- } exports {
fn func_name(param: type) -> return_type;
}
The Python code is executed to define functions, which are then made available to the DSL with the declared type signatures.
Note: This is the legacy syntax. New code should use @native decorator.
- code: str
- exports: List[NativeFunctionDecl]
- class yapcad.dsl.ast.NativeFunction(span: SourceSpan, name: str, parameters: List[Parameter], return_type: TypeNode, python_code: str)[source]
Bases:
AstNodeA native function (Python code with DSL type signature).
- Syntax:
@native def function_name(param1: type1, param2: type2) -> return_type:
‘’’Python code here’’’ …
The function body contains Python code that is executed directly.
- name: str
- python_code: str
- class yapcad.dsl.ast.NativeFunctionDecl(span: SourceSpan, name: str, parameters: List[Parameter], return_type: TypeNode)[source]
Bases:
AstNodeA function declaration in a native block’s exports section (legacy).
Represents: fn name(param1: type1, param2: type2) -> return_type;
- name: str
- class yapcad.dsl.ast.OptionalType(span: SourceSpan, inner: TypeNode)[source]
Bases:
TypeNodeAn optional type, e.g., ‘point3d?’.
- class yapcad.dsl.ast.Parameter(span: SourceSpan, name: str, type_annotation: TypeNode | None = None, default_value: Expression | None = None, ui_hint: dict | None = None)[source]
Bases:
AstNodeA function parameter.
- default_value: Expression | None = None
- name: str
- ui_hint: dict | None = None
- class yapcad.dsl.ast.PassStatement(span: SourceSpan)[source]
Bases:
StatementA pass statement (placeholder for empty blocks).
- class yapcad.dsl.ast.Pattern(span: SourceSpan)[source]
Bases:
AstNodeBase class for match patterns.
- class yapcad.dsl.ast.PrintVisitor(indent: int = 0)[source]
Bases:
AstVisitorDebug visitor that prints the AST structure.
- class yapcad.dsl.ast.PythonBlock(span: SourceSpan, code: str)[source]
Bases:
StatementAn inline Python block (legacy support).
- code: str
- class yapcad.dsl.ast.PythonExpr(span: SourceSpan, code: str, return_type: TypeNode)[source]
Bases:
ExpressionA python block that returns a value (legacy support).
- code: str
- class yapcad.dsl.ast.RangeExpr(span: SourceSpan, start: Expression, end: Expression, step: Expression | None = None)[source]
Bases:
ExpressionA range expression (e.g., 0..10 or range(10)).
- end: Expression
- start: Expression
- step: Expression | None = None
- yapcad.dsl.ast.RequireStatement
alias of
AssertStatement
- class yapcad.dsl.ast.ReturnStatement(span: SourceSpan, value: Expression | None = None)[source]
Bases:
StatementA return statement.
- value: Expression | None = None
- class yapcad.dsl.ast.SimpleType(span: SourceSpan, name: str)[source]
Bases:
TypeNodeA simple type like ‘int’, ‘float’, ‘solid’, etc.
- name: str
- class yapcad.dsl.ast.Statement(span: SourceSpan)[source]
Bases:
AstNodeBase class for all statements.
- class yapcad.dsl.ast.TypeNode(span: SourceSpan)[source]
Bases:
AstNodeBase class for type annotations.
- class yapcad.dsl.ast.UnaryOp(span: SourceSpan, operator: TokenType, operand: Expression)[source]
Bases:
ExpressionA unary operation (e.g., not x, -n).
- operand: Expression
- class yapcad.dsl.ast.UseStatement(span: SourceSpan, module_path: List[str], alias: str | None = None)[source]
Bases:
AstNodeA use/import statement (e.g., use yapcad.stdlib.transforms).
- Syntax:
use module.path use module.path as alias use module.path.{item1, item2} # (future: selective imports)
- alias: str | None = None
- module_path: List[str]
- class yapcad.dsl.ast.VarDecl(span: SourceSpan, name: str, type_annotation: TypeNode | None, initializer: Expression | None)[source]
Bases:
StatementA variable declaration (Pythonic style, no ‘let’ keyword).
- Syntax options:
x = 42 # Type inferred x: int = 42 # Explicit type x: int # Declaration without initialization (rare)
- initializer: Expression | None
- name: str
- class yapcad.dsl.ast.WhileStatement(span: SourceSpan, condition: Expression, body: Block)[source]
Bases:
StatementA while loop (e.g., while condition:).
- condition: Expression
- class yapcad.dsl.ast.WildcardPattern(span: SourceSpan)[source]
Bases:
PatternThe wildcard pattern ‘_’.
yapcad.dsl.checker module
Type checker for the yapCAD DSL.
Traverses the AST and validates types, collecting diagnostics for type errors, undefined identifiers, and other semantic issues.
- class yapcad.dsl.checker.CheckResult(diagnostics: List[Diagnostic], has_errors: bool, has_warnings: bool, has_python_blocks: bool)[source]
Bases:
objectResult of type checking a module.
- diagnostics: List[Diagnostic]
- has_errors: bool
- has_python_blocks: bool
- has_warnings: bool
- class yapcad.dsl.checker.TypeChecker(max_errors: int = 20)[source]
Bases:
objectType checker for the yapCAD DSL.
Traverses the AST and validates: - Type compatibility in assignments and function calls - Return type matching - Require expression boolean constraint - Emit target type matching command return type - Undefined identifier detection - Python block flagging
- check(module: Module) CheckResult[source]
Type check a complete module.
- yapcad.dsl.checker.check(module: Module, max_errors: int = 20) CheckResult[source]
Convenience function to type check a module.
- Parameters:
module – The parsed module AST
max_errors – Maximum errors before stopping (default 20)
- Returns:
CheckResult with diagnostics
yapcad.dsl.errors module
DSL-specific exceptions and error handling.
Error code ranges (from Phase 3 roadmap): - E0xx: Lexer errors - E1xx: Parser errors - E2xx: Type errors - E3xx: Semantic errors
- class yapcad.dsl.errors.Diagnostic(code: str, message: str, severity: ErrorSeverity, span: SourceSpan, source_line: str | None = None, hints: List[str] = <factory>, related: List[Diagnostic] = <factory>)[source]
Bases:
objectA single diagnostic message (error, warning, etc.).
- code: str
- hints: List[str]
- message: str
- severity: ErrorSeverity
- source_line: str | None = None
- span: SourceSpan
- class yapcad.dsl.errors.DiagnosticCollector(max_errors: int = 20)[source]
Bases:
objectCollects diagnostics during compilation.
- add(diagnostic: Diagnostic) None[source]
Add a diagnostic.
- diagnostics: List[Diagnostic]
- property error_count: int
- property has_errors: bool
- property has_warnings: bool
- property should_stop: bool
Check if we’ve hit the max error limit.
- property warning_count: int
- exception yapcad.dsl.errors.DslError(diagnostic: Diagnostic)[source]
Bases:
ExceptionBase exception for DSL errors.
- class yapcad.dsl.errors.ErrorSeverity(*values)[source]
Bases:
EnumSeverity levels for diagnostics.
- ERROR = 'error'
- HINT = 'hint'
- INFO = 'info'
- WARNING = 'warning'
- exception yapcad.dsl.errors.LexerError(diagnostic: Diagnostic)[source]
Bases:
DslErrorError during lexical analysis (E0xx).
- exception yapcad.dsl.errors.ParserError(diagnostic: Diagnostic)[source]
Bases:
DslErrorError during parsing (E1xx).
- exception yapcad.dsl.errors.SemanticError(diagnostic: Diagnostic)[source]
Bases:
DslErrorError during semantic analysis (E3xx).
- exception yapcad.dsl.errors.TypeError(diagnostic: Diagnostic)[source]
Bases:
DslErrorError during type checking (E2xx).
- yapcad.dsl.errors.error_invalid_binary_literal(text: str, span: SourceSpan, source_line: str = None) LexerError[source]
E008: Invalid binary literal.
- yapcad.dsl.errors.error_invalid_escape_sequence(seq: str, span: SourceSpan, source_line: str = None) LexerError[source]
E005: Invalid escape sequence in string.
- yapcad.dsl.errors.error_invalid_expression(span: SourceSpan, source_line: str = None) ParserError[source]
E103: Invalid expression.
- yapcad.dsl.errors.error_invalid_hex_literal(text: str, span: SourceSpan, source_line: str = None) LexerError[source]
E007: Invalid hexadecimal literal.
- yapcad.dsl.errors.error_invalid_number_literal(text: str, span: SourceSpan, source_line: str = None) LexerError[source]
E006: Invalid number literal.
- yapcad.dsl.errors.error_require_failed(message: str, span: SourceSpan, source_line: str = None) SemanticError[source]
E301: Require constraint failed.
- yapcad.dsl.errors.error_type_mismatch(expected: str, found: str, span: SourceSpan, source_line: str = None) TypeError[source]
E201: Type mismatch.
- yapcad.dsl.errors.error_undefined_identifier(name: str, span: SourceSpan, source_line: str = None) TypeError[source]
E202: Undefined identifier.
- yapcad.dsl.errors.error_unexpected_character(char: str, span: SourceSpan, source_line: str = None) LexerError[source]
E001: Unexpected character.
- yapcad.dsl.errors.error_unexpected_eof(expected: str, span: SourceSpan) ParserError[source]
E102: Unexpected end of file.
- yapcad.dsl.errors.error_unexpected_token(expected: str, found: str, span: SourceSpan, source_line: str = None) ParserError[source]
E101: Unexpected token.
- yapcad.dsl.errors.error_unterminated_comment(span: SourceSpan, source_line: str = None) LexerError[source]
E004: Unterminated multi-line comment.
- yapcad.dsl.errors.error_unterminated_multiline_string(span: SourceSpan, source_line: str = None) LexerError[source]
E003: Unterminated multi-line string.
- yapcad.dsl.errors.error_unterminated_string(span: SourceSpan, source_line: str = None) LexerError[source]
E002: Unterminated string literal.
- yapcad.dsl.errors.warning_python_block(span: SourceSpan, source_line: str = None) Diagnostic[source]
W001: Python block requires manual approval.
yapcad.dsl.introspection module
DSL Introspection API for agentic engineering tools.
This module provides programmatic access to the yapCAD DSL’s type system, built-in functions, and methods. It’s designed to be queried by AI agents and other tools that need to understand the DSL’s capabilities.
- Usage:
- from yapcad.dsl.introspection import (
get_api_reference, get_function_info, get_type_info, list_functions, list_types, describe_function,
)
# Get complete API reference as a dictionary api = get_api_reference()
# Get info about a specific function info = get_function_info(“box”) print(info[“signature”]) # “box(width: float, depth: float, height: float) -> solid”
# List all available functions for name in list_functions():
print(name)
- yapcad.dsl.introspection.describe_function(name: str) str[source]
Get a human-readable description of a function.
- Parameters:
name – The function name
- Returns:
Formatted description string
- yapcad.dsl.introspection.get_api_as_json() str[source]
Get the complete API reference as a JSON string.
Useful for tools that prefer to parse JSON directly.
- yapcad.dsl.introspection.get_api_reference() Dict[str, Any][source]
Get the complete API reference as a dictionary.
Returns a dictionary with: - types: All available types with descriptions - functions: All built-in functions with signatures and descriptions - methods: Type-specific methods organized by receiver type
This is the primary entry point for agentic tools to understand the DSL’s capabilities.
- yapcad.dsl.introspection.get_common_pattern(name: str) str | None[source]
Get a common DSL pattern/example.
- Parameters:
name – Pattern name (e.g., “boolean_subtraction”, “gear_creation”)
- Returns:
DSL code example or None if pattern not found
- yapcad.dsl.introspection.get_function_info(name: str) Dict[str, Any] | None[source]
Get detailed information about a specific function.
- Parameters:
name – The function name
- Returns:
Dictionary with signature, description, example, etc. Returns None if function not found.
- yapcad.dsl.introspection.get_methods_for_type(type_name: str) Dict[str, Dict[str, Any]][source]
Get all methods available on a given type.
- Parameters:
type_name – The type name (e.g., “solid”, “curve”, “region2d”)
- Returns:
Dictionary mapping method names to their signatures
- yapcad.dsl.introspection.get_type_info(name: str) Dict[str, Any] | None[source]
Get information about a type.
- Parameters:
name – The type name
- Returns:
Dictionary with tier, description, constructor info. Returns None if type not found.
- yapcad.dsl.introspection.list_common_patterns() List[str][source]
List all available common pattern names.
yapcad.dsl.lexer module
Lexer for the yapCAD DSL v2 (Pythonic Syntax).
Converts source text into a stream of tokens for the parser. Supports: - Python-style indentation (INDENT/DEDENT tokens) - Significant newlines (NEWLINE tokens) - Implicit line continuation inside brackets - Single-line comments (#) - Multi-line comments (/* */) - String literals with escape sequences - Multi-line strings (triple quotes) - Integer literals (decimal, hex, binary) - Float literals (including scientific notation) - All DSL keywords and operators
- class yapcad.dsl.lexer.Lexer(source: str, filename: str | None = None)[source]
Bases:
objectTokenizer for the yapCAD DSL v2 with Python-style indentation.
This lexer generates INDENT and DEDENT tokens based on changes in leading whitespace, similar to Python’s tokenizer.
- Usage:
lexer = Lexer(source_code) tokens = lexer.tokenize()
- Or for streaming:
lexer = Lexer(source_code) for token in lexer:
process(token)
- property lines: List[str]
Lazy-load line list for error reporting.
- yapcad.dsl.lexer.tokenize(source: str, filename: str | None = None) List[Token][source]
Convenience function to tokenize source code.
- Parameters:
source – The source code to tokenize
filename – Optional filename for error messages
- Returns:
List of tokens
- Raises:
LexerError – If tokenization fails
yapcad.dsl.meta_apply module
Apply @meta decorator hints from the DSL to yapCAD geometry metadata.
This module bridges the gap between the DSL’s @meta(...) command decorator
(which produces a flat meta_hint dict on a FunctionDef node) and the
v1.1 metadata namespace helpers in yapcad.metadata.
Typical usage — called by the DSL evaluator or service layer after a command emits a solid:
from yapcad.dsl.meta_apply import apply_meta_hint
if fn.meta_hint:
apply_meta_hint(solid, fn.meta_hint)
The function is idempotent and additive: calling it multiple times with
the same hints merges cleanly because the underlying namespace helpers use
setdefault / field-level writes, not wholesale replacement.
Namespace routing
Dotted keys in the hint dict are split on the first dot to determine the namespace, then the remainder becomes the field name:
assembly.joint_kind→ assembly namespace, fieldjoint_kindoperation.kind→ operation namespace, fieldkindlayer→ root metadata fieldlayertags→ root metadatatagslist (value appended)
Unknown namespaces or unrecognised field names within a known namespace are stored verbatim in the namespace dict rather than raising an error. This keeps the DSL forward-compatible: a field defined in a future v1.2 spec won’t break existing parsers.
List-of-dict assembly fields
The @meta decorator additionally accepts the four structured assembly
list fields as lists of dict literals. Each entry is forwarded to the
corresponding yapcad.metadata helper, so the same validation (enum
checks, required-key checks, vector length checks) applies whether the
caller writes Python or DSL:
@meta(
assembly.datums=[
{id="neck_face", kind="axis", ring="upper", R_mm=151.9, z_mm=330.0},
{id="bore", kind="axis", ring="upper", R_mm=151.9, z_mm=325.0},
],
assembly.bolt_patterns=[
{id="primary", ring="upper", R_mm=149.4, z_mm=317.3, count=8,
fastener={kind="heatset", size="1/4-20"}},
],
assembly.surfaces=[{id="mate_top", kind="mating", mate_to="nosecone.base_bore"}],
assembly.keepouts=[{id="clearance_zone", kind="volume", reason="approach"}],
)
command FORWARD_BULKHEAD(...) -> solid:
...
Known unsupported field shapes still raise ValueError with the name of
the field so callers can fall back to the Python helpers.
- yapcad.dsl.meta_apply.apply_meta_hint(solid: list, meta_hint: Dict[str, Any]) None[source]
Apply a
FunctionDef.meta_hintdict to a yapCAD solid’s metadata.- Parameters:
solid – A yapCAD solid (list representation from
geom3d).meta_hint – The flat dict produced by one or more
@meta(...)decorators. Keys are plain strings or dotted namespace paths ("assembly.joint_kind","operation.kind","layer", etc.).
- Raises:
TypeError – If
solidis not a solid ormeta_hintis not a dict.ValueError – If a structured list field (bolt_patterns, datums, …) is attempted via the flat interface.
Example:
@meta(assembly.joint_kind="revolute", layer="kinematics") @meta(operation.kind="subtract", operation.feature_kind="pocket") command MAKE_POCKET(depth: float = 10.0) -> solid: ... # After evaluation: apply_meta_hint(result_solid, fn.meta_hint) # → assembly.joint_kind = "revolute" # → operation.kind = "subtract", operation.feature_kind = "pocket" # → root layer = "kinematics"
- yapcad.dsl.meta_apply.apply_meta_hint_to_raw(meta: Dict[str, Any], meta_hint: Dict[str, Any]) None[source]
Apply a
meta_hintdict directly to an already-extracted metadata dict.Convenience variant for callers that have already retrieved the metadata dict (e.g. via
get_solid_metadata) rather than the raw solid.- Parameters:
meta – Metadata dict (mutable, modified in place).
meta_hint – Flat hint dict from
@metadecorators.
yapcad.dsl.packaging module
DSL-to-Package integration.
Provides functions to compile DSL source, execute commands, and package the resulting geometry with full provenance tracking.
- class yapcad.dsl.packaging.PackageResult(*, success: bool, manifest: 'PackageManifest' | None = None, execution_result: ExecutionResult | None = None, error_message: str | None = None)[source]
Bases:
objectResult of DSL-to-package operation.
- yapcad.dsl.packaging.package_from_dsl(source: str, command_name: str, parameters: Dict[str, Any], target_dir: Path | str, *, name: str, version: str, description: str | None = None, author: str | None = None, units: str | None = None, materials: Dict[str, Dict[str, Any]] | None = None, overwrite: bool = False) PackageResult[source]
Compile DSL source, execute a command, and package the result.
This is a high-level function that combines DSL compilation, execution, and packaging into a single workflow. The resulting package includes full provenance metadata linking it to the original DSL source.
- Parameters:
source – DSL source code containing the module and command definitions.
command_name – Name of the command to execute (e.g., “MAKE_GEAR”).
parameters – Dictionary of parameter values for the command.
target_dir – Directory where the package will be created.
name – Name for the package (used in manifest).
version – Version string for the package.
description – Optional description for the package.
author – Optional author name.
units – Unit system (default “mm”).
materials – Optional materials dictionary for the package.
overwrite – If True, overwrite existing package directory.
- Returns:
PackageResult with success status, manifest, and any error info.
Example
>>> source = ''' ... module gear_design; ... ... command MAKE_GEAR(teeth: int, module_mm: float) -> solid { ... let pitch_diameter: float = teeth * module_mm; ... let gear: solid = cylinder(pitch_diameter / 2.0, 10.0); ... emit gear; ... } ... ''' >>> result = package_from_dsl( ... source, ... "MAKE_GEAR", ... {"teeth": 24, "module_mm": 2.0}, ... "output/gear_pkg", ... name="gear_24t", ... version="1.0.0", ... ) >>> if result.success: ... print(f"Package created at {result.manifest.root}")
yapcad.dsl.parser module
Recursive descent parser for the yapCAD DSL v2 (Pythonic Syntax).
Converts a token stream into an Abstract Syntax Tree (AST). Supports Python-style indentation-based blocks.
- class yapcad.dsl.parser.Parser(tokens: List[Token], filename: str | None = None, source: str | None = None)[source]
Bases:
objectRecursive descent parser for the yapCAD DSL v2 with Python-style indentation.
- Usage:
parser = Parser(tokens) module = parser.parse_module()
- The parser implements standard precedence climbing for expressions:
- Lowest: or
and == != < > <= >= + - * / // %
- Highest: ** (power, right-associative)
unary (not -)
- PRECEDENCE = {TokenType.AND: 2, TokenType.DOUBLE_SLASH: 6, TokenType.DOUBLE_STAR: 7, TokenType.EQ: 3, TokenType.GE: 4, TokenType.GT: 4, TokenType.LE: 4, TokenType.LT: 4, TokenType.MINUS: 5, TokenType.NE: 3, TokenType.OR: 1, TokenType.PERCENT: 6, TokenType.PLUS: 5, TokenType.SLASH: 6, TokenType.STAR: 6}
- RIGHT_ASSOCIATIVE = {TokenType.DOUBLE_STAR}
- yapcad.dsl.parser.parse(tokens: List[Token], filename: str | None = None, source: str | None = None) Module[source]
Convenience function to parse tokens into a module.
- Parameters:
tokens – List of tokens from the lexer
filename – Optional filename for error messages
source – Optional original source code for extracting raw text
- Returns:
Parsed Module AST
- Raises:
ParserError – If parsing fails
yapcad.dsl.symbols module
Symbol table management for the yapCAD DSL type checker.
Provides scoped symbol tables for tracking variable definitions, function signatures, and type information during type checking.
- class yapcad.dsl.symbols.FunctionSignature(name: str, params: List[Tuple[str, Type, Any | None]], return_type: Type, is_method: bool = False, is_variadic: bool = False)[source]
Bases:
objectType signature for a function or built-in.
- is_method: bool = False
- is_variadic: bool = False
- name: str
- class yapcad.dsl.symbols.Scope(symbols: Dict[str, ~yapcad.dsl.symbols.Symbol]=<factory>, parent: Scope | None = None, name: str = '')[source]
Bases:
objectA single scope in the scope stack.
- name: str = ''
- class yapcad.dsl.symbols.Symbol(name: str, kind: SymbolKind, type: Type, span: SourceSpan | None = None, is_mutable: bool = False, has_python_block: bool = False)[source]
Bases:
objectA symbol in the symbol table.
- has_python_block: bool = False
- is_mutable: bool = False
- kind: SymbolKind
- name: str
- span: SourceSpan | None = None
- class yapcad.dsl.symbols.SymbolKind(*values)[source]
Bases:
EnumThe kind of symbol being tracked.
- COMMAND = 4
- FUNCTION = 3
- MODULE = 5
- PARAMETER = 2
- VARIABLE = 1
- class yapcad.dsl.symbols.SymbolTable[source]
Bases:
objectManages scopes and symbol definitions for type checking.
Provides: - Nested scope management (push/pop) - Symbol definition and lookup - Built-in function registry
- define(symbol: Symbol) bool[source]
Define a symbol in the current scope.
Returns True if successful, False if already defined in current scope.
- get_all_builtins() Dict[str, FunctionSignature][source]
Get all registered built-in functions.
- lookup_builtin(name: str) FunctionSignature | None[source]
Look up a built-in function signature.
- yapcad.dsl.symbols.get_method_signature(obj_type: Type, method_name: str) FunctionSignature | None[source]
Get the method signature for a type, if it exists.
yapcad.dsl.tokens module
Token types for the yapCAD DSL lexer.
yapCAD DSL v2 - Pythonic Syntax
Token type categories follow error code ranges from the roadmap: - E0xx: Lexer errors - E1xx: Parser errors - E2xx: Type errors - E3xx: Semantic errors
- class yapcad.dsl.tokens.SourceLocation(line: int, column: int, offset: int, filename: str | None = None)[source]
Bases:
objectRepresents a position in source code.
- column: int
- filename: str | None = None
- line: int
- offset: int
- class yapcad.dsl.tokens.SourceSpan(start: SourceLocation, end: SourceLocation)[source]
Bases:
objectRepresents a range in source code.
- end: SourceLocation
- start: SourceLocation
- class yapcad.dsl.tokens.Token(type: TokenType, value: Any, lexeme: str, span: SourceSpan)[source]
Bases:
objectA single token from the lexer.
- lexeme: str
- span: SourceSpan
- value: Any
- class yapcad.dsl.tokens.TokenType(*values)[source]
Bases:
EnumAll token types recognized by the DSL lexer.
- AND = 76
- ARROW = 92
- AS = 19
- ASSERT = 17
- ASSIGN = 79
- AT = 97
- BOOL_LITERAL = 4
- CLOSE = 30
- CLOSE_C0 = 31
- CLOSE_C1 = 32
- COLON = 88
- COMMA = 90
- COMMAND = 23
- DEDENT = 100
- DEF = 8
- DOT = 91
- DOUBLE_ARROW = 93
- DOUBLE_SLASH = 67
- DOUBLE_STAR = 69
- ELIF = 12
- ELSE = 13
- EMIT = 10
- EOF = 102
- EQ = 74
- EXPORT = 21
- EXPORTS = 29
- FLOAT_LITERAL = 2
- FN = 28
- FOR = 14
- GE = 73
- GT = 71
- HASH = 98
- IDENTIFIER = 5
- IF = 11
- IN = 15
- INDENT = 99
- INT_LITERAL = 1
- LBRACE = 82
- LBRACKET = 86
- LE = 72
- LET = 24
- LPAREN = 84
- LT = 70
- MATCH = 20
- MINUS = 64
- MINUS_ASSIGN = 81
- MODULE = 6
- NATIVE = 22
- NATIVE_BLOCK = 103
- NE = 75
- NEWLINE = 101
- NOT = 78
- OR = 77
- PASS = 18
- PERCENT = 68
- PLUS = 63
- PLUS_ASSIGN = 80
- PYTHON = 27
- QUESTION = 95
- RANGE = 94
- RBRACE = 83
- RBRACKET = 87
- REQUIRE = 25
- RETURN = 9
- RPAREN = 85
- SEMICOLON = 89
- SLASH = 66
- STAR = 65
- STRING_LITERAL = 3
- TYPE_ARC = 45
- TYPE_BEZIER = 52
- TYPE_BOOL = 36
- TYPE_CATMULLROM = 50
- TYPE_CIRCLE = 46
- TYPE_DICT = 62
- TYPE_ELLIPSE = 47
- TYPE_FLOAT = 34
- TYPE_HYPERBOLA = 49
- TYPE_INT = 33
- TYPE_LINE_SEGMENT = 44
- TYPE_LIST = 61
- TYPE_LOOP3D = 57
- TYPE_NURBS = 51
- TYPE_PARABOLA = 48
- TYPE_PATH2D = 53
- TYPE_PATH3D = 54
- TYPE_POINT = 37
- TYPE_POINT2D = 38
- TYPE_POINT3D = 39
- TYPE_PROFILE2D = 55
- TYPE_REGION2D = 56
- TYPE_SHELL = 59
- TYPE_SOLID = 60
- TYPE_STRING = 35
- TYPE_SURFACE = 58
- TYPE_TRANSFORM = 43
- TYPE_VECTOR = 40
- TYPE_VECTOR2D = 41
- TYPE_VECTOR3D = 42
- UNDERSCORE = 96
- USE = 7
- WHILE = 16
- WITH = 26
- yapcad.dsl.tokens.get_deprecation_message(keyword: str) str | None[source]
Get the deprecation message for a keyword, if any.
yapcad.dsl.types module
Type system definitions for the yapCAD DSL.
- The type system is organized into five tiers:
Tier 1: Primitives (int, float, bool, string, point, vector, transform) Tier 2: Curve Primitives (line_segment, arc, circle, bezier, nurbs, etc.) Tier 3: Compound Curves (path2d, path3d, profile2d, region2d, loop3d) Tier 4: Surfaces (surface, shell) Tier 5: Solids (solid)
Plus generic types: list<T>, dict
- class yapcad.dsl.types.CompoundCurveType(_name: str)[source]
Bases:
TypeA Tier 3 compound curve type (paths, profiles, regions).
- is_assignable_from(other: Type) bool[source]
Check if this type can accept a value of the other type.
- property name: str
The type name for display/errors.
- class yapcad.dsl.types.CurveType(_name: str)[source]
Bases:
TypeA Tier 2 curve primitive type.
- property name: str
The type name for display/errors.
- class yapcad.dsl.types.DictType[source]
Bases:
TypeA dictionary type (string keys).
- property name: str
The type name for display/errors.
- class yapcad.dsl.types.ErrorType[source]
Bases:
TypeA type representing a type error (prevents cascading errors).
- is_assignable_from(other: Type) bool[source]
Check if this type can accept a value of the other type.
- property name: str
The type name for display/errors.
- class yapcad.dsl.types.FunctionType(param_types: Tuple[Type, ...], return_type: Type)[source]
Bases:
TypeA function type for lambdas and built-in functions.
- property name: str
The type name for display/errors.
- class yapcad.dsl.types.GeometricPrimitiveType(_name: str, dimension: int | None = None)[source]
Bases:
TypeA geometric primitive type (point, vector, transform).
Points and vectors are dimensionally polymorphic - they can be 2D or 3D. point2d/point3d and vector2d/vector3d are specific variants.
- dimension: int | None = None
- is_assignable_from(other: Type) bool[source]
Check if this type can accept a value of the other type.
- property name: str
The type name for display/errors.
- class yapcad.dsl.types.ListType(element_type: Type)[source]
Bases:
TypeA generic list type: list<T>.
- is_assignable_from(other: Type) bool[source]
Check if this type can accept a value of the other type.
- property name: str
The type name for display/errors.
- class yapcad.dsl.types.NoneType[source]
Bases:
TypeThe none/null type (only valid for optional types).
- property name: str
The type name for display/errors.
- class yapcad.dsl.types.OptionalTypeWrapper(inner_type: Type)[source]
Bases:
TypeAn optional type: T?
- is_assignable_from(other: Type) bool[source]
Check if this type can accept a value of the other type.
- property name: str
The type name for display/errors.
- class yapcad.dsl.types.PrimitiveType(_name: str)[source]
Bases:
TypeA primitive type (int, float, bool, string).
- is_assignable_from(other: Type) bool[source]
Check if this type can accept a value of the other type.
- property name: str
The type name for display/errors.
- class yapcad.dsl.types.SolidType(_name: str = 'solid')[source]
Bases:
TypeA Tier 5 solid type.
- property name: str
The type name for display/errors.
- class yapcad.dsl.types.SurfaceType(_name: str)[source]
Bases:
TypeA Tier 4 surface type.
- property name: str
The type name for display/errors.
- class yapcad.dsl.types.Type[source]
Bases:
ABCBase class for all DSL types.
- is_assignable_from(other: Type) bool[source]
Check if this type can accept a value of the other type.
- abstract property name: str
The type name for display/errors.
- class yapcad.dsl.types.TypeTier(*values)[source]
Bases:
EnumTier classification for types in the hierarchy.
- COMPOUND_CURVE = 3
- CURVE = 2
- GENERIC = 0
- PRIMITIVE = 1
- SOLID = 5
- SURFACE = 4
- class yapcad.dsl.types.UnknownType[source]
Bases:
TypeA placeholder for type inference or error recovery.
- is_assignable_from(other: Type) bool[source]
Check if this type can accept a value of the other type.
- property name: str
The type name for display/errors.
- yapcad.dsl.types.common_type(t1: Type, t2: Type) Type | None[source]
Find the common type that both t1 and t2 can be assigned to.
Returns None if no common type exists.
- yapcad.dsl.types.is_compound_curve(t: Type) bool[source]
Check if type is a compound curve (Tier 3).
- yapcad.dsl.types.is_geometric_primitive(t: Type) bool[source]
Check if type is a geometric primitive (point, vector, transform).
- yapcad.dsl.types.is_geometry(t: Type) bool[source]
Check if type is any geometric type (Tier 1 geometric through Tier 5).
- yapcad.dsl.types.make_list_type(element_type: Type) ListType[source]
Create a list type with the given element type.
- yapcad.dsl.types.make_optional_type(inner_type: Type) OptionalTypeWrapper[source]
Create an optional type wrapping the given type.
Module contents
yapCAD Domain-Specific Language (DSL) compiler.
This module provides: - Lexer: Tokenizes DSL source code - Parser: Builds AST from tokens - Type checker: Validates types and constraints - Interpreter: Executes DSL commands to generate geometry - Transforms: AST transformations for optimization
- Usage:
from yapcad.dsl import tokenize, parse, check, Lexer, Parser, TypeChecker
# Simple parsing tokens = tokenize(‘let x: int = 42;’)
# Or parse and type check a complete module source = ‘’’ module my_design;
- command MAKE_BOX(width: float, height: float) -> solid {
let box: solid = box(width, height, 10.0); emit box;
tokens = tokenize(source) module = parse(tokens) result = check(module) if result.has_errors:
- for diag in result.diagnostics:
print(diag)