We'll be collecting interesting newsgroup responses, assorted hints, and various documentation in this file.
To see the declarations you have attached to IdNodes, use the command
unpyth --decls FILE.ASTwhere FILE.AST is the file produced by your semantic analyzer. This will produce output that looks like this:
native class Any#0: ... native class Unit#1: ... etc. a#7 = 3 y#8 = 2 z#9 = 3 def f#10 (a#11, b#12): y#13 = a#11 + b#12 + z#9 return y#13 Declarations: #0: AnyType #1: UnitType etc. #7: VarDecl type: Any; #8: VarDecl type: Any; #9: VarDecl type: Any; #10: FuncDecl type: (Any, Any)->Any; #11: VarDecl inside #10; type: Any; #12: VarDecl inside #10; type: Any; #13: VarDecl inside #10; type: Any;
To see the types that your analyzer has attached to expressions, use
unpyth --types FILE.ASTwhich (when your analyzer is fully working) should produce something like this:
a: Int a = 3 b: String b = "abc" f: Int -> Int def f (x): return x +::Int 1 q = a +::Int 3 b = b +::String "x" c = f (a)::IntThe idea here is that `::TYPE' decorates function calls, operators, and a few other things. You will also see decorations when types are "unexpected". In the example above, the program gave all the integer literals the type Int. Had it not done so, you might see this instead:
a: Int a = 3::AnyThe notation "::?" indicates a null value for the type.
In all cases, you can see declarations and types for the native classes (which your analyzer sees as NativeClassDeclNodes) with the '--native' option:
unpyth --decls --native FILE.AST
For your convenience, we have specifialized this command specifically for this project. Here are some typical things you might want to do:
staff-prcs infoEach version will have a minor revision number, numbering consecutively from 1 (the oldest).
staff-prcs -r.N1 -r.N2
staff-prcs checkoutBy appending a "-r.N" option to this, you can check out a particular version.
addPrimitiveType
method in Type
is called
for you; you needn't do so. The only serious difference in processing
primitive types---represented in the program text as "native classes"---and
ordinary classes, therefore, is that for native classes, you get the
Decl
by either calling Type.getPrimitiveType
or
(probably easier) by calling .getPrimType()
on the native class
AST. For ordinary classes, you have to create a ClassDeclType
when you process the ClassDeclNode
.
In both cases, the name of the class (or native class)
should thenceforth be mapped to the Decl
that you fetched or
created. As you can see, Type
is a subtype of Decl
,
so that the Decl
for a class or native class C
doubles as the type that is denoted when you use C in a type
declaration. That is, when you see
class Thing: etc. X : (String, Thing) -> Anyall of the
IdNodes
for Thing
(actually, of course,
their semantic delegates) should point to the same ClassDeclType
.
Finally, for both a native class or ordinary class, you should add
all the Decl
s for members (attributes) of that class to its
Decl
(using .addAttribute
).
A. Yep. Actually it's quite easy. In Python (and Pyth), each variable attribute is both an instance variable AND a class variable. Consider:
class foo: x = 3 y = x # OK def bar (self): print y # ILLEGAL print self.y # OK a = foo () a.x = 19 print foo.x # prints 3 print a.x # prints 19
Compiler-wise, this is all easy. Just make sure that the enclosing declarative region inside bar is the global region, NOT the class foo.
You recommended that we use a versioning system (specifically PRCS). And I've gotten PRCS to work correctly, but I'm wondering how you can configure it so that only myself and my partner can access the repository (or the project) without making it visible (and editable) for everyone in the class.One option is to use CVS with ssh instead. To use PRCS, if we have student logins A and B, and A wishes to house the repository, making it available to B, you can use the following procedure
In A: # The repository is named SECRET_PASSWORD (replace with a secret name, # shared with B only). setenv PRCS_REPOSITORY SECRET_PASSWORD # Allow world r/w access to this repository prcs admin access # At this point, you get an interactive dialog that includes: prcs: Setting access permissions for repository foo/. prcs: Repository entry owner: cs164-aa prcs: Repository entry group: cs164 prcs: Repository entry access: prcs: Owner: read/write prcs: Group: no permission prcs: Other: no permission Enter a group[cs164] # Respond with just carriage return Group members' access, select(rwnq?)[n] # Respond "w" Other users' access, select(rnwq?)[n] # Respond "w"Now both partners, A and B do this:
# In ~/.local_cshrc file, put setenv PRCS_REPOSITORY ~A/SECRET_PASSWORD # Also, of course, make sure that .local_cshrc is protected: chmod go= ~/.local_cshrcThe procedure above assumes that A's home directory has the default protection, rwx--x--x, so that nobody can list its contents to see the name of the repository, but can read files in it if they know the names. If A wants to make his home directory readable, he should instead use
mkdir ~/secret chmod go=x ~/secretand modify the setenvs to
setenv PRCS_REPOSITORY ~A/secret/SECRET_PASSWORDUnfortunately, there are holes in this procedure (I won't tell you what, and I will spay or neuter, as appropriate, anyone who posts them), but it will do for state-government work.
class ProgramSem extends StaticSemantics { ProgramSem (AST source) { super (source); } ...
The createDelegate
method in SemanticBase
uses
a constructor with this signature to create a delegate. Do not change the
formal type from AST
to a more specific type.
A: Attributes are rather tricky. Clearly, you can't completely handle the case above until you know the type of x. Therefore, assigning a Decl to y has to wait until after you have decided on the types of all identifiers, which means after resolving other identifiers, handling "ID: TYPE" declarations, and attaching types to the formal parameters of functions.
So, you'll need yet another pass in which you process each reference SOMETHING.y by first computing the type, T, of SOMETHING (using still another recursive method!) and then looking up y in type T. If you do not find some kind of attribute Decl, simply use the null Decl as the decl value for y; otherwise, use the Decl for the attribute you find (VarAttrDecl or MethodDecl). Specifically:
getAttribute
) and its parent
types. If this fails, it is an error. [Actually, this is a recent
change to this rule back to its original form. To prevent mutiny,
we will not be testing the case where you access a non-existent
attribute of a The statements concerning inherited attributes and the like in the project handout are not quite right. The truth actually simplifies your task, so here it is:
class A: a = 3 b = a + 2but this does not:
class A: a = 3 class B(A): b = a + 2 # Error: a not defined.So let's us do the same.
On the other hand, once the class is complete and you need to look up 'a' in something whose type is declared to be 'B', you will need to follow the parent-class chain.
If class B inherits from A, then:
def f(x): x = 5does the assignment to
x
create a new
Decl? Or does it refer to the same Decl as the parameter x
?
A: According to Python semantics (and by default, therefore, for Pyth), these are the same variable in the same region.
Any
is the type of "a value that we know nothing about."
x: String y: String z: String x < y < zWhat type should you ascribe to the "<" operators? According to Python, a comparison in isolation yields a boolean value, which we are representing instead as the Ints 0 and 1. However, the meaning of the whole comparison is that if x < y, it is the (String) value of y, and not the Int value of the comparison, that is compared to z. So you could argue that the type of the first "<" could be either String or Int.
Let us declare by fiat that the type of all the "<" operators here is Int.
Page was last modified on Tue Apr 5 15:40:27 2005.