Skip to content

Commit

Permalink
change 'ref x = y;' to only make lvalue bindings
Browse files Browse the repository at this point in the history
add 'forward x = y;' for the old behavior of binding either a ref of an lvalue or a capture of an rvalue
  • Loading branch information
jckarter committed Nov 27, 2011
1 parent 9c89962 commit 3c0d006
Show file tree
Hide file tree
Showing 13 changed files with 134 additions and 60 deletions.
107 changes: 60 additions & 47 deletions ChangeLog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@
Tool changes:
-------------
* A "clayfix" program is provided to update code written for Clay 0.0 to
compile in 0.1. It is fairly simple at this point, but most converted code should
just work. Changes that can't be clayfix-ed are noted in this changelog.
compile in 0.1. It is fairly simple at this point, but most converted code
should just work. Changes that can't be clayfix-ed are noted in this
changelog.
* "clay-bindgen" has been rewritten in Clay, using the libclang C library.

Language changes:
Expand All @@ -15,7 +16,8 @@ Language changes:
callbyname ==> alias
lvalue ==> ref

* Two-dot ellipsis '..' can now be used interchangeably with three-dot ellipsis '...'.
* Two-dot ellipsis '..' can now be used interchangeably with three-dot
ellipsis.
... ==> ..

* The 'procedure' keyword has been changed to 'define'.
Expand All @@ -40,12 +42,13 @@ Language changes:
println("Hello world");
}

* The 'new' keyword has been removed. A 'new()' function is provided in the library
that does the exact same thing.
* The 'new' keyword has been removed. A 'new()' function is provided in the
library that does the exact same thing.

* Hex float syntax (-0x1.234ABCp2) is now supported.

* enum and variant syntax has been changed to be more congruent with record syntax:
* enum and variant syntax has been changed to be more congruent with record
syntax:
// define enum type Foo with values ZIM, ZANG, ZUNG
enum Foo (ZIM, ZANG, ZUNG);

Expand All @@ -55,9 +58,9 @@ Language changes:
// add Zippity,Doo,Dah to variant Foo
instance Foo (Zippity, Doo, Dah);

