Está en la página 1de 44

Machine Translated by Google

Especificación del lenguaje DesignScript 2.1


1. Introducción
2. Elementos léxicos
2.1 Comentarios
2.2 punto y coma
2.3 Identificadores

2.4 Palabras clave


2.5 Booleano literal

2.6 literal entero


2.7 Literal de punto flotante
2.8 Literal de cadena

3. Tipos
3.1 tipos primitivos
3.2 Tipos definidos por el usuario

3.3 Colecciones
3.3.1 Lista
3.3.1.1 Rango

3.3.1.2 Indexación
3.3.1.3 lista dinámica
3.3.1.4 Lista de inmutabilidad
3.3.2 Reglas de
3.4 conversión de tipo de
diccionario 3.4.1 Caso sin
matriz 3.4.2 Promoción de rango
4. Variables
4.1 Alcance
4.2 dinámico
4.2.1 Resolución de alcance
5. Funciones
5.1 Declaración de función
5.2 Argumentos predeterminados

5.3 sobrecargas de funciones

5.4 Resolución de funciones

6. Expresiones
6.1 Expresión de creación de listas
6.2 Expresión de rango Expresión
6.3 condicional en línea 6.4 Expresión
de acceso a miembros Expresión de acceso a
6.5 listas Operadores 6.6.1 Operadores
6.6 aritméticos 6.6.2 Operadores de
comparación
Machine Translated by Google

6.6.3 Operadores lógicos


7. Declaraciones
7.1 Declaraciones vacías
7.2 Importar extractos
7.3 Declaraciones de expresión
7.4 asignaciones
7.5 Declaraciones de flujo

7.5.1 Declaraciones de devolución


7.5.2 Instrucciones de ruptura
7.5.3 Instrucción de continuación
7.6 Si declaraciones
7.7 Bucles
7.7.1 Sentencias while
7.7.2 Para sentencias

8. Bloques de idioma
8.1 Bloque de idioma asociativo por defecto
8.2 Bloque de idioma asociativo anidado Bloque
8.3 de idioma imperativo 9. Replicación y guía
de replicación Guía de replicación y replicación Regla de
9.1 despacho de funciones para replicación y
9.2 guía de replicación
10. List@Level 11.
Funciones integradas
12. Internos

12.1 Actualización asociativa


12.1.1 Establecimiento de asociatividad
12.1.2 Actualización por reejecución 12.1.3
Dependientes 12.1.4 Entidades de las que
se podría depender
12.1.4.1 Variables
12.1.4.2 Función
12.1.4.3 Propiedades
12.1.5 Ámbito de asociatividad 12.2 Clases

12.2.1 Declaración de clase


12.2.2 Herencia
12.2.3 Constructores

12.2.4 Propiedades
12.2.5 Funciones miembro
12.2.6 Modificadores de acceso
12.2.7 Miembros estáticos

12.2.8 Método _Dispose()


Machine Translated by Google

1. Introducción
Esta es la documentación para el lenguaje de programación DesignScript. DesignScript es un lenguaje dinámico, de
recolección de elementos no utilizados y asociativo, y proporciona un sólido soporte para una programación basada en flujos.
ambiente.

1
La gramática en esta especificación está en forma extendida de Backus-Naur (EBNF).

Este documento no contiene información sobre las API y la interfaz de funciones externas (métodos Zero Touch). Este último
depende de la implementación.

2. Elementos léxicos

2.1. Comentarios
DesignScript admite dos tipos de comentarios.

• El comentario de una sola línea comienza con // y se detiene al final de la línea. •


Bloquear comentarios comienza con /* y termina con */.

Ejemplo:

x = 1; // comentario de una sola línea

/*
Bloquear comentarios
*/
y = 2;

2.2. punto y coma


Punto y coma “;” se utiliza como un terminador de una declaración.

2.3. Identificadores
Los identificadores en DesignScript nombran variables, tipos, funciones y espacios de nombres.

Identificador =
identificador_inicial_letra {identificador_parte_letra}

“identifier_start_letter” es el carácter Unicode en las siguientes categorías:


• Letra mayúscula (Lu) • Letra
minúscula (Ll)

1
https://en.wikipedia.org/wiki/Extended_Backus-Naur_Form
Machine Translated by Google

• Letra mayúscula del título


(Lt) • Letra modificadora (Lm)
• Otra letra (Lo) • Número de
letra (Nl)

“identifier_part_letter” es el carácter Unicode en las categorías de “identifier_start_letter” que incluye las siguientes categorías: •
Letra combinada (Mn, Mc) • Letra digital decimal (Nd) • Letra de conexión (Nc) • No ensamblador de ancho cero

• Carpintería de ancho cero

2.4. Palabras clave


Las siguientes palabras están reservadas como palabras clave y no se pueden usar como variables definidas por el usuario.

romper, clase, constructor, continuar, def, más, más si, extiende, para, desde, si, importar, en,
devolver, estático, mientras,

2.5. Booleano literal


El literal booleano solo puede ser cualquiera de los siguientes valores fijos:

verdadero Falso

2.6. Literal entero El


literal entero representa una constante entera. Está en base decimal.

dígito = '0'..'9'

dígito_hexadecimal = '0'..'9' + 'a'..'f' + 'A'..'F'

número_decimal = dígito { dígito }

Ejemplo:

123;

2.7. Literal de punto flotante


Los literales de punto flotante representan una constante de punto flotante en base decimal.

punto_flotante =
dígito { dígito } '.' [dígito { dígito }] [exponente]
Machine Translated by Google

| dígito { dígito } exponente | '.'


dígito { dígito } [ exponente ]

exponente = ('E' | 'e') ['+' | '-'] dígito { dígito }

Ejemplo:

1.2e3; // 1200.0;
1.234;
0,123;

2.8. Literal de cadena El literal de

cadena representa una constante de cadena. Se obtiene poniendo una secuencia de caracteres entre comillas dobles (“).

