diff --git a/src/main/java/chocopy/pa3/CodeGenImpl.java b/src/main/java/chocopy/pa3/CodeGenImpl.java
index 7d6c69f4b7d3c01a43b39c518efe97e5a2026c48..4d5fdcd194cc8f7b49370649fd66e5cfadb8358f 100644
--- a/src/main/java/chocopy/pa3/CodeGenImpl.java
+++ b/src/main/java/chocopy/pa3/CodeGenImpl.java
@@ -1,16 +1,14 @@
 package chocopy.pa3;
 
+import java.util.ArrayList;
 import java.util.List;
+import java.util.Objects;
 
 import chocopy.common.analysis.SymbolTable;
 import chocopy.common.analysis.AbstractNodeAnalyzer;
-import chocopy.common.astnodes.Stmt;
-import chocopy.common.astnodes.ReturnStmt;
-import chocopy.common.codegen.CodeGenBase;
-import chocopy.common.codegen.FuncInfo;
-import chocopy.common.codegen.Label;
-import chocopy.common.codegen.RiscVBackend;
-import chocopy.common.codegen.SymbolInfo;
+import chocopy.common.analysis.types.SymbolType;
+import chocopy.common.astnodes.*;
+import chocopy.common.codegen.*;
 
 import static chocopy.common.codegen.RiscVBackend.Register.*;
 
