• No results found

New User-Defined Opcode Syntax

In document Extensible Computer Music Systems (Page 121-128)

3.3 Csound 7: New Parser, New Possibilities

3.3.4 New User-Defined Opcode Syntax

The new-style UDO syntax provides an alternate way to define UDOs from the previous system (here called “old-style UDO”). This was done to work with explicit types and structs, which the older-style UDO syntax could not accommodate.

Motivations

With the introduction of the new type system in Csound6 and structs in Csound7, the old-style UDO syntax presented problems for defining arguments with multi-character type names. Listing 3.37 shows an example of old-style UDO syntax. Input and argument types are given as a series of single-letter types, using one letter per argument.

opcode myAdd , k, kk k1 , k2 xin

xout kval endop

Listing 3.37: Pre-Csound 7 UDO definition

Attempting to extend the old-style specification would have been awkward at best. Listing 3.38 shows some possible approaches to extend the old-style syntax. Note that each form requires a special start character to determine when a possible multi-character type started, and a special end character to determine when the type name ended. Arguably, these alternatives are not very easy to read or understand.

opcode my_opcode , a' MyType ;kk , a ...

endop

opcode my_opcode , a" MyType "kk , a ...

endop

opcode my_opcode , a: MyType ;kk , a ...

endop

Listing 3.38: Possible alternate syntaxes for old-style UDOs

Also, another problem with old-style UDOs is that the argument specifi- cation is done using text instead of a quoted string. Because of this, special lexer and parser rules were required to handle the case of UDO argument specifications. This made the lexer and parser rules for UDOs awkward to extend.

Design

The design of new-style UDOs took into account both the requirements for multi-character type names as well as conventions found in other programming languages. Listing 3.39 shows examples of a myAdd function in C/C++/Java and Pascal. Like Csound, these are statically typed languages; they all share a common approach to function definition. Input arguments for a function are listed with both the name of the input argument as well as its type. For output arguments, these languages specify only the types of the output arguments, but not names.

// C, C++, Java

float myAdd ( float k1 , float k2) { return k1 + k1;

}

{ Pascal }

function myAdd (k1 , k2: real ): real ; begin

myAdd := k1 + k2; end ;

Listing 3.39: Function definitions in various programming languages In the C/C++/Java example, float is specified as the output argument type, then the myAdd function name is given, and float k1 and float k2 are specified in a comma-separated list within parentheses. In the Pascal example, k1 and k2 are declared as input arguments with the real type, and the output argument type is also specified as a real. Note that the type of the value returned from the function, as specified in the return line in

the C example and with the myAdd := statement in the Pascal example, is type-checked to agree with the specified output type.

A new syntax was developed for Csound 7 to accommodate types that are longer than one character in length. An example of this syntax is presented in Listing 3.40. This syntax shares common properties found in the examples in Listing 3.39: input arguments are given as a list of names together with their types, and the output types are specified without names in a second list. Because Csound allows for returning multiple values from an opcode, a single output type-specifier was insufficient to accommodate Csound opcode definitions. Consequently, a list within parentheses was used.

; void return

opcode no_return (k1 , k2): void endop

;; Single k- type return opcode myAdd (k1 , k2):k endop

;; Empty return , equivalent to void opcode myAdd (k1 , k2) :()

endop

;; Single k- type return opcode myAdd (k1 , k2):(k) endop

;; Multiple type return

endop

Listing 3.40: Csound 7 new-style UDO definitions

The new-style UDO syntax was chosen to look similar to function definition forms found in other languages. It also adds the ability to specify both argument names and types. In Listing 3.40, the input arguments are specified as simply k1 and k2, but in Listing 3.34, the to_polar opcode takes in an argument of num:Rectangular, using an explicitly-typed variable name.

The practice of defining variable names for input arguments follows the same conventions for variable names found elsewhere in the Csound Orchestra language. Users can choose to use non-qualified variable names, falling back on the first-letter rule to determine the type of the variable, or use the name:type convention to explicitly give the type for the argument. It is the latter convention that allows for variables to use multi-character type names.

The types listed for the output argument of new-style UDOs can be of three forms: a single output type, a comma-separated list of output types within parentheses, or the word void, which denotes no return arguments. Of the three, the parentheses form is the standard practice, as it is generic and works with zero, one, or multiple return types. The void and single-arg forms are therefore syntactic sugar for quicker and easier reading and writing.

Implementation

Implementing new-style UDOs required changes in the lexer, parser, and semantic analyser. For the lexer, the only new requirement was for a new VOID_TOKEN type that would match the word void. For the parser, the existing udo_definition was augmented to include the new-style UDO syntax, and additional rules were added for the input and output argument

lists for new-style UDOs. The code for the grammar changes are shown in Listing 3.41.

udo_definition : UDOSTART_DEFINITION identifier ',' UDO_IDENT ',' UDO_IDENT NEWLINE statement_list UDOEND_TOKEN NEWLINE

| UDOSTART_DEFINITION identifier udo_arg_list ':' udo_out_arg_list NEWLINE statement_list UDOEND_TOKEN NEWLINE ; udo_arg_list : '(' out_arg_list ')' ; udo_out_arg_list : '(' out_type_list ')' | VOID_TOKEN ;

out_type_list : out_type_list ',' out_type ;

out_type : identifier

| array_identifier ;

Listing 3.41: New-style UDO grammar rules

Finally, two changes were made to the semantic analyser. Firstly, internal representations of opcode argument specifications were modified to allow multi-character types by using delimiters. The form used was the one shown in the last example in Listing 3.38, using a colon and semi-colon as start and end delimiters. While this would have been awkward for users to use,

using it internally would have no impact on the user. This approach was taken as all opcodes, including native ones, ultimately hold their input and output arguments in strings. Updating the code that parses argument strings and adding delimited multi-character types was vastly simpler than trying to change argument specifications for all opcodes.

Secondly, when the analyser encountered a new-style UDO, it would first rewrite the TREE. The analyser would look at all input arguments and their types, generate an input argument string, and generate an xin opcode call. It would then look at the specified output argument types, generate an output argument string, and verify that a type-appropriate xout opcode call was found. Finally, the input and argument type strings were appended to the UDO TREE.

By the end of the TREE rewrite process, the UDO TREE would be in a format compatible with the old-style UDO format. From here, semantic analysis and compilation for UDOs proceeded as before.

Summary

Csound7 provides a new-style UDO syntax that is designed to work with multi-character type names. This allows UDOs to work with structs and is enabled by the use of explicitly typed variable names. The new syntax lets users specify input arguments and types together, rather than specifying types in one place and arguments by name in another, as was done with old-style UDOs. Finally, the new-style UDO syntax is arguably simpler to read and write, and uses a familiar design found in other programming languages.

In document Extensible Computer Music Systems (Page 121-128)