Cualquier carácter puede estar en la secuencia excepto la nueva línea y las comillas dobles ("). El carácter de barra invertida en la secuencia podría
2
combinarse con el siguiente carácter para convertirse en un carácter de escape:

• \a •
\b • \f
• \n •
\t • \v
• \r

Ejemplo:

// "Hola Guión de diseño


// Idioma"
“\”Hola\tDesignScript\nIdioma\””;

3. Tipos

3.1. tipos primitivos


Los tipos primitivos se refieren a los tipos de datos más básicos que están disponibles en el lenguaje. El sistema de tipos en DesignScript es dinámico y está

orientado a objetos, lo que significa que la verificación de tipos de un programa se realiza en tiempo de ejecución en función de los datos devueltos.

DesignScript admite los siguientes tipos primitivos:

Escribe Rango de valores * Valor por defecto

“”
cadena n/A

2
https://en.wikipedia.org/wiki/Escape_character Estos
*
son detalles de implementación y no son específicos de la especificación del idioma.
Machine Translated by Google

entero 63 -2 63 - 2 - 1 0

punto flotante IEEE 754 de doble precisión 3 0

bool verdadero Falso falso

nulo nulo nulo

variable n/A nulo

Si la implementación del idioma es compatible con FFI (funciones externas), el valor predeterminado de todos los demás tipos de FFI
importados es 'nulo'.

3.2. Tipos definidos por el usuario


Los tipos definidos por el usuario se admiten a través del mecanismo de clase . Estos tipos, también denominados clases, pueden
contener
• Propiedades •
Métodos de instancia
• Miembros estáticos
• Constructores

Solo se permite la herencia simple en DesignScript.

3.3. Colecciones

3.3.1. Lista

Lista = “[” exprLista? “]”

exprList = Expresión (“,” Expresión)*

Una lista es un tipo de variable que contiene uno o más valores de un tipo dado o una variedad de tipos. También puede contener
valores que son Listas por sí mismos o Diccionarios. Puede considerarse como una matriz dinámica cuyo tamaño no es fijo y se asigna
en tiempo de ejecución. Las listas se crean con el operador de corchetes ([ ]) alrededor de un conjunto de valores separados por comas,
o se dejan vacías para crear una colección vacía:

un = []; // lista vacía


a = [1, 2, 3]; // crea una lista con valores explícitos

Las listas también se pueden crear usando expresiones de rango.

3
https://en.wikipedia.org/wiki/Double-precision_floating-point_format
Machine Translated by Google

3.3.1.1. Rango

Si un tipo tiene corchetes, "[ ]", como sufijo después, declara una lista. El número de “[]” especifica el rango o la
dimensión de la lista. Un “[]..[]” especifica un rango arbitrario, lo que significa que la lista puede tener cualquier rango,
incluido un valor único o el rango 0. Por ejemplo:

int[] // una lista de enteros cuyo rango es 1 int[][] // una


lista de enteros cuyo rango es 2 int[]..[] // una lista de
enteros con rango arbitrario

Una lista es un tipo único en DesignScript, ya que es el único tipo que admite la replicación. Las funciones pueden
replicarse sobre argumentos de lista. El rango de un tipo de argumento decide cómo funcionan la replicación y las
guías de replicación en el argumento durante el envío de la función.

3.3.1.2. Indexación Es
posible indexar en cualquier ubicación de la lista usando el operador de corchetes ([ ]) después del nombre de la
variable. La indexación comienza en 0, lo que significa que se accede al primer elemento de una lista 'a' con: 'a[0]'.
Las listas también se pueden usar como índices para generar nuevas sublistas a partir de una lista. Por ejemplo, una
lista que contiene los números [1, 3, 5, 7], cuando se usa como índice de una lista, extrae los elementos 2, 4, 6 y 8 de
una lista:

// Crea una nueva lista c, a partir de una colección de índices a =


1..10; b = [1, 3, 5, 7]; c = a[b]; // c = [2, 4, 6, 8]

3.3.1.3. Lista dinámica Una


lista en DesignScript es dinámica. Los miembros individuales de una lista se pueden modificar utilizando el mismo
operador de índice después de que se haya creado la lista. Si establece un valor para un índice que está más allá de
la longitud de la lista, se expandirá automáticamente y los índices intermedios se rellenarán con valores "nulos". Esto
también se llama "relleno nulo". Por ejemplo:

x = [1, 2, 3]; x[5]


= 4; // x = [1, 2, 3, nulo, nulo, 4];

También es posible cambiar dinámicamente el rango de una lista. En el siguiente ejemplo, 'x' es originalmente una lista
de rango 1. Cuando se establece en un valor en un índice para una dimensión que excede el límite/rango de la lista, los
índices intermedios se establecen en valores 'nulos' debido al relleno nulo:
Machine Translated by Google

x = [1, 2, 3]; x[1]


[2] = 99; // x = [1, [2, nulo, 99], 3]

Nota: La naturaleza dinámica de una lista no debe confundirse con la inmutabilidad de la lista que se trata en el siguiente
sección.

3.3.1.4. Lista de inmutabilidad

Las listas en DesignScript son inmutables. Cuando se copia una lista de una variable a otra variable, se trata de una operación de
copia profunda, es decir, se copian también todos los elementos de la lista. Lo mismo ocurre cuando las listas de DesignScript
interactúan con las listas de C#. La lista original permanece inmutable y cualquier operación en ella crea una nueva Lista. Ejemplo:

a = 1..5; b
= un; b[7]
= 99; // b = [1, 2, 3, 4, 5, nulo, nulo, 99], a = [1, 2, 3, 4, 5]

3.3.2. Diccionario

Diccionario =
"{" valores clave? “}”

valoresclave
= valorclave (“,” valorclave)*

keyValue =
cadena “:” Expresión

Un diccionario DesignScript es un mapa desordenado de pares clave-valor, donde las claves son únicas en el diccionario y solo pueden
ser del tipo 'cadena'. Los valores en el Diccionario pueden ser de cualquier tipo, incluidas listas y diccionarios en sí mismos. Los
diccionarios se inicializan usando llaves, '{ }'. Las llaves vacías crean un diccionario vacío. Los diccionarios se pueden inicializar y
consultar utilizando la siguiente sintaxis:

x = {“foo”: 1, “bar”: 2, “baz”: 3}; a = x[“foo”]; // a =


1 b = x[“baz”]; // segundo = 3

A diferencia de las listas, los diccionarios no se pueden modificar dinámicamente una vez inicializados. Son estrictamente inmutables.
La replicación no es compatible con los diccionarios.
Machine Translated by Google

3.4. Reglas de conversión de tipos


DesignScript tiene ciertas reglas de conversión de tipos integradas. La conversión de tipo (también llamada
coerción de tipo) puede ser explícita o implícita. DesignScript no admite la conversión de tipo explícita.

Dado que DesignScript es un lenguaje de tipo dinámico, los valores se pueden convertir entre diferentes tipos
automáticamente en tiempo de ejecución, lo que se conoce como coerción de tipo implícita. La conversión de
tipo implícita puede ocurrir con los valores cuando interactúan entre sí a través de operadores como '==' o
desencadenados por el contexto circundante, como con 'if (valor) {...}', donde 'valor' se convierte en booleano. La
conversión de tipo también ocurre con los argumentos de función cuando se pasan a posiciones de parámetro
con tipo en la función y se les obliga a asumir el tipo del parámetro. Ejemplos:

// Un valor doble distinto de cero se convierte en un valor verdadero cuando se fuerza a un 'bool'
escriba a = 3.0 == verdadero; // un = verdadero
// Una cadena se puede convertir a un valor verdadero cuando se fuerza a un tipo 'bool'. Vea la
siguiente declaración condicional en línea como ejemplo: i = “hola”? “no vacío” : “vacío”; // i = "no vacío"
i=
“”
? “no vacío” : “vacío”; // i = "vacío"

Las siguientes reglas implícitas de conversión de tipos especifican el resultado de convertir un objeto de un
tipo a otro con contenido similar:

3.4.1. Caso no incluido en la lista

“sí” significa convertible, “no” significa no convertible.

A variable En t doble bool cadena usuario definido


Desde

variable
si si, si Sí, si Sí, si el tipo si, si Sí, si el tipo
es real el tipo real real puede es real real puede
el tipo puede puede ser ser obligado a el tipo puede ser obligado a
ser coaccionado a bool ser usuario definido
coaccionado doble coaccionado escribe
a int a la cadena

En t si si si x != 0 no no

doble si advertencia si x != 0 && x ! no no


= NaN

bool si no no si no no

x!= “”
cadena si no no si no

usuario definido si no no x != nulo no covariante


Machine Translated by Google

3.4.2. Promoción de rango


Los argumentos de valor único cuando se pasan a posiciones de parámetros de función con tipos de lista (matriz) se
promocionan a listas. De manera similar, los argumentos de lista de menor rango se promocionan a listas de mayor rango
cuando se pasan a parámetros de función con mayor rango. Las reglas de promoción de matrices y coerción de tipos también
se aplican cuando a los identificadores escritos (variables) con tipos clasificados más altos se les asignan valores clasificados
más bajos. La siguiente tabla muestra todas las reglas de conversión de tipo y promoción de matriz en DesignScript:

a: int[] = 123; // a = [123] ya que el valor asignado a 'a' se promociona a una lista

A var[] En t[] doble[] bool[] cadena[] usuario

Desde definido[]

variable
si Sí, si Sí, si Sí, si el tipo Sí, si Sí, si el tipo real
el tipo el tipo real real se el tipo coincide con el
real se se puede puede real se definido por el usuario
puede obligar a obligar a bool puede escribe
obligar duplicar forzar a
a int una cadena

En t si si si x != 0 no no

doble si advertencia si x != 0 && x ! no no


= NaN

bool si no no si no no

x!= “”
cadena si no no si no

usuario definido si no no x != nulo no covariante

4. Variables

4.1. Dinámica
Las variables en DesignScript son dinámicas. Si una variable no se declara con un tipo, se le puede asignar
cualquier tipo y el tipo depende totalmente del tiempo de ejecución. Ejemplo:

123; a = “hola”; ////aaahora


es unes
'int'una
a=
'cadena'

En el siguiente ejemplo, dado que 'a' se declara como 'int' y no hay conversión de 'cadena' a 'int', 'a' es
'nulo' en este caso:
Machine Translated by Google

a : int = “cadena”; // a es 'nulo'

4.2. Alcance
4
DesignScript utiliza alcance de bloque. El alcance de una variable definida en DesignScript se limita a un bloque (como un bloque de
idioma) o una función donde se define. Una variable se puede usar antes de que se defina debido a la asociatividad y la máquina
virtual DesignScript se asegurará de propagar la actualización del valor a todas sus referencias.

x = y; // x = 2, esta declaración se ejecutará después de 'y' debido a la asociatividad