@@ -60,7 +58,6 @@ public class CodeGenImpl extends CodeGenBase {
         backend.emitSW(ZERO, SP, 4, "Top saved RA is 0.");
         backend.emitADDI(FP, SP, 2 * backend.getWordSize(),
                          "Set FP to previous SP.");
-
         for (Stmt stmt : statements) {
             stmt.dispatch(stmtAnalyzer);
         }
@@ -80,7 +77,13 @@ public class CodeGenImpl extends CodeGenBase {
     protected void emitUserDefinedFunction(FuncInfo funcInfo) {
         backend.emitGlobalLabel(funcInfo.getCodeLabel());
         StmtAnalyzer stmtAnalyzer = new StmtAnalyzer(funcInfo);
+        // Prologue:
+        backend.emitSW(FP, SP, 0, "Save old FP");
+        backend.emitSW(RA, SP, -4, "Save RA");
+        backend.emitADDI(SP, SP, -8, "Increment stack pointer 2 places");
+        backend.emitADDI(FP, SP, 4, "FP is one slot below top of stack");
 
+        // Emit code for function stmts
         for (Stmt stmt : funcInfo.getStatements()) {
             stmt.dispatch(stmtAnalyzer);
         }
@@ -89,11 +92,13 @@ public class CodeGenImpl extends CodeGenBase {
         backend.emitLocalLabel(stmtAnalyzer.epilogue, "Epilogue");
 
         // FIXME: {... reset fp etc. ...}
+        backend.emitLW(RA, FP, 0, "Restore RA");
+        backend.emitLW(FP, FP, 4, "Restore old FP");
         backend.emitJR(RA, "Return to caller");
     }
 
     /** An analyzer that encapsulates code generation for statments. */
-    private class StmtAnalyzer extends AbstractNodeAnalyzer<Void> {
+    private class StmtAnalyzer extends AbstractNodeAnalyzer<Object> {
         /*
          * The symbol table has all the info you need to determine
          * what a given identifier 'x' in the current scope is. You can
@@ -158,6 +163,97 @@ public class CodeGenImpl extends CodeGenBase {
             return null;
         }
 
+        @Override
+        public Void analyze(ExprStmt exprStmt) {
+            exprStmt.expr.dispatch(this);
+            return null;
+        }
+
+
+        @Override
+        public Void analyze(CallExpr callExpr) {
+            // NOT DONE
+            if (globalSymbols.get(callExpr.function.name) instanceof FuncInfo) {
+                FuncInfo func =  (FuncInfo) globalSymbols.get(callExpr.function.name);
+                for (Expr e : callExpr.args) {
+                    backend.emitADDI(SP, SP, -4, "Increment stack ptr by 1");
+                    e.dispatch(this);
+                }
+                // Push parameters onto stack
+                backend.emitJAL(func.getCodeLabel(), "Invoke function");
+
+                // Restore SP
+                for (Expr e : callExpr.args) {
+                    backend.emitADDI(SP, SP, 4, "Increment stack ptr by 1");
+                }
+
+            }
+            return null;
+        }
+
+        @Override
+        public Void analyze(BooleanLiteral literal) {
+            /* Push boolean literal onto stack, incrementing stack pointer*/
+            backend.emitLA(A0, constants.getBoolConstant(literal.value), "Load boolean literal into a0");
+            backend.emitSW(A0, SP, 0, "Push on stack");
+            return null;
+        }
+
+        @Override
+        public Void analyze(IntegerLiteral literal) {
+            backend.emitLA(A0, constants.getIntConstant(literal.value), "Load integer literal into a0");
+            backend.emitSW(A0, SP, 0, "Push on stack");
+            return null;
+        }
+
+        @Override
+        public Void analyze(StringLiteral literal) {
+            backend.emitLA(A0, constants.getStrConstant(literal.value), "Load string literal into a0");
+            backend.emitSW(A0, SP, 0, "Push on stack");
+            return null;
+        }
+
+        @Override
+        public Void analyze(Identifier id) {
+            // NOT DONE
+            SymbolInfo ident;
+            // global var case
+            if (this.funcInfo == null) {
+                ident = globalSymbols.get(id.name);
+                backend.emitLW(A0, ((GlobalVarInfo) ident).getLabel(), "Load identifier");
+                backend.emitSW(A0, SP, 0, "Push to stack");
+            } else { // local variable
+                 ident = this.funcInfo.getSymbolTable().get(id.name);
+            }
+            return null;
+        }
+
+        @Override
+        public Void analyze(BinaryExpr binaryExpr) {
+            switch (binaryExpr.operator) {
+                case "+":
+                    // needs to be extended string concatenation, list concatenation
+                    backend.emitADDI(SP, SP, -4, "Increment stack ptr for first operand");
+                    binaryExpr.left.dispatch(this);
+                    backend.emitADDI(SP, SP, -4, "Increment stack ptr for second operand");
+                    binaryExpr.right.dispatch(this);
+                    backend.emitLW(T0, SP, 0, "Load operand 2 into t0");
+                    backend.emitLW(T0, T0, "@.__int__", "Load value of operand 2 into t0");
+                    backend.emitADDI(SP, SP, 4, "Decrement stack ptr for first operand");
+                    backend.emitLW(T1, SP, 0, "Load operand 1 into t1");
+                    backend.emitLW(T1, T1, "@.__int__", "Load value of operand 1 into t1");
+                    backend.emitADDI(SP, SP, 4, "Decrement stack ptr for second operand");
+                    backend.emitADD(T0, T0, T1, "Add operands");
+                    backend.emitJAL(((FuncInfo) globalSymbols.get("int-alloc")).getCodeLabel(), "Jump to int alloc routine");
+                    backend.emitSW(T0, SP, 0, "Push result on stack");
+            }
+
+            return null;
+        }
+        @Override
+        public Void analyze(AssignStmt assignStmt) {
+            return null;
+        }
         // FIXME: More, of course.
 
     }
@@ -186,6 +282,17 @@ public class CodeGenImpl extends CodeGenBase {
      *
      */
     protected void emitCustomCode() {
+        backend.emitGlobalLabel(new Label("int-alloc"));
+        backend.emitLA(A0, intClass.getPrototypeLabel(), "Get int prototype address");
+        backend.emitJAL(objectAllocLabel, "Allocate int");
+
+        FuncInfo allocInt = makeFuncInfo("int-alloc", 0, SymbolType.OBJECT_TYPE,
+                globalSymbols, null, this::emitStdFunc);
+        allocInt.addParam(makeStackVarInfo("arg", SymbolType.OBJECT_TYPE,
+                null, allocInt));
+        functions.add(allocInt);
+        System.out.println(allocInt.getBaseName());
+        globalSymbols.put(allocInt.getBaseName(), allocInt);
         emitErrorFunc(errorNone, "Operation on None");
         emitErrorFunc(errorDiv, "Divison by zero");
         emitErrorFunc(errorOob, "Index out of bounds");