* Scope guard statements are now provided. 'finally foo();' performs 'foo();' on scope
exit for any reason. 'onerror foo();' performs 'foo();' if the scope is exited by a
thrown exception, without catching the exception.
* Scope guard statements are now provided. 'finally foo();' performs 'foo();'
on scope exit for any reason. 'onerror foo();' performs 'foo();' if the
scope is exited by a thrown exception, without catching the exception.
// 0.0
try {
foo();
Expand Down Expand Up @@ -90,17 +93,18 @@ Language changes:
// 0.1
(a,b) -> a+b+c

* Pattern overloads have been unrestricted. '[F|Foo?(F)] F() {}' will now overload
all symbols matching Foo?(F) instead of just types. Universe overloads also now have
lower precedence than specific overloads. This change may break code even
after it has been clayfix-ed.
* Pattern overloads have been unrestricted. '[F|Foo?(F)] F() {}' will now
overload all symbols matching Foo?(F) instead of just types. Such
overloads also now have lower precedence than specific overloads. This
change may break code even after it has been clayfix-ed.

* Function arguments are now passed by noalias nocapture reference. Mutated arguments
should not alias, and taking pointers to arguments that outlive the function scope
are not allowed. (It's currently unchecked by the compiler, though.) If you need to
pass potentially aliasing mutable references or capture argument references, use
Pointer[T] arguments. Pointers remain unrestricted. Return-by-reference functions
also may still return aliases to their input arguments.
* Function arguments are now passed by noalias nocapture reference. Mutated
arguments should not alias, and taking pointers to arguments that outlive
the function scope are not allowed. (It's currently unchecked by the
compiler, though.) If you need to pass potentially aliasing mutable
references or capture argument references, use Pointer[T] arguments.
Pointers remain unrestricted. Return-by-reference functions also may
still return aliases to their input arguments.

* Switch syntax has been changed.
// 0.0
Expand Down Expand Up @@ -137,19 +141,22 @@ Language changes:
z();
}

* A top-level module name declaration may be included in source files, immediately
after any 'import' definitions.
* A top-level module name declaration may be included in source files,
immediately after any 'import' definitions.
import foo.*;
import bar.*;

in module.name;
Module declarations are not required, but if specified the declared name must match
the name used to import the module. The module name can be followed by an attribute
expression list in parens:
Module declarations are not required, but if specified the declared name
must match the name used to import the module. The module name can be
followed by an attribute expression list in parens:
in module.name (Int64, Float32);
Specifying an integer type as a module attribute sets the default type for unsuffixed
integer literals in the module source code. Likewise, specifying a float type sets
the default type for unsuffixed floating-point literals.

var x = 1; // x will be an Int64
var y = 1.0; // x will be a Float32
Specifying an integer type as a module attribute sets the default type for
unsuffixed integer literals in the module source code. Likewise, specifying
a float type sets the default type for unsuffixed floating-point literals.

* You may now import private members from modules with the following syntax:
import foo.(private member);
Expand All @@ -163,16 +170,16 @@ Language changes:
* Octal integer literals have been removed. Literals starting with 0 are now
interpreted as decimal.

* A single multiple-value expression can now be bound or assigned to multiple variables
without an explicit unpack operator.
* A single multiple-value expression can now be bound or assigned to multiple
variables without an explicit unpack operator.
// 0.0
var a, b = ...multiValues();

// 0.1
var a, b = multiValues();

* Tuple syntax has been changed to use square brackets. Parens are now used only for
grouping.
* Tuple syntax has been changed to use square brackets. Parens are now used only
for grouping.
// 0.0
()
(1,)
Expand All @@ -197,8 +204,8 @@ Language changes:
// 0.1
(x, y) -> (x+1, y-1)

CodePointer (and CCodePointer, etc.) types now must always have their input and
output type lists in tuples, even if there is one input or output:
CodePointer (and CCodePointer, etc.) types now must always have their input
and output type lists in tuples, even if there is one input or output:
// 0.0
CodePointer[(Int, Float), String]
CodePointer[Int, (String, Char)]
Expand All @@ -207,25 +214,25 @@ Language changes:
CodePointer[[Int, Float], [String]]
CodePointer[[Int], [String, Char]]

clayfix's logic for fixing CodePointer types is pretty rudimentary and may break
code that tries to be fancy. It will add a tuple around any single expression in the
input or output field that isn't already in parentheses.
clayfix's logic for fixing CodePointer types is pretty rudimentary and may
break code that tries to be fancy. It will add a tuple around any single
expression in the input or output field that isn't already in parentheses.

* Interface restrictions for generic functions can now be declared:
define foo(x:T, y:T) : T;

bar() {
var a = foo(1, 3); // ok
var b = foo(1_i64, 3_i32); // type error, types of foo()'s parameters must match
var b = foo(1_i64, 3_i32); // type error, types of parameters must match
}
The implementation is currently lazy and stupid; it only checks call sites against the
interface instead of verifying overloads at definition time. This will be changed in the
future.

* C99-compatible complex numbers are now supported with the Complex32, Complex64,
and Complex80 types. Suffixing a floating-point literal with 'j' creates an imaginary
literal. The 'math' module provides type-generic overloads for the standard C99 math
library functions:
The implementation is currently lazy and stupid; it only checks call sites
against the interface instead of verifying overloads at definition time.
This will be changed in the future.

* C99-compatible complex numbers are now supported with the Complex32,
Complex64, and Complex80 types. Suffixing a floating-point literal with
'j' creates an imaginary literal. The 'math' module provides
type-generic overloads for the standard C99 math library functions:
import math.(sqrt);
...
var x = sqrt(4.0f); // 2.0f
Expand All @@ -251,11 +258,17 @@ Language changes:
f64 ==> ff
f80 ==> l or (to coerce an integer-looking literal) fl

* A new eval form supports evaluation of static strings as code. eval can be used
as a statement or expression.
* A new eval form supports evaluation of static strings as code. eval can be
used as a statement or expression.
eval #"""println("Hello world");""";
var x = eval #"1 + 2";

* "ref x = y;" will now only bind references to lvalues. The old behavior of
implicitly capturing rvalues or referencing lvalues is provided by
'forward x = y;" now. clayfix will convert all "ref" bindings to "forward"
bindings. Statement forms that implicitly created "ref" bindings, such as
"for" and "..for" loops, now create "forward" bindings.

Library changes:
----------------
* The bitwise operation functions have been given shorter names:
Expand Down
3 changes: 2 additions & 1 deletion compiler/src/analyzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2147,7 +2147,8 @@ EnvPtr analyzeBinding(BindingPtr x, EnvPtr env)
switch (x->bindingKind) {

case VAR :
case REF : {
case REF :
case FORWARD : {
MultiPValuePtr right = analyzeMulti(x->values, env, x->names.size());
if (!right)
return NULL;
Expand Down
3 changes: 2 additions & 1 deletion compiler/src/clay.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1147,7 +1147,8 @@ struct Label : public Statement {
enum BindingKind {
VAR,
REF,
ALIAS
ALIAS,
FORWARD
};

struct Binding : public Statement {
Expand Down
31 changes: 31 additions & 0 deletions compiler/src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3695,6 +3695,37 @@ EnvPtr codegenBinding(BindingPtr x, EnvPtr env, CodegenContextPtr ctx)
}

case REF : {
MultiPValuePtr mpv = safeAnalyzeMulti(x->values, env, x->names.size());
if (mpv->size() != x->names.size())
arityError(x->names.size(), mpv->size());
MultiCValuePtr mcv = new MultiCValue();
for (unsigned i = 0; i < x->names.size(); ++i) {
PValuePtr pv = mpv->values[i];
if (pv->isTemp)
argumentError(i, "ref can only bind to an lvalue");
TypePtr ptrType = pointerType(pv->type);
CValuePtr cvRef = codegenAllocNewValue(ptrType, ctx);
mcv->add(cvRef);
}
int tempMarker = markTemps(ctx);
int marker = cgMarkStack(ctx);
codegenMulti(x->values, env, ctx, mcv, x->names.size());
cgDestroyAndPopStack(marker, ctx, false);
clearTemps(tempMarker, ctx);
EnvPtr env2 = new Env(env);
for (unsigned i = 0; i < x->names.size(); ++i) {
CValuePtr cv;
cv = derefValue(mcv->values[i], ctx);
addLocal(env2, x->names[i], cv.ptr());

ostringstream ostr;
ostr << x->names[i]->str << "_" << cv->type;
cv->llValue->setName(ostr.str());
}
return env2;
}

case FORWARD : {
MultiPValuePtr mpv = safeAnalyzeMulti(x->values, env, x->names.size());
if (mpv->size() != x->names.size())
arityError(x->names.size(), mpv->size());
Expand Down
6 changes: 3 additions & 3 deletions compiler/src/desugar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ StatementPtr desugarForStatement(ForPtr x) {

BlockPtr block = new Block();
vector<StatementPtr> &bs = block->statements;
bs.push_back(new Binding(REF, identV(exprVar), new ExprList(x->expr)));
bs.push_back(new Binding(FORWARD, identV(exprVar), new ExprList(x->expr)));

CallPtr iteratorCall = new Call(prelude_expr_iterator(), new ExprList());
iteratorCall->args->add(new NameRef(exprVar));
Expand All @@ -151,7 +151,7 @@ StatementPtr desugarForStatement(ForPtr x) {
ExprPtr unpackNext = new Unpack(nextCall.ptr());
BlockPtr whileBody = new Block();
vector<StatementPtr> &ws = whileBody->statements;
ws.push_back(new Binding(REF, x->variables, new ExprList(unpackNext)));
ws.push_back(new Binding(FORWARD, x->variables, new ExprList(unpackNext)));
ws.push_back(x->body);

bs.push_back(new While(hasNextCall.ptr(), whileBody.ptr()));
Expand Down Expand Up @@ -240,7 +240,7 @@ StatementPtr desugarSwitchStatement(SwitchPtr x) {

// initialize %thing
{
BindingPtr b = new Binding(REF, identV(thing), new ExprList(x->expr));
BindingPtr b = new Binding(FORWARD, identV(thing), new ExprList(x->expr));
block->statements.push_back(b.ptr());
}

Expand Down
23 changes: 23 additions & 0 deletions compiler/src/evaluator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2350,6 +2350,29 @@ EnvPtr evalBinding(BindingPtr x, EnvPtr env)
}

case REF : {
MultiPValuePtr mpv = safeAnalyzeMulti(x->values, env, x->names.size());
if (mpv->size() != x->names.size())
arityError(x->names.size(), mpv->size());
MultiEValuePtr mev = new MultiEValue();
for (unsigned i = 0; i < x->names.size(); ++i) {
PValuePtr pv = mpv->values[i];
if (pv->isTemp)
argumentError(i, "ref can only bind to an rvalue");
EValuePtr evPtr = evalAllocValue(pointerType(pv->type));
mev->add(evPtr);
}
int marker = evalMarkStack();
evalMulti(x->values, env, mev, x->names.size());
evalDestroyAndPopStack(marker);
EnvPtr env2 = new Env(env);
for (unsigned i = 0; i < x->names.size(); ++i) {
EValuePtr evPtr = mev->values[i];
addLocal(env2, x->names[i], derefValue(evPtr).ptr());
}
return env2;
}

case FORWARD : {
MultiPValuePtr mpv = safeAnalyzeMulti(x->values, env, x->names.size());
if (mpv->size() != x->names.size())
arityError(x->names.size(), mpv->size());
Expand Down
2 changes: 2 additions & 0 deletions compiler/src/parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1141,6 +1141,8 @@ static bool bindingKind(int &bindingKind) {
bindingKind = REF;
else if (restore(p), keyword("alias"))
bindingKind = ALIAS;
else if (restore(p), keyword("forward"))
bindingKind = FORWARD;
else
return false;
return true;
Expand Down
3 changes: 3 additions & 0 deletions compiler/src/printer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,9 @@ static void printStatement(ostream &out, const Statement *x) {
case ALIAS :
out << "ALIAS";
break;
case FORWARD :
out << "FORWARD";
break;
default :
assert(false);
}
Expand Down
6 changes: 3 additions & 3 deletions lib-clay/algorithms/algorithms.clay
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ reduce(f:F, a:A) {
assert(hasNext?(iter));
var result = next(iter);
while (hasNext?(iter)) {
ref v = next(iter);
forward v = next(iter);
result = f(result, v);
}
return result;
Expand Down Expand Up @@ -88,7 +88,7 @@ overload select(a:A, f) {
assert(hasNext?(iter));
var result = next(iter);
while (hasNext?(iter)) {
ref v = next(iter);
forward v = next(iter);
if (f(v, result))
result = v;
}
Expand All @@ -101,7 +101,7 @@ overload select(a:A, f) {
assert(hasNext?(iter));
var result = &next(iter);
while (hasNext?(iter)) {
ref v = next(iter);
forward v = next(iter);
if (f(v, result^))
result = &v;
}
Expand Down
2 changes: 1 addition & 1 deletion lib-clay/sequences/sequences.clay
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ overload lesser?(a:A, b:B) {
while (hasNext?(i)) {
if (not hasNext?(j))
return false;
ref x, y = next(i), next(j);
forward x, y = next(i), next(j);
if (x != y)
return x < y;
}
Expand Down
4 changes: 2 additions & 2 deletions lib-clay/test/test.clay
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ private testOptions() {
}

[..T] ifPasses(expectFn, test: TestStatus, ..args:T) {
ref fn = dropValues(static countValues(..T) - 1, ..args);
forward fn = dropValues(static countValues(..T) - 1, ..args);
var preFailed = test.failed;
expectFn(test, ..takeValues(static countValues(..T) - 1, ..args));
if (test.failed == preFailed)
Expand Down Expand Up @@ -341,7 +341,7 @@ private runCase?(_case) = optionsInclude?("case", _case.name);
private colored?() = not(optionGiven?(testOptions(), "no-color"));

private optionsInclude?(name, elt){
ref seq = getOptions(testOptions(), name);
forward seq = getOptions(testOptions(), name);
return empty?(seq) or include?(seq, elt);
}

Expand Down
2 changes: 1 addition & 1 deletion test/permissive/main.clay
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ T(..args:A) --> returned:T {
alias n = RecordFieldCount(T);
..for (i in staticIntegers(static n)) {
ref field = staticIndex(returned, i);
ref value = nthValue(i, ..args);
var value = nthValue(i, ..args);
permissiveAssign(field, value);
}
}
Expand Down
Loading

0 comments on commit 3c0d006

Please sign in to comment.