y = 2;
z = x + y; // z = 4, ya que se ejecutará después de 'x'

En el caso del alcance imperativo, las declaraciones se ejecutan en secuencia a diferencia del código asociativo. Todas las
variables globales (definidas en el ámbito externo) que se utilizan en el bloque imperativo se copian localmente y cualquier cambio
en ellas dentro del bloque imperativo no afecta sus valores en el bloque externo. En otras palabras, estas variables globales son de
solo lectura (inmutables) dentro del bloque imperativo:

x = 1;
y = 2;
def foo(x) { z =
3; // “z” es una variable local
devuelve x + y; // "x" es el parámetro
// "y" está en el ámbito externo y no está definido dentro de la función
}
[Imperativo] { x =
3; m = norte; // Se hace una copia local de “x” y la “x” global no cambia // “m”, “n” son variables
n = 4; locales. // el orden de las declaraciones es importante en el código imperativo //
dado que 'm' se asigna antes que 'n', su valor sigue siendo 'nulo'

si es verdad) {
y = x + 100; // OK, "x" es visible aquí
}

devuelve x + y + m; // se hace una copia local de 'y' dentro del bloque imperativo

4.2.1. Resolución de alcance


El orden de búsqueda de un identificador es

• Alcance más interno. •


Cada ámbito externo progresivo, incluido el ámbito de clase.

4
https://en.wikipedia.org/wiki/Scope_(informática_ciencia)#Block_scope
Machine Translated by Google

• Clases que amplía la clase actual.

• El alcance global.

5. Funciones
5.1. Declaración de función

FunctionDeclaration =
identificador “def” [“:” TypeSpecification] ParameterList StatementBlock.

Lista de parámetros =
“(“ [Parámetro {“,” Parámetro}] “)”

Parámetro =
identificador [“:” TypeSpecification] [DefaultArgument]

BloqueDeDeclaraciones =
"{" { Declaración } "}"

El tipo de retorno de una función es opcional. De forma predeterminada, el tipo de retorno es una lista clasificada
arbitraria, "var[]..[]". Si se especifica el tipo de devolución, puede ocurrir una conversión de tipo. No se recomienda especificar el tipo
de retorno a menos que sea necesario.

Una función siempre debe definirse en el bloque de lenguaje asociativo global o en el bloque de nivel superior.

Para los parámetros, si no se especifican sus tipos, por defecto son del tipo 'var'. El tipo de parámetros debe
especificarse cuidadosamente para que la replicación y la guía de replicación funcionen como se desea.
Por ejemplo, si el tipo de un parámetro es var[]..[] (rango arbitrario), significa que no hay replicación en este parámetro.

Ejemplo:

def foo : var(x : int[]..[], y : int = 3) {

devuelve x + y;
}

5.2. Argumentos predeterminados


La declaración de función permite argumentos predeterminados para sus parámetros, pero con una restricción: todos los
argumentos predeterminados deben aplicarse a los parámetros más a la derecha.

Ejemplo:
Machine Translated by Google

// es válido porque "y" y "z" son los parámetros predeterminados más a la derecha def foo(x, y =
1, z = 2) {

devuelve x + y + z;
}

// no es válido porque "x" no es el parámetro predeterminado más a la derecha def bar(x =


1, y, z = 2) {

devuelve x + y + z;
}

5.3. sobrecargas de funciones


DesignScript admite la sobrecarga de funciones, es decir, funciones con el mismo nombre pero con diferentes
tipos/cantidad de parámetros. La función que se llamará finalmente depende totalmente del tiempo de ejecución,
especialmente si ocurre la replicación . La máquina virtual DesignScript intentará encontrar la mejor coincidencia
según el tipo de argumentos y el tipo de todos los parámetros de todas las funciones candidatas.

Ejemplo:

def foo(x:int, y:int) {

devuelve x + y;
}

def foo(x: doble, y: doble) {

volver x *
y;
}

// llamará a foo(x:int, y:int) r1 = foo(2, 3);

// llamará a foo(x:doble, y:doble) r2 = foo(2.1,


3.2);

Las sobrecargas de funciones, con la excepción de aquellas con parámetros que solo difieren por rango, son ilegales.
Esto significa que para las funciones sobrecargadas que tienen el mismo número y tipos de parámetros pero tienen uno
o más parámetros que difieren solo en el rango, la sobrecarga que se define primero siempre gana mientras que el
compilador descarta el resto. Por ejemplo,
Machine Translated by Google

def foo(x: número, y: booleano)


{
...
}

// sobrecarga no válida, ya que solo los rangos de los parámetros son


diferentes def foo(x: número[], y: bool[])
{
...
}

// sobrecarga válida

def foo(x: booleano, y: número)


{
...
}

El nodo de mayor rango se puede utilizar tanto en una llamada replicada como en una no replicada y, por lo tanto, siempre se
prefiere a una sobrecarga de menor rango. Por lo tanto, como regla general, siempre se aconseja a los usuarios que eliminen las
sobrecargas de menor rango en favor de métodos de mayor rango para que el compilador de DesignScript siempre llame al método
de mayor rango como el primero y único que encuentre.

5.4. Resolución de funciones


El orden de resolución de una función es: •
Ámbito más interno • Cada ámbito
externo progresivo • Ámbito de instancia
de clase
• Clase que la clase extiende

• El alcance mundial

Como las funciones se pueden sobrecargar, el resultado de la resolución de funciones devolverá una lista de funciones candidatas.
La máquina virtual encontrará la mejor coincidencia según el tipo de argumentos, los tipos de parámetros y la guía de
replicación.
Machine Translated by Google

6. Expresiones

6.1. Expresión de creación de lista

ListCreationExpression = “[” [Expresión { “,” Expresión } ] “]”

La expresión de creación de listas es crear una lista. Ejemplo:

x = [[1, 2, 3], nulo, [verdadero, falso], “DesignScript”];

6.2. Expresión de rango

La expresión de rango es una forma conveniente de generar una lista.

