FCS Language Basics

Migration / Verification Status: Foundational reference for expressions, variables, control flow, math, strings, arrays/higher-order functions, units, lambdas, and related constructs. Content reviewed against the corresponding pages in the HiStructOrg femcad-doc wiki (especially the detailed Array-functions catalog). All major areas are backed by tested gists and early Golem test cases. See project/migration/full-wiki-to-dzone-mapping.md for full traceability to the live wiki pages.


Wiki Sources for Language Fundamentals (from live crawl of https://github.com/HiStructOrg/femcad-doc/wiki)

The following wiki pages were the primary sources for the depth in this document (and the low-numbered gists). They have been cross-checked, with their richer examples and edge cases folded into the tested D-Zone version where they added value beyond the existing gists.

Wiki Page (live) Lines Key Topics Covered Primary D-Zone Home Related Verified Gists Verification Notes
Array-functions.md 620 Select, SelectIterate, SelectMany, Where, Find, Take/Skip, Aggregate, OrderBy (multi-column), Zip, ColectBy (group), Sum/CumulativeSums, All/Any, Spacings, array ops/merging This page + gist-006 gist-006-lists-linq, gist-009 Rich catalog; core methods already exercised in Golem tests 004 (array sum)
Math-operations.md 164 Arithmetic, functions, operators, Math namespace This page gist-001-arithmetic, gist-007-math Strong coverage
Strings.md 165 String ops, formatting, interpolation This page gist-003-strings Good
Units.md 85 Unit constants, conversion, Unit. namespace This page + 08 gist-008-units Core
Intervals.md 61 Range, interval syntax and ops This page gist-009 (parametric) -
Ternary-operator.md 59 cond ? a : b and variants This page gist-004-conditionals -
Lambda-function.md 23 x => expr, higher-order usage This page gist-005-lambdas -
Enumerable-range.md 22 Range generation This page gist-009 -
Map-(-[key,-value]-).md 48 Dictionary / map type This page - Needs dedicated gist?
IndexPath.md 29 Path indexing into nested structures This page + 19/27 - -
Native-Entities.md 153 Built-in geometry primitives (moved to 02) 02-GEOMETRY-PRIMITIVES gist-100-vertex and friends Geometry foundation
gblock-distribution.md 69 GBlock + distribution basics 04-CLASSES-DISTRIBUTIONS gist-300+, gist-010 See 04

Note on Array-functions.md: This 620-line wiki page is the most detailed single source for FCS array power. The current "Lists (arrays)" section in this document covers the most common methods. Advanced methods (SelectMany, multi-column OrderBy, ColectBy, CumulativeSums, Spacings, etc.) are referenced via the gists and will receive expanded dedicated examples in future passes of this wave.


1. File Structure

FCS scripts are plain text files with .fcs extension. A script consists of:

# This is a comment
## Multi-line comments use multiple #

# Variable definitions
height := 10.5
width := 20

# Computed values
area := height * width

# Data items (geometry, mesh, analysis)
vertex {v1} xyz 0 0 0

2. Comments

# Single line comment
## Another comment style

# Comments can appear at end of line
x := 10  # inline comment

3. Variable Assignment

FCS has two binding operators, := and =. Both are legal at the top level and inside updaters (Class{ ... }, parameters { ... }). FCS is pure and lazy (see How FCS Evaluates): nothing runs top to bottom, and a definition is evaluated only when something asks for it. Neither operator means "assign now, mutate later". There is no mutable state.

What the operators decide is whether a field is an input that callers may override, and when an updater entry is evaluated.

Top-level fields: := is an input, = is internal

a := 1        # input: lazy, cached per instance, overridable
b = 2         # internal: may be inlined/optimised by the engine
s = a + b
Engine (.fcsconfig.json) Class{a = 10}.s Class{b = 20}.s
e3.emulation (no config file) 12 21
e4.trans 12 21
e4.pure 12 error: Unable to update readonly field 'b' ... define it with ':='

Practical rule: declare every value that a caller, a parent gblock or user input (PVC / configurator) may change with :=. Use = for derived or internal values. Code written this way behaves the same under every engine.

Inside updaters: = passes a value, := passes a lazy expression

gclass {gc} filename "child.fcs"
x = gc{ a = someValue }.t
y = gc{ a := someValue }.t

For constants and pass-through values (parameters {w = w}) both forms give the same result.

All tables in this section were verified with fli.exe on 2026-10-12.

4. Data Types

Primitives

Type Examples Description
Integer 10, -5, 0 Whole numbers
Double 3.14, -0.5, 1e6 Floating point
Boolean True, False Logical values
String "hello", 'world' Text

Compound Types

# Lists (arrays)
numbers := [1, 2, 3, 4, 5]
mixed := [1, "two", 3.0]
empty := []

# Tuples
point := (1.0, 2.0, 3.0)

# Dynamic objects (anonymous)
config := { width := 10, height := 20, name := "box" }

Accessing Properties

# Object property access
obj := { x := 1, y := 2 }
xVal := obj.x          # dot notation

# List indexing (0-based)
arr := [10, 20, 30]
first := arr[0]        # 10
last := arr[-1]        # 30 (negative = from end)

# Slicing
subset := arr[1:3]     # [20, 30]

5. Operators

Arithmetic

a := 10 + 3     # Addition: 13
b := 10 - 3     # Subtraction: 7
c := 10 * 3     # Multiplication: 30
d := 10 / 3     # Division: 3.333...
e := 10 % 3     # Modulo: 1
f := 2 ** 3     # Power: 8 (or use Pow(2,3))

Comparison

a := 5 == 5     # Equal: True
b := 5 != 3     # Not equal: True
c := 5 > 3      # Greater: True
d := 5 < 3      # Less: False
e := 5 >= 5     # Greater or equal: True
f := 5 <= 3     # Less or equal: False

Logical

a := True and False   # False
b := True or False    # True
c := not True         # False

String Concatenation

greeting := "Hello" + " " + "World"  # "Hello World"

6. Control Flow

Ternary Expression

# condition ? if_true : if_false
max := a > b ? a : b
status := count > 0 ? "has items" : "empty"

FCS has no if statement or if ... then ... else expression. Writing one is a syntax error that stops the whole file from parsing (verified with fli.exe, all engines). Use the ternary operator above.

7. Functions (Lambdas)

Single-argument Lambda

square := x => x * x
result := square(5)  # 25

Multi-argument Lambda

add := (a, b) => a + b
multiply := a, b => a * b

sum := add(3, 4)      # 7
prod := multiply(3, 4) # 12

Lambda with Body

# For complex functions, use block syntax
compute := (x, y) => {
    temp := x * 2
    result := temp + y
    result  # last expression is return value
}

8. Class Instantiation

Classes (defined elsewhere) are instantiated with curly braces:

# Basic instantiation
myBeam := BeamClass{}

# With property overrides
myBeam := BeamClass{ length = 10, width = 0.5 }

# Nested
config := OuterClass{
    inner = InnerClass{ value = 100 }
}

Property Override (Updater Syntax)

# Clone with modified properties
original := MyClass{ a = 1, b = 2 }
modified := original{ a = 10 }  # b remains 2

9. Built-in Functions

Math Functions

# Trigonometry (angles in radians)
s := Sin(0.5)
c := Cos(0.5)
t := Tan(0.5)
a := Asin(0.5)
a := Acos(0.5)
a := Atan(0.5)
a := Atan2(y, x)

# Other math
sq := Sqrt(16)       # 4
pw := Pow(2, 3)      # 8
ab := Abs(-5)        # 5
mn := Min(3, 7)      # 3
mx := Max(3, 7)      # 7
rd := Round(3.7)     # 4
fl := Floor(3.7)     # 3
cl := Ceil(3.2)      # 4

# Constants
pi := PI             # 3.14159...
e := E               # 2.71828...

Unit Conversions

# Common unit conversions
angle_rad := 45 * Unit.deg    # degrees to radians
angle_deg := 0.785 / Unit.deg # radians to degrees

Type Conversions

intVal := Math.ToInteger(3.7)    # 3
dblVal := Math.ToDouble(5)       # 5.0
strVal := x.ToString()           # "..."

List Operations

arr := [1, 2, 3, 4, 5]

count := arr.Count              # 5
first := arr.First()            # 1
last := arr.Last()              # 5
sum := arr.Sum()                # 15
avg := arr.Average()            # 3.0
min := arr.Min()                # 1
max := arr.Max()                # 5

# Functional operations
doubled := arr.Select(x => x * 2)           # [2, 4, 6, 8, 10]
filtered := arr.Where(x => x > 2)           # [3, 4, 5]
any := arr.Any(x => x > 4)                  # True
all := arr.All(x => x > 0)                  # True

10. Import Statements

# Import another FCS file
import "path/to/file.fcs"

# All definitions from imported file become available

11. String Formatting

name := "beam"
length := 10.5

# String concatenation
msg := "The " + name + " is " + length.ToString() + " meters"

# Formatted strings (if supported)
formatted := $"Length: {length:F2} m"

12. Special Identifiers

Identifier Description
this Reference to current class instance
GCS Global Coordinate System
Unit Unit conversion namespace
Fcs FCS namespace for built-in types

13. Syntax Rules Summary

  1. Case Sensitive: myVar ≠ MyVar
  2. Whitespace: Significant for line breaks, not indentation
  3. Semicolons: Not required (line breaks separate statements)
  4. Identifiers: Start with letter/underscore, contain letters/digits/underscores
  5. Keywords: Cannot be used as identifiers

14. Common Patterns

Parametric Design

# Parameters
L := 10          # Length
W := L / 2       # Width depends on L
H := 3           # Height

# Geometry uses parameters
vertex {v1} xyz 0 0 0
vertex {v2} xyz L 0 0
vertex {v3} xyz L W 0
vertex {v4} xyz 0 W 0

Conditional Geometry

includeSupport := True
supportHeight := includeSupport ? 1.0 : 0.0

Iteration via Select

# Create list of points
points := Fcs.Converters.EnumerableRange(10).Select(i => {
    x := i * 0.1
    y := Sin(x)
    result := { X := x, Y := y }
})