| BSUIR Open X. Reload. Students final |
|---|
| Finished |
Maxim Vitalievich decided to learn a new programming language. One of his acquaintances recommended learning the Rust language, as it is the most promising. Yes, the language is really inspiring, but it forces you to face the harsh reality — the great and mighty borrow checker.
To say that Maxim Vitalyevich was somewhat at a loss would be an understatement. To get out of this situation and deal with the borrow checker, Maxim Vitalievich decided to simplify the language.
The new language only supports a predefined set of functions. In total, $$$n$$$ functions are available in the language, the description of each has the following syntax:
<char> := "a" | "b" | ... | "z"
<name> := <char> | <char> <name>
<nameOrRefName> := <name> | "&" <name>
<argument> := <nameOrRefName>
<arguments> := <argument> | <argument> ", " <arguments>
<functionName> := <nameOrRefName>
<functionArguments> := "" | <arguments>
<function> := "fn " <functionName> "(" <functionArguments> ")"
So <function> is a function description. You may notice that the function name can be either"name" or "&name". In the first case, the function returns a value; in the second case, a reference. Examples of correct functions:
fn input() // The input function returns a value and does not contain any arguments.
fn sum(a, b) // The sum function returns a value and takes two arguments by value.
fn add(&a, &b) // The add function returns a value and takes arguments by reference.
fn &ref(a) // The ref function returns a reference and takes an argument by value.
fn assign(a, &b) // The assign function returns a value and takes the first argument
// by value, and the second by reference.
We also give incorrect examples (such examples cannot occur in the input data):
&fn funcd() // Wrong character order.
fn funcb(a, b&) // Wrong character order.
fn funcc(&&a) // Cannot get reference to reference.
fn &&funca() // Can't return a reference to a reference.
fn fn() // Uses fn as the name.
fn funce(fn) // Uses fn as the name.
fn funcf(a, a) // Same argument names.
fn funcg(a, &a) // Same argument names.
To implement some program, the language has the "<declare>" — construct to declare a new variable (or reference). The syntax can be described as follows:
<callArguments> := <expression> | <expression> ", " <callArguments>
<functionCallArguments> := "" | <callArguments>
<functionCall> := <name> "(" <functionCallArguments> ")"
<expression> := <nameOrRefName> | <functionCall>
<declare> := <name> " := " <expression>
Here are correct examples of using the construction:
a := input() // Define a variable with the result value of input().
b := input()
c := a // Assign the old value to the new variable.
d := add(&b, &c) // Call the function, passing arguments by reference.
e := add(ref(b), ref(c))
f := &e
Here are incorrect examples of using the construction (such examples cannot be found in the input data):
a := &input() // Can't get a reference to the result of a function.
fn := a // Cannot use fn as a name.
&b := c // Cannot declare a reference name.
Maxim Vitalievich believes that such a syntax is quite simple, so he cannot make syntax errors when using the language.
However, Maxim Vitalievich can make the following mistakes:
Let's take a closer look at the last point. Maksim Vitalyevich's language has its own borrow checker mechanism. The bottom line is that all variables that are used by value are moved and are no longer available. Consider the following example:
a := input() // a is a value.
b := sum(a, a) // Error!
In this case, the variable "a" is passed by value 2 times, but after the first use it is no longer available, thus an error occurs. In the same time:
a := input() // a is a value.
b := sum(&a, &a) // Correct if sum accepts references. Variable a
// remains available because it was not used by value.
After declaring a variable with the same name (:=), the old variable (if it is a value) is considered to be moved and is no longer available from the next line.
The following rules apply for links:
Consider the following examples:
a := input()
b := a
c := &a // Error, variable a has been moved.
a := input()
b := &a
c := move(a) // Same as c := a. In either case, the variable a is moved.
d := b // Error, variable b is a reference to the value of a that has been moved.
a := input()
b := &a
c := call(a, b) // Error. The variable a has been moved, so the reference cannot be used.
a := input()
b := &a
a := a // The old value of variable a has been moved.
c := clone(b) // Error, variable b refers to the old variable a, which
// has been moved to the previous line.
Since Maxim Vitalievich invented the language and wants to use it, he asks you to implement a program that will check Maxim Vitalievich's code for errors.
The first line contains the number $$$n$$$ — the number of functions.
The following $$$n$$$ lines contain descriptions of functions according to the described syntax. It is guaranteed that all function names are unique, and all argument names for each function are also unique.
The next line contains the number $$$m$$$ — the number of lines in Maxim Vitalyevich's code.
The following $$$m$$$ lines contain constructs for declaring a new variable in accordance with the description of the syntax.
It is guaranteed that the total length of strings does not exceed $$$100\,000$$$. The input data does not contain extra spaces, and there cannot be spaces less than what is described in the syntax of the language.
$$$$$$ 1 \le n \le 20 $$$$$$ $$$$$$ 1 \le m \le 100 $$$$$$
In a single line print "Valid" if the program is correct.
Otherwise, print "Error in line N" (without quotes), where N — is the number of the first line with an error in Maxim Vitalyevich's code.
Line numbering starts at $$$1$$$.
3 fn input() fn clone(&a) fn sum(a, b) 5 a := input() b := input() br := &b s := sum(a, b) bc := clone(br)
Error in line 5
2 fn input() fn clone(&a) 3 a := input() a := &a b := clone(a)
Error in line 3
2 fn &input() fn sum(&a, &b) 3 a := input() b := sum(a, a) c := sum(a, &b)
Valid
In the first test case, the fifth line uses the "br" reference to the value moved in the fourth line.
In the second test case, the value of the variable "a" is used on the third line, but it has already been moved on the previous line.
| Name |
|---|