RangeExpression =
Expresión [“..” [“#”] Expresión [“..” [“#”] Expresión]

Hay tres formas de expresiones de rango:


• valor_inicial..valor_final • Si
valor_inicial < valor_final, genera una lista en orden ascendente que comienza en valor_inicial y termina en
un valor <= valor_final con un incremento de 1. • Si valor_inicial > valor_final, genera una lista en orden
descendente que comienza en start_value y termina en un valor >= end_value con un incremento de -1.

• valor_inicial..valor_final..incremento
• Si start_value < end_value, entonces el incremento debe ser un valor positivo. Va a
generar una lista que comience en valor_inicial y último valor <= valor_final, aumentando según el valor de
incremento especificado en la expresión de rango.
• Si valor_inicial > valor_final, el incremento debe ser un valor negativo. Va a
generar una lista que comienza en start_value last value >= end_value, disminuyendo por el valor de
incremento especificado en la expresión de rango. • start_value..#number_of_elements..increment: genera
una lista que contiene
número_de_elementos elementos. El elemento comienza en start_value y el incremento es incremento. El
valor de número_de_elementos siempre se redondea al entero más próximo.
• valor_inicial..valor_final..#número_de_elementos: genera una lista que contiene
number_of_elements elementos igualmente espaciados entre start_value y end_value,
incluidos start_value y end_value. Dependiendo de si start_value <= end_value, la lista
generada estará en orden ascendente o descendente. El valor de número_de_elementos siempre
se redondea al entero más próximo.
Machine Translated by Google

Ejemplo:

1..5; // [1, 2, 3, 4, 5]

5..1; // [5, 4, 3, 2, 1]

1.2 .. 5.1; // [1.2, 2.2, 3.2, 4.2]

5.1 .. 1.2; // [5.1, 4.1, 3.1, 2.1]

1..10..2; // [1, 3, 5, 7, 9]

0..3..0.8; // [0, 0.8, 1.6, 2.4]

10..1..-2; // [10, 8, 6, 4, 2]

1..#5..2; // [1, 3, 5, 7, 9]

1..5..#3; // [1, 3, 5]

La expresión de rango se maneja especialmente para cadenas con un solo carácter. Por ejemplo, las siguientes
expresiones de rango también son válidas:

“a”..“e”; // ["a B C D e"]

“a”..#4..2; // [“a”, “c”, “e”, “g”]

“a”..“g”..#3; // [“a”, “d”, “g”]

Si se requiere que una expresión de rango generada comience y termine precisamente en los valores de expresión de
rango mínimo y máximo, podemos aproximar un incremento, acercándonos lo más posible al incremento y manteniendo
una distribución equitativa de números entre los límites del rango. Esto se puede hacer con el signo de tilde (~) antes del
tercer parámetro.

0..7..~0.75; // [0, 0.777, 1.555, 2.333, 3.111, 3.888, 4.666, 5.444, 6.222, 7]

6.3. Expresión condicional en línea

InlineConditionalExpression = Expresión ? Expresión : Expresión;

La primera expresión en la expresión condicional en línea es expresión de condición cuyo tipo es bool. Si es cierto, el
valor de “?” se devolverá la cláusula; de lo contrario, se devolverá el valor de la cláusula ":". No es necesario que los tipos
de expresiones para las condiciones verdaderas y falsas sean iguales. Ejemplo:
Machine Translated by Google

x = 2;
y = (x % 2 == 0) ? “fu”: 21;

Las expresiones condicionales en línea se replican en las tres expresiones. Ejemplo:

x = [verdadero, falso,
verdadero]; y = [“foo”, “bar”,
“qux”]; z = [“ding”, “dang”, “dong”];

r = x? y : z; // replica, r = [“foo”, “dang”, “qux”]

6.4. Expresión de acceso de miembros


La expresión de acceso a miembros tiene la forma

xyz

"y" y "z" podrían ser propiedades o funciones miembro. Si no son accesibles, se devolverá nulo .

Ejemplo:

p = Circle.ByCenterPointRadius(Point.ByCoordinates(5, 0, 0), 10); x =


p.PuntoCentral.X; // expresión de acceso a miembros, x = 5

6.5. Expresión de acceso a la lista


La expresión de acceso a la lista tiene la forma

hacha]

“x” podría ser un valor entero o una clave de cualquier tipo (si “a” es un diccionario).

Se aplican las siguientes reglas:


• Si solo está obteniendo valor, si "a" no es una lista, o la longitud de "a" es menor que "x", o el rango de "a"
es menor que el número de índices, por ejemplo, el rango de "a" es 2 pero la expresión es a[x][y][z], habrá una
advertencia "IndexOutOfRange" y se devolverá un valor nulo . • Si está asignando un valor a la lista, si "a" no es
una lista, o la longitud de "a" es menor que "x", o la
el rango de "a" es menor que el número de índices, "a" se ampliará o se promoverá su dimensión para que pueda

acomodar el valor. Por ejemplo,

a = 1;
a[1] = 2; // “a” será promovido, a = [1, 2] ahora
Machine Translated by Google

a[3] = 3; // “a” se extenderá, a = [1, 2, null, 3] ahora // “a” se promocionará,


a[0][1] = 3; a = [[1, 3], 2, null, 3] ahora

6.6. Operadores Los


siguientes operadores son compatibles con DesignScript:

+ Suma aritmética
- Resta aritmética
*
multiplicación aritmética
/ división aritmética
% modo aritmético
> comparación grande
>= Comparación grande que
< Comparar menos
<= Comparación menor que
== Comparación igual
!= Comparación no igual
&& lógico y
|| ! lógico o
No lógico
- Negar

Todos los operadores admiten la replicación. Excepto el operador unario “!”, todos los demás operadores también admiten la
guía de replicación. Es decir, los operandos podrían ser guías de replicación adjuntas.

x = [1, 2, 3]; y =
[4, 5, 6]; r1 = x + y;
// replicación // r1
= [5, 7, 9]

r2 = x<1> + y<2>; // guía de replicación // r2 =


[ // // // //
[5, 6, 7], [6,
7, 8], [7, 8,
9]
]

Precedencia del operador

Precedencia Operador

-
6

5 *, /, %

4 +, -
Machine Translated by Google

3 >, >=, <, <=, ==, !=

2 &&

1 ||

6.6.1. Operadores aritméticos

+, -, *, /, %

Normalmente, los operandos son valores enteros o valores de punto flotante. "+" se puede utilizar como concatenación de cadenas:

s1 = “Diseño”; s2
= “Guión”; s = s1
+ s2; // “Script de diseño”

6.6.2. Operadores de comparación Las

declaraciones que utilizan estos operadores dan como resultado un valor "verdadero" o "falso".

>, >=, <, <=, ==, !=

6.6.3. Operadores lógicos Cada

declaración que usa un operador lógico solo puede devolver un valor "verdadero" o "falso".

&&, ||, !

El operando debe ser de tipo "bool"; de lo contrario, se incurrirá en conversión de tipo.

7. Declaraciones

7.1. Declaraciones vacías


declaración vacía es

7.2. Instrucciones de importación Las

instrucciones de importación importan otro archivo de código fuente de DesignScript o ensamblado de C# en el espacio de nombres actual.

ImportStatement = "importar" "(" (cadena | (identificador de cadena))")"


Machine Translated by Google

Si importa un ensamblado de C#, la máquina virtual DesignScript generará clases de DesignScript para las clases definidas en el ensamblado,

esto lo hace FFI.

Las declaraciones de importación podrían importar todas las entidades encontradas en la ubicación, o para una entidad nombrada específica
encontrada en la ubicación.

La ubicación puede ser especificada por:

• Una ruta de archivo relativa, utilizando las convenciones del sistema operativo local. • Una

ruta de archivo absoluta, utilizando las convenciones del sistema operativo local.
• Una URI.

Ejemplo:

importar (“/home/dev/libraries/foo.ds”); importar


(Punto de “Geometry.dll”);

Tenga en cuenta que las declaraciones de importación solo se pueden usar en archivos DesignScript (con una extensión ".DS"), que se pueden

importar a Dynamo. Las declaraciones de importación no se pueden usar en nodos de bloque de código en Dynamo.

7.3. Declaraciones de expresión

DeclaraciónDeExpresión = Expresión “;”

Las sentencias de expresión son expresiones sin asignación.

7.4. asignaciones

Asignación = Expresión “=” ((Expresión “;”) | LanguageBlock)

El lado izquierdo de “=” debe ser asignable. Por lo general, es una expresión de acceso a miembros o una expresión o variable de acceso a una

matriz . Si el lado izquierdo es una variable que no se ha definido antes, la declaración de asignación definirá esta variable.

7.5. Declaraciones de flujo


Las declaraciones de flujo cambian el flujo de ejecución del programa. Una declaración de flujo es una de las siguientes:

1. Una declaración de devolución .

2. Una declaración de ruptura en el bloque de la declaración for o while en el bloque de lenguaje imperativo.

3. Una declaración continua en el bloque de la declaración for o while en el bloque de lenguaje imperativo.

7.5.1. Declaraciones de devolución


Machine Translated by Google

ReturnStatement = "devolver" Expresión ";"

Una declaración de "retorno" finaliza la ejecución de la función más interna y regresa a su llamador, o
finaliza el bloque de idioma imperativo más interno y regresa al bloque de idioma o función de nivel
superior.

7.5.2. romper declaraciones

BreakStatement = "romper" ";"

Una declaración de "ruptura" finaliza la ejecución del bucle "for" o bucle " while" más interno .
Ejemplo:

yo = [Imperativo] {

a = 0;
while(true) // esto hará que el bucle while se ejecute indefinidamente {

a = a+1;
si (un == 10)
descanso; // cuando a es igual a 10, esta declaración sale del ciclo

} devuelve un; // un = 10
};

yo = [Imperativo] {

a = 0; l
= 1..100; para
(yo en l) {

a = yo;
si (a == 15)
romper;

} devuelve un; // a = 15 y no 100


};

7.5.3. Continuar declaración

ContinuarDeclaración = “continuar” “;”

Ejemplo:

yo = [Imperativo]
Machine Translated by Google

{
a = 0;
l = 1..10;
para (yo en l)
{
if(i%2 != 0) // salta todos los números impares
Continuar; // continuar con la siguiente iteración del ciclo, omitir el resto del cuerpo

a = a + yo;

} devuelve un; // a = 30, suma de todos los números pares hasta 10


};

Una instrucción "continuar" inicia la siguiente iteración del bucle "for" o bucle " while" más interno .

7.6. Si declaraciones
Las declaraciones "si" especifican la ejecución condicional de múltiples ramas en función del valor booleano de cada
expresión condicional. Las declaraciones "si" solo son válidas en el bloque de lenguaje imperativo.

IfStatement =
“if” “(” Expression “)” StatementBlock { “elseif” “(”
Expression “)” StatementBlock } [ “else” StatementBlock ]

Ejemplo:

x = 5;
si (x > 10) { y =
1;

} elseif (x > 5) { y =
2;

} elseif (x > 0) { y =
3;

} más
{ y = 4;
}

7.7. Bucles
En el código Imperative DesignScript, un programador tiene la opción de escribir código que itere manualmente sobre la
lista, extrayendo elementos individuales de la colección uno a la vez. Los bucles son construcciones de lenguaje para
repetir la ejecución sobre un bloque de código. El número de veces que se llama a un bucle se puede regir por la longitud
de la lista (bucle "for") donde se llama al bucle con cada elemento de la lista como entrada. El número de iteraciones de
un bucle también se puede determinar mediante una expresión booleana ("bucle while"), donde se llama al bucle hasta
que la expresión booleana devuelve falso. Los bucles se pueden utilizar para generar colecciones, buscar una solución o
llamar de forma repetitiva a un determinado bloque de código.
Machine Translated by Google

7.7.1. Mientras que las declaraciones

Las declaraciones "while" ejecutan repetidamente un bloque en un bucle hasta que la condición se vuelve falsa. Las
declaraciones "while" solo son válidas en el bloque de lenguaje imperativo. Un ciclo while puede ejecutarse infinitamente
si la condición no se evalúa como falsa , por lo que es importante tener una condición de terminación para salir del ciclo,
a menos que haya una declaración de interrupción explícita dentro del ciclo que obligue a la ejecución a salir del ciclo
while . .

MientrasInstrucción = “mientras” “(” Expresión “)” BloqueDeInstrucción

Ejemplo:

suma =
0; x = 0;
mientras (x < 10)
{
suma = suma +
x; x = x + 1;

} // suma == 55

7.7.2. Para declaraciones

"for" itera todos los valores en la cláusula "in" y asigna el valor a la variable de bucle. La expresión en la cláusula "in"
debe devolver una lista; si es un singleton, es una evaluación de declaración única. Las declaraciones "for" solo son
válidas en el bloque de lenguaje imperativo. Al igual que las sentencias while , se puede salir de un bucle for utilizando
una sentencia break en el cuerpo de la sentencia for .

ForStatement = "for" "(" Identificador "en" Expresión ")" StatementBlock

Ejemplo:

suma =
0; para (x en 1..10) {

suma = suma + x;

} // suma == 55

8. Bloques de idioma
DesignScript tiene dos paradigmas de lenguaje: asociativo e imperativo. Cada uno de estos idiomas está escrito
en sus respectivos bloques de idioma.
Machine Translated by Google

8.1. Bloque de idioma asociativo predeterminado


De forma predeterminada, todas las declaraciones están en un bloque de idioma asociativo de nivel superior predeterminado, por lo que la actualización asociativa está

habilitada de forma predeterminada.

A diferencia de un bloque de idioma anidado, no hay declaración de retorno en el bloque de idioma asociativo de nivel superior.

8.2. Bloque de lenguaje asociativo anidado


Es válido definir explícitamente un bloque de idioma anidado, ya sea asociativo o imperativo, en el bloque de idioma asociativo
predeterminado o en una función. También es válido definir un bloque de idioma imperativo anidado dentro de un bloque de idioma
asociativo anidado y viceversa.

AssociativeLanguageBlock = "[" "Associative" "]" StatementBlock

Las declaraciones en el bloque de lenguaje asociativo predeterminado se ejecutan en el orden en que las declaraciones
dependen unas de otras. Esto significa que todas las dependencias de una instrucción se ejecutan antes que la propia
instrucción, independientemente del orden en que se produzcan las instrucciones en el bloque asociativo.
Las declaraciones en un bloque asociativo anidado se ejecutan secuencialmente hasta que una declaración de retorno devuelve un
valor; de lo contrario, el bloque de idioma devuelve nulo.

No es válido definir un bloque de idioma anidado dentro de un bloque anidado del mismo tipo.

Ejemplos:

x = 1;

// z = 3 z
= [Asociativo] {

y = 2;
devuelve x + y;
}

[Asociativo] {

// bloque de lenguaje asociativo inválido


[Asociativo] { }

8.3. bloque de lenguaje imperativo


El bloque de lenguaje imperativo proporciona una manera conveniente de usar la semántica imperativa. Similar al bloque de
lenguaje asociativo anidado, el bloque de lenguaje imperativo ejecuta todas las declaraciones secuencialmente a menos que una
declaración sea una declaración de devolución para devolver un valor. Un bloque de idioma imperativo solo se puede definir en un
bloque de idioma asociativo externo o en el bloque de idioma asociativo predeterminado.
Machine Translated by Google

Las diferencias clave entre el bloque de idioma asociativo y el bloque de idioma imperativo son: • La
actualización asociativa está deshabilitada en el bloque de idioma imperativo. • Las declaraciones
"if", "for" y "while" solo están disponibles en bloques de lenguaje imperativo.

Ejemplo:

x = 1;

// definir un bloque de idioma imperativo en el bloque de idioma asociativo superior y = [Imperativo]


{

si (x > 10)
{ devuelve 3;

} más si (x > 5)
{ devuelve 2;

} más
{ devuelve 1;
}
}

def suma(x)
{
// define un bloque de lenguaje imperativo dentro de una función, que está en un // bloque de lenguaje
asociativo global return [Imperative] {

s = 0;
para (i en 1..x) {

s = s + yo;
}
devoluciones;
}
}

[Asociativo] {

// define un bloque de lenguaje imperativo dentro de un bloque de lenguaje asociativo return


[Imperativo] {

volver 42;
}
}

[Imperativo] {

// bloque de idioma imperativo inválido


[Imperativo] {
Machine Translated by Google

}
}

9. Guía de replicación y replicación

9.1. Guía de replicación y replicación


La replicación es una forma de expresar la iteración en un bloque de lenguaje asociativo. Se aplica a una llamada de
función cuando el rango de los argumentos de entrada excede el rango de los parámetros. En otras palabras, se puede
llamar a una función varias veces en la replicación y el valor de retorno de cada llamada de función se agregará y
devolverá como una lista.

Hay dos tipos de replicación:


• Replicación zip: para múltiples listas de entrada, la replicación zip consiste en tomar todos los elementos de cada
lista en la misma posición y llamar a la función; el valor de retorno de cada llamada de función se agrega y se
devuelve como una lista. Por ejemplo, para los argumentos de entrada x = [x1, x2, ..., xn] e y = [y1, y2, ..., yn],
al llamar a la función f(x, y) con replicación zip, es equivalente a [f(x1, y1), f(x2, y2), ..., f(xn, yn)]. Como las
longitudes de los argumentos de entrada pueden ser diferentes, la replicación zip podría ser: • Replicación zip más
corta: use la longitud más corta • Replicación zip más larga: use la longitud más larga, el último elemento en la
lista de entrada corta

se repetirá La
replicación zip predeterminada es la replicación zip más corta; de lo contrario, debe usar la guía de replicación
para especificar el enfoque más largo.
• Replicación cartesiana: equivale a bucle anidado en lenguaje imperativo. Por ejemplo, para los
argumentos de entrada x = [x1, x2, ..., xn] e y = [y1, y2, ..., yn], al llamar a la función f(x, y) con
replicación cartesiana y los índices cartesianos son [0, 1], lo que significa que la iteración sobre el
primer argumento es el primer ciclo, y la iteración sobre el segundo argumento es el ciclo anidado;
es equivalente a [f(x1, y1), f(x1, y2), ..., f(x1, yn), f(x2, y1), f(x2, y2), ..., f( x2, yn), ..., f(xn, y1), f(xn,
y2), ..., f(xn, yn)].

La guía de replicación se utiliza para especificar el orden de los índices de replicación cartesiana; la guía de replicación
inferior, el lazo exterior. Si dos guías de replicación tienen el mismo valor, se aplicará la replicación zip.

Guía de replicación = “<” número [“L”] “>” {“<” número [“L”] “>”}

Solo se permite un valor entero en la guía de replicación. El sufijo "L" indica si la replicación es una replicación zip, luego
use la estrategia de replicación zip más larga. El número de guía de replicación especifica el nivel anidado.
Por ejemplo, la guía de replicación xs<1><2> indica que el argumento debe ser al menos bidimensional y su nivel
anidado es 2; también podría expresarse mediante el siguiente pseudocódigo:
Machine Translated by Google

// xs<1><2>
para (ys en xs) {

para (y en ys) {

...
}
}

Ejemplo:

def sumar(x: var, y: var) {

devuelve x + y;
}

x = [1, 2]; ys =
[3, 4]; zs = [5,
6, 7];

// usa la replicación zip r1 =


add(xs, ys); // r1 = [4, 6]

// usa la replicación zip más corta r2 = add(xs,


zs); // r2 = [6, 8];

// la replicación zip más larga debe especificarse a través de la guía de replicación. // las guías de
aplicación deben tener el mismo valor; de lo contrario, // se aplicará la replicación cartesiana r3 =
add(xs<1L>, zs<1L>); // r3 = [6, 8, 9]

// usa replicación cartesiana r4 =


add(xs<1>, ys<2>); // r4 = [[4, 5], [5, 6]];

// usa replicación cartesiana r5 =


add(xs<2>, ys<1>); // r5 = [[4, 5], [5, 6]];

Además de la replicación para la llamada de función explícita, la guía de replicación y replicación también se puede aplicar
a las siguientes expresiones: 1. Operadores binarios como +, -, *, /, etc. Todos los operadores binarios en DesignScript se
pueden ver como una función que acepta dos parámetros, y el operador unario se puede ver como una función que
acepta un parámetro. Por lo tanto, la replicación se aplicará a la expresión “xs + ys” si “xs” e “ys” son listas.

2. Expresión de rango.
3. Expresión condicional en línea en forma de “xs ? ys : zs” donde “xs”, “ys” y “zs” son listas.
4. Indexación de matriz. Por ejemplo, xs[ys] donde ys es una lista. La replicación podría aplicarse a la matriz
indexación en ambos lados de la expresión de asignación. Tenga en cuenta que la replicación no se aplica a varios
índices.
Machine Translated by Google

5. Expresión de acceso a miembros. Por ejemplo, xs.foo(ys) donde xs e ys son listas. Replicación
La guía podría aplicarse a objetos y argumentos. Si xs es una lista, xs debería ser una lista homogénea, es decir,
todos los elementos en xs son del mismo tipo.

9.2. Regla de distribución de funciones para replicación y guía de replicación


El uso de la replicación zip o la replicación cartesiana depende totalmente de la guía de replicación especificada, los tipos de
argumentos de entrada y los tipos de parámetros. Debido a que el argumento de entrada podría ser una lista heterogénea, la
implementación calculará qué combinación de replicación generará la distancia de conversión de tipos más corta.

Tenga en cuenta que si el argumento es una lista irregular, el resultado de la replicación no está definido.

Formalmente, para una función "f(x1: t1, x2: t2, ..., xn: tn)" y argumentos de entrada "a1, a2, ..., an", la regla de envío de la
función es: 1. Obtener una lista de la función sobrecargada f() con el mismo número de parámetros. Estas funciones son

candidatos.

2. Si existen guías de replicación, se procesarán nivel por nivel. Por ejemplo, para la llamada de función f(as<1><1>,
bs, cs<1><2>, ds<2><1L>), existen dos niveles de guías de replicación.

una. Para cada nivel, ordene las guías de replicación en orden ascendente. Si la guía de replicación es inferior a
o igual a 0, se omitirá esta guía de replicación (es una guía de replicación stub).
i. Para cada guía de replicación, si aparece en varios argumentos, se aplica la replicación zip.
Por defecto, usando el cordón más corto. Si algún número de guía de replicación tiene el
sufijo "L", se aplica el lazado más largo. ii. De lo contrario, se aplica la replicación cartesiana.
iii. Repita el paso b hasta que se hayan procesado todas las guías de replicación.

b. Repita el paso a hasta que se hayan procesado todos los niveles de


replicación. C. Para este ejemplo, se generarán las siguientes
i. replicaciones: replicación zip en as, cs replicación cartesiana
ii. en ds
Machine Translated by Google

iii. Replicación zip en as, ds


IV. Replicación cartesiana en ds
3. Después del procesamiento de la guía de replicación, se calcula el rango de cada argumento de entrada: r1 =
rango(a1), r2 = rango(a2), ..., <número de rn = rango(an); para cada rango, actualícelo a r = r -
guía de replicación en el argumento>. La lista final [r1, r2, ..., rn] se denomina lista de reducción, cada valor de
reducción representa un bucle anidado máximo posible en el argumento correspondiente.

4. Con base en esta lista de reducción, calcule una combinación de listas de reducción cuyos valores de elementos sean
menores o iguales que el valor de reducción correspondiente en la lista de reducción base. Para cada lista de
reducción [r1, r2, ..., rn], realice iterativamente el siguiente cálculo para generar repeticiones: a. Para cualquier ri >
0, ri = ri - 1. Si hay múltiples reducciones cuyos valores son mayores o iguales a 1, se aplica la replicación zip; de
lo contrario, se aplica la replicación cartesiana.

5. Combine las replicaciones generadas en los pasos 3 y 4, en función de los argumentos de entrada y la firma de las
funciones candidatas, elija la mejor función coincidente y la mejor estrategia de replicación. Durante el proceso, si
el tipo de parámetro y el tipo de argumento son diferentes, se calculará la puntuación de distancia de tipo.

10. Lista@Nivel
List@Level es una función de lista especial que devuelve una lista aplanada en un nivel específico. Si una entrada se
especifica como una lista dominante, la estructura de la salida será la misma que la estructura de la lista dominante.

Por ejemplo, para dos entradas xs (lista de rango 4) e ys (lista de rango 3), queremos llamar a la función f() con el
segundo nivel de xs e ys, donde xs es la lista dominante: +(xs@@L2 , ys@L2). La salida conserva la estructura de la lista de
xs , ya que es la lista dominante (representada por el símbolo doble '@'):

x = [[[["a","b"], ["c","d"]], [["e","f"], ["g","h"]]], [ [["i","j"]]]]; y = [[["1","2"], ["3","4"], ["5","6"]],


[["7","8"], ["9" ,"10"], ["11","12"]]]; x = xs@@L2 + ys@L2;
Machine Translated by Google

xs sí

ys@L2 devuelve:
Machine Translated by Google

[
[1, 2]
[3, 4]
[5, 6]
[7, 8]
[9, 10]
[11, 12]
]

xs@L2 devuelve:

[
[a, b]
[c, d]
[e, f]
[g, h]
[i, j]
]
Machine Translated by Google

x = xs@@L2 + ys@L2 devuelve:

11. Funciones integradas


Las siguientes funciones son funciones globales integradas que son nativas de DesignScript y se usan internamente en la máquina

virtual. Estos no están expuestos en la interfaz de usuario de Dynamo, pero aún se pueden invocar desde el bloque de código.
nodos:

• Concat:var[]..[](lista1: var[]..[], lista2: var[]..[])


Concatena list1 y list2 y devuelve una nueva lista.

• Cuenta:int(lista: var[]..[])
Devuelve el número de elementos de la lista especificada.

• Evaluar:var[]..[](fptr: fptr, params: var[]..[], desempaquetar: bool)


Evalúa un puntero de función con parámetros
especificados. • Dormir (x: int)
Ponga la máquina virtual en reposo durante x milisegundos.

• Transponer:var[]..[](lista: var[]..[])
Intercambia filas y columnas en una lista de listas. Si hay algunas filas que son más cortas que otras, los valores nulos se

insertan como marcadores de posición en la lista de resultados de modo que siempre sea rectangular.

• __GC()
Forzar la recolección de basura.

Las siguientes funciones integradas se exponen al usuario final como heredadas de la clase FFI List:

• Equals:bool(objetoA: var, objetoB: var)


Determina si dos instancias de objeto son iguales.

• GroupByFunction(lista: var[]..[], func: Función)


Agrupa elementos en una lista según lo determinado por una función de predicado.
Machine Translated by Google

• MaximumItemByKey(lista: var[]..[], keyProjector: Función)


Determina el elemento máximo en una lista que satisface una función de predicado.
• ElementoMínimoPorClave(lista: var[]..[], proyector de teclas: Función)
Determina el elemento mínimo en una lista que satisface una función de
predicado. • Clasificación (lista: var[]..[])
Cuenta el rango máximo de la lista especificada.
• RemoveIfNot:var[]..[](lista: var[]..[], tipo:cadena)
Elimina los miembros de la lista que no son miembros del tipo especificado.
• SortByFunction(lista: var[]..[], func: Función)
Ordena los elementos de una lista de acuerdo con una
función determinada. • TrueForAll: bool(lista: var[]..[], predicado: Función)
Devuelve verdadero si el predicado dado se cumple para todos los elementos de la lista.
• TrueForAny: bool(lista: var[]..[], predicado: Función)
Devuelve verdadero si el predicado dado se cumple para cualquiera de los elementos de la lista.

12. Internos

12.1. Actualización asociativa Tenga en cuenta

que la actualización asociativa está deshabilitada en los nodos de bloque de código al no permitir la redefinición de
variables, sin embargo, el lenguaje en sí lo admite. La actualización asociativa se puede ver en acción escribiendo archivos
DesignScript y ejecutándolos.

La asociatividad es una característica de DesignScript que permite la propagación de un cambio de variable a todas las
declaraciones dependientes del programa. La propagación del cambio ocurre en tiempo de ejecución y es manejada por el mecanismo
de actualización de la máquina virtual DesignScript.

Ejemplo de actualización asociativa:

1: x = 1; 2:
y = x; 3: x
= 3;

Si el código está en bloque de lenguaje asociativo, se ejecutará de la siguiente manera: 1.


“x” se establece en 1.

2. “y” se establece en “x” y depende de “x”, por lo que “y” es 1. 3.


“x” se cambia a 3. Como “y” depende de “x”, “y” será actualizado a 3.

En la línea 2, “y” depende de “x”, o “y” depende de “x”; luego, en la línea 3, el cambio de "x" actualizará "y" mediante la reejecución
de la instrucción de asignación correspondiente que establece la asociatividad.

Por otro lado, si el código está en bloque de lenguaje imperativo, el cambio de "x" no actualizará "y", al igual que otros lenguajes de
programación.

Hay cuatro elementos clave en la definición y actualización de la asociatividad:


Machine Translated by Google

1. El establecimiento de la asociatividad se realiza mediante sentencia de asignación.


2. La actualización se realiza volviendo a ejecutar la instrucción de asignación.
3. El dependiente (en el lado izquierdo de la asignación) podría ser
• Variables

• Propiedades 4.
Las entidades de las que se puede depender son •
Variables

• Propiedades
• Funciones

12.1.1. Establecimiento de asociatividad


La declaración de asignación en bloque de lenguaje asociativo establece una relación entre las entidades asignadas y las
entidades utilizadas en la declaración para calcularla. La redefinición eliminará la asociatividad anterior (si la hay) y redefinirá
la asociatividad.

Es importante señalar que las entidades asignadas y las entidades de las que se depende deben definirse en el mismo
ámbito. Ver ámbito de asociatividad.

Un ejemplo en bloque de lenguaje asociativo

1: x = 1; 2:
y = 2; 3: z
= foo(x, y); 4: x = 3;
5: y = 4; 6: z = 0; 7:
x = 5;

En la línea 3, la asignación establece la asociatividad entre “z” y “foo”, “x” e “y”, por lo que “z” dependerá de “foo”, “x” e “y”.
Después de actualizar “x” a 3, la línea 3 se volverá a ejecutar para actualizar “z”; después de actualizar "y" a 4 en la línea 5, la
línea 3 se volverá a ejecutar.

En la línea 6, la redefinición de “z” elimina la asociatividad previamente establecida. Ahora "z" ya no depende de otras entidades,
por lo que la siguiente actualización de "x" en la línea 7 no incurrirá en un nuevo cálculo de "z".

La declaración de asignación en el bloque de lenguaje imperativo cambia solo las variables/propiedades a las que están asignadas
y no tiene una actualización implícita.

Un ejemplo en bloque de lenguaje imperativo

[Imperativo] {
Machine Translated by Google

1: x = 1; 2: y
= x; 3: x = 3; }

El código se ejecuta línea por línea, no se volverá a realizar ningún cálculo en el bloque de idioma imperativo. Después de la
ejecución, "x" es 3 e "y" es 1.

12.1.2. Actualización por reejecución


El cambio se propaga a todos los dependientes de forma recursiva al volver a ejecutar todas las instrucciones que establecen
la asociatividad.

12.1.3. dependientes
Un dependiente puede ser una variable o una propiedad. El siguiente código muestra el último caso:

clase Foo {

X;
}

f = Foo(); m =
21;

// propiedad “x” depende de “m” fx = m;

metro = 42;

r = fx; // r es 42

Después de que "m" se actualice a 42, la declaración de asignación "fx = m" se volverá a ejecutar para actualizar la propiedad "x".

12.1.4. Entidades de las que se puede depender

12.1.4.1. Variables
El cambio de variable desencadenará actualizaciones de sus dependientes. La variable podría aparecer en:
• Expresión •
Parámetros: en forma de “x = f(y, z)”, donde “x” depende de “f()” y de las variables “y” y
“z”.

• Indexación de listas: en forma de “x = y[z]”, donde “x” depende tanto de las variables “y” como de la variable indexadora
de matrices “z”.

Hay un caso especial para la autorredefinición, es decir, una variable depende de sí misma. Por ejemplo, “a = a + 1”.
Este tipo de autorredefinición no eliminará la asociatividad previamente establecida entre “a” y otras variables. Además, el cambio
de "a" solo actualizará sus dependientes, no "a" en sí. El siguiente ejemplo ilustra este caso:
Machine Translated by Google

1: x = 1; 2:
y = 2; 3: x
= x + y; 4: z = x
+ y; 5: x = x + 1;

El código anterior se ejecutará de la siguiente manera:


1. “x” se establece en 1.

2. “y” se establece en
2. 3. “x” se cambia a “x + y”. Entonces "x" depende de "y", "x" es 3 ahora. 4. “z” se
establece en “x + y”. Entonces "z" depende de "x" e "y", "z" es 5 ahora. 5. "x" se incrementa
en 1. Se activará la actualización de "z" , "z" es 6 ahora.

También está bien que la variable aparezca en la lista de parámetros de la función, tal como muestra el ejemplo en el
establecimiento de la asociatividad .

12.1.4.2. Función
En forma de:

x = f(...);

La asignación establece asociatividad entre “x” y la función “f()”. Cualquier actualización del cuerpo de la función de cualquier "f ()"
sobrecargada provocará la reejecución de esta declaración. Tenga en cuenta que esta función solo está disponible cuando Live Runner
está habilitado (que solo está disponible en el entorno de programación visual).

12.1.4.3. Propiedades
En forma de:

r = xyz;

La asignación establece asociatividad entre “r” y variable “x” y propiedades “y” y “z”. Cualquier actualización de "x", "y" y "z" actualizará
"r".

Ejemplo:

clase Foo {

X;
constructor Foo(_x) {

x = _x;
}
}
Machine Translated by Google

barra de clase
{
foo;
constructor Barra(_x) {

Foo = Foo(_x);
}
}

b = Barra(0); t
= b.foo.x;

b.foo.x = 1; // actualizar “x” b.foo =


Foo(2); // actualiza “foo” b = Bar(3); //
actualizar "b"

Cada actualización en las últimas tres declaraciones volverá a ejecutar la declaración "t = b.foo.x" para actualizar el valor de "t".

12.1.5. Ámbito de asociatividad


Dado que tanto el establecimiento de la asociatividad como la actualización se realizan en tiempo de ejecución, es importante
tener en cuenta que el establecimiento y la actualización de la asociatividad solo deben aplicarse a entidades en el mismo
ámbito; de lo contrario, el resultado no está definido. Si ya existe una asociatividad, la asociatividad puede eliminarse.

Hay cuatro casos no definidos:

1. El dependiente se define en el ámbito superior y depende de las variables definidas en el mismo ámbito,
pero la asociatividad se establece en la función. Por ejemplo, en el código siguiente, "x" e "y" , ambos definidos en el
bloque de lenguaje asociativo global. La ejecución de "foo()" ejecutará la línea 5 para establecer la asociatividad entre "x"
e "y". El comportamiento esperado de este tipo de asociatividad no está definido, por lo tanto, actualizar "y" a 3 no
necesariamente actualizará "x" ya que la máquina virtual DesignScript no admite ejecutar solo la línea 5 sin ejecutar toda
la función "foo()".

1: x = 1; 2:
y = 2; 3:
def foo() 4: { 5:

x = y;
6: devolver nulo;
7: }
8: 9:
foo(); 10: y
= 3; // la actualización de "x" no está definida

2. El dependiente se define en el ámbito superior y depende de variables definidas en el mismo ámbito, pero la asociatividad
se establece en bloque de lenguaje anidado. Por ejemplo, en el siguiente código, "x" y
Machine Translated by Google

"y" ambos definidos en el bloque de lenguaje asociativo global. La ejecución del lenguaje imperativo anidado
establecerá la asociatividad entre "x" e "y" en la línea 5, pero el comportamiento esperado de este tipo de asociatividad
tampoco está definido.

1: x = 1; 2:
y = 2;
3: [Imperativo] 4: { 5:

x = y;
6: devolver nulo;
7: }
8: y = 3; // la actualización de "x" no está definida

3. El dependiente se define en el ámbito superior pero depende de las variables definidas en la función. Para
ejemplo, “x” depende de la variable local “y” en “foo()”.

1: x = 1; 2:
def foo() 3: { 4:

y = 2; x
5: = y;
6: devolver nulo;
7: }
8: foo(); 9:
y = 3;

4. El dependiente se define en el ámbito superior pero depende de las variables definidas en el bloque de idioma anidado. Por
ejemplo, "x" depende de la variable local "y" en el bloque de lenguaje imperativo anidado.

1: x = 1;
2: [Imperativo] 3: { 4:

y = 2; x
5: = y;
6: devolver nulo;
7: }

12.2. Clases
Nota: Las clases solo se pueden declarar en archivos de script DesignScript o archivos que tengan una extensión .DS. Las
declaraciones de clase no están permitidas en los nodos de bloque de código en Dynamo. Los archivos de DS se pueden importar a
una sesión de Dynamo para consumirlos como nodos.
Machine Translated by Google

12.2.1. Declaración de clase

ClassDeclaration =
identificador de "clase" [identificador de "extensión"]
“{“ [Declaración de miembro de clase] “}”

ClasMemberDeclaration =
Declaración de constructor
| Declaración de miembro

Declaración de constructor =
identificador de “constructor” Lista de parámetros
[“:” “base” “(“ ArgumentList “)”]
DeclaraciónBloque

Declaración de miembro =
[Modificador de acceso] [estática] (Declaración de función | Declaración de variable “;”)

AccessMmodifier = “público” | “protegido” | "privado"


Una clase solo se puede definir en el bloque de lenguaje asociativo de nivel superior.

12.2.2. Herencia
DesignScript solo admite la herencia única. Es decir, solo se permite una clase base.

Ejemplo:

clase Punto2D {

...
}

clase Point3D: extiende Point2D {

...
}

12.2.3. Constructores
Aunque no es forzado, pero se sugiere que el nombre del constructor comience con “Por…” para indicar
cómo crear el objeto. Por ejemplo, el constructor de la creación de un Punto puede ser “ByCoordinates()”.

Si la clase hereda de la otra clase, es posible llamar al constructor de la clase base llamando a
"base(...)".

Para crear una instancia de clase, use la declaración de creación de objetos "ClassName.ConstructorName (...)". Si el
nombre del constructor es el mismo que el nombre de la clase, o una clase no tiene constructor (en este caso, un
Machine Translated by Google

el constructor predeterminado se creará internamente), en ambos casos, la declaración de creación de objetos


podría simplificarse como ClassName (...).

Ejemplo:

clase Punto2D {

constructor PorCoordenadas(x, y) {

...
}
}

clase Point3D: extiende Point2D {

constructor PorCoordenadas(x, y, z) : base(x, y) {

...
}

constructor Punto3D() {

...
}
}

// crea una instancia de Point3D p1 =


Point3D.ByCoordinates(1, 2, 3);

// crea la otra instancia de Point3D p2 = Point3D();

12.2.4. Propiedades
Las variables definidas en clase son propiedades. La inicialización de propiedades podría estar en el constructor o en la
definición.

Para distinguir las propiedades de otros tipos de variables, se podría usar la expresión de acceso
de miembros “this.property_name” o “'base.property_name” para indicar que “property_name” es una propiedad de la
clase o una propiedad de la clase base.

Extendiendo el ejemplo anterior de Point2D y Point3D :

clase Punto2D {

x = 0; // inicializa la propiedad "x"


y = 0;

constructor PorCoordenadas(x, y)
Machine Translated by Google

{
esto.x = x;
esto.y = y;
}
}

clase Point3D: extiende Point2D {

z = 0;

constructor PorCoordenadas(x, y, z) : base(x, y) {

esto.z = z;
}

constructor Punto3D() {

= 1; // es propiedad
// es
“y” propiedad
de la clase“x”
base
de la
z =clase
1; base x = 1; base.y

}
}

// crea la otra instancia de Point3D p1 = Point3D();

// x == 1 x =
p1.x;

// actualizar propiedad “y” p1.y


= 2;

12.2.5. Funciones de los miembros


La definición de funciones miembro es la misma que la definición de función normal. Todas las propiedades son
accesibles en las funciones miembro.

12.2.6. Modificadores de acceso


La restricción de acceso a las propiedades de la clase y las funciones de los miembros se especifica mediante etiquetas
public, protected y private. Si no se especifica ningún especificador de acceso para los miembros, por defecto son públicos.

Se aplican las siguientes reglas:

• Se puede acceder a los miembros públicos desde cualquier lugar dentro y fuera de la clase. •
Solo se puede acceder a los miembros protegidos en la clase o en la clase derivada. • Solo se
puede acceder a los miembros privados en la clase.

Ejemplo:
Machine Translated by Google

base de clase
{
propiedad
privada1; prop2
protegida; público prop3;

definición privada
foo1() {...}

protegido def foo2() {...}

// por defecto es public def foo3()


{}

Derivado de la clase: extiende la base


{
barra de definición

() {

// como "prop1" es privado en base, no es accesible x = prop1;

// "prop2" es accesible en la clase derivada y = prop2;

// "prop3" es accesible en la clase derivada z = prop3;

}
}

b = Base();

// como "prop1" es privado, no es accesible fuera de la clase // p1 es nulo p1 =


b.prop1;

// como "prop2" está protegido, no es accesible fuera de la clase // p2 es nulo p2 =


b.prop2;

// como "prop3" es público, es accesible fuera de la clase p3 = b.prop3;

12.2.7. Miembros estáticos


Las propiedades estáticas y las funciones miembro estáticas se definen a nivel de clase. Es decir, la expresión de
acceso tiene la forma de "ClassName.X" o "ClassName.Y()'
Machine Translated by Google

Hay algunas reglas:


• No es válido acceder a miembros estáticos en el nivel de instancia.

• No es válido si una propiedad estática tiene el mismo nombre que una propiedad no estática o un miembro estático
tiene la misma firma que una función miembro no estática. • No es necesario
tener "ClassName". prefijo al llamar a miembros estáticos en la clase.

El siguiente ejemplo muestra estas reglas:

clase Foo {

X;

// error: x se ha definido como una propiedad no estática static x;

Y estático;

def foo() { }

// error: foo() se ha definido como una función miembro no estática static def foo()
{}

barra de definición estática()


{
// error: no es válido llamar a la función miembro estática en la función // miembro no
estática qux();

def qux() {

// está bien llamar a la función de miembro estático en un miembro no estático //


function bar();

}
}

f = Foo();

// error: no es válido acceder a miembros estáticos en el nivel de instancia r = fY;

// obtener el valor del miembro estático "Y" r =


Foo.Y;

// error: no es válido acceder a miembros estáticos en el nivel de instancia r = f.bar();


Machine Translated by Google

// llamar a la función miembro estática "bar()" r =


Foo.bar();

12.2.8. Método _Dispose()


Si se define un método público _Dispose() en la clase, cuando la instancia se recopile como basura, se llamará
a este método, por lo que _Dispose() podría usarse para liberar los recursos adquiridos por instancia. Por lo general,
este método se generará automáticamente para las clases de FFI.

Ejemplo:

clase desechable {

Indicador estático = falso;

def _Dispose() {

Bandera = verdadero;
}
}

[Imperativo] {

d = Desechable();

// función incorporada para forzar la recolección de basura.

__GC(); //
"d" será basura recolectada
}

// Desechable.Bandera es verdadera
r = Desechable.Bandera;

También podría gustarte