Skip to content

Commit

Permalink
Merge branch 'marcelomamorim-feature/grupo-4-tac-generation'
Browse files Browse the repository at this point in the history
  • Loading branch information
rbonifacio committed Nov 23, 2023
2 parents 1fdd13f + 778be75 commit e3d566b
Show file tree
Hide file tree
Showing 10 changed files with 610 additions and 90 deletions.
17 changes: 0 additions & 17 deletions .github/worflows/ci.yml

This file was deleted.

17 changes: 17 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
name: CI
on:
pull_request:
push:
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Setup JDK
uses: actions/setup-java@v3
with:
distribution: temurin
java-version: 11
- name: Build and Test
run: sbt -v +test
7 changes: 7 additions & 0 deletions docs/tac/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# O que foi implementado agora no primeiro semestre de 2023 (2023-1)?

- Prettier Printer de TAC

# O que fica como implementações para o futuro?

-
125 changes: 88 additions & 37 deletions src/main/scala/br/unb/cic/oberon/codegen/TACodeGenerator.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ object TACodeGenerator extends CodeGenerator[List[TAC]] {
private var tc = new TypeChecker()
private var expVisitor = new ExpressionTypeChecker(tc)

private val typeByteSize: Map[Type, Int] =
Map(IntegerType -> 4,
RealType -> 4
)

override def generateCode(module: OberonModule): List[TAC] = {
load_vars(module.variables, module.constants)
module.stmt match {
Expand All @@ -18,46 +23,53 @@ object TACodeGenerator extends CodeGenerator[List[TAC]] {
}
}

// A geração de código de procedure foi mais difícil do que imaginamos, tivemos algumas dúvidas que não conseguimos resolver pesquisando.
// def generateProcedure(proc: Procedure, insts: List[TAC]): (Address, List[TAC]) = {}

def generateStatement(stmt: Statement, insts: List[TAC]): List[TAC] = {
stmt match {
case AssignmentStmt(designator, exp) =>
val (t, insts1) = generateExpression(exp, insts)
designator match {
case VarAssignment(varName) =>
val v = Name(varName, expVisitor.checkExpression(exp).get)
return insts1 :+ CopyOp(t, v, "")

insts1 :+ CopyOp(t, v, "")
case ArrayAssignment(array, index) =>
val (a, insts2) = generateExpression(array, insts1)
val (i, insts3) = generateExpression(index, insts2)
return insts3 :+ ListSet(t, i, a, "")

val offset = getArrayOffset(a, index)
insts2 :+ ArraySet(t, offset, a, "")
case PointerAssignment(pointerName) =>
val p = Name(pointerName, LocationType)
return insts1 :+ SetPointer(t, p, "")

case RecordAssignment(_, _) =>
throw new Exception("Records não foram implementados!")
insts1 :+ SetPointer(t, p, "")
case RecordAssignment(record,field) =>
val (name: Name, insts2: List[TAC]) = generateExpression(record, insts1)
val offset = getRecordOffset(name, field)
insts2 :+ RecordSet(t, offset, name, "")
}

case SequenceStmt(stmts) =>
stmts.foldLeft(insts) { (acc, stm) =>
generateStatement(stm, acc)
}
case ProcedureCallStmt(name, argsExps) => {
val argsTAC = argsExps.map(exp => generateExpression(exp, List()))
val TACops = argsTAC.flatMap {
case (_, tac: List[TAC]) => tac
}
val param = argsTAC.map(_._1).map {
case t: Temporary => (List[TAC](), Param(t, ""))
case name1: Name =>
val t = new Temporary(name1.t)
(List(MoveOp(name1, t, "")), Param(t, ""))

// No final não conseguimos implementar a geração de procedures
// case ProcedureCallStmt(name, argsExps) =>
// val (args, argInsts) = argsExps.foldLeft((List[Address](),insts)) {
// (acc, expr) =>
// val (address, ops) = TACodeGenerator.generateExpression(expr, acc._2)
// (acc._1 :+ address, ops)
// }
// val params = args.map(x => Param(x, ""))
// return argInsts ++ params :+ Call(name, args.length, "")
case const: Constant =>
val t = new Temporary(const.t)
(List(MoveOp(const, t, "")), Param(t, ""))

}
val paramops = param.map(_._1)
val paramops2 = paramops.flatten
val param2 = param.map(_._2)

insts ++ TACops ++ paramops2 ++ param2 :+ Call(name, argsExps.length, "")

}
case IfElseStmt(condition, thenStmt, elseStmt) =>
val l1 = LabelGenerator.generateLabel
val l2 = if (elseStmt.isDefined) LabelGenerator.generateLabel else ""
Expand Down Expand Up @@ -231,15 +243,11 @@ object TACodeGenerator extends CodeGenerator[List[TAC]] {

case ExitStmt() =>
return insts :+ Exit("")

case ForEachStmt(_, _, _) =>
throw new Exception("ForEachStmt não foi implementado")

case ElseIfStmt(_, _) =>
throw new Exception("ElseIfStmt não foi implementado")

case NewStmt(_) =>
throw new Exception("NewStmt não foi implementado")
case NewStmt(varName) =>
val (variable: Address, insts1) = generateExpression(VarExpression(varName), insts)
insts1 :+ New(variable, "")
case MetaStmt(_) =>
throw new Exception("MetaStmt não foi implementado")
}
}

Expand Down Expand Up @@ -396,15 +404,18 @@ object TACodeGenerator extends CodeGenerator[List[TAC]] {
val (a, insts1) = generateExpression(array, insts)
val (i, insts2) = generateExpression(index, insts1)
val t = new Temporary(expVisitor.checkExpression(expr).get)
return (t, insts2 :+ ListGet(a, i, t, ""))

return (t, insts2 :+ ArrayGet(a, i, t, ""))
case PointerAccessExpression(name) =>
val p = Name(name, LocationType)
val t = new Temporary(expVisitor.checkExpression(expr).get)
return (t, insts :+ GetValue(p, t, ""))

case FieldAccessExpression(exp, name) =>
throw new Exception("FieldAccessExpression não foi implementada!")
case FieldAccessExpression(record, field) =>
val (name: Name, insts1: List[TAC]) = generateExpression(record, insts)
val offset = getRecordOffset(name, field)
val fieldtype = getFieldType(name, field)
val t = new Temporary(fieldtype)
(t, insts1 :+ RecordGet(name, offset, t, ""))
}
}

Expand Down Expand Up @@ -452,7 +463,43 @@ object TACodeGenerator extends CodeGenerator[List[TAC]] {

case None => insts1
}
}
}

private def getArrayOffset(array: Address, index: Expression): Address = {
val arrayType = array match {
case Name(_, ArrayType(_, baseType)) => baseType
}
val index1 = index match {
case IntValue(value) => value
}

val offset = typeByteSize.getOrElse(arrayType, 0) * index1


Constant(offset.toString, IntegerType)

}

private def getRecordOffset(record: Name, field: String): Constant = {
val variables: List[VariableDeclaration] = record.t.asInstanceOf[RecordType].variables
val targetIndex: Int = variables.indexWhere(_.name == field)
val variables2: List[VariableDeclaration] = variables.take(targetIndex + 1)

val offset: Int = variables2.map {
case VariableDeclaration(_, ArrayType(size, vartype)) => size * typeByteSize.getOrElse(vartype, 0)
case VariableDeclaration(_, vartype) => typeByteSize.getOrElse(vartype, 0)
}.sum

Constant(offset.toString, IntegerType)
}

private def getFieldType(record: Name, field: String): Type = {
val variables: List[VariableDeclaration] = record.t.asInstanceOf[RecordType].variables
variables.find(_.name == field).map(_.variableType) match {
case Some(ty) => ty
case None => throw new IllegalArgumentException("All variables need a Type")
}
}


def load_vars(
Expand All @@ -462,7 +509,11 @@ object TACodeGenerator extends CodeGenerator[List[TAC]] {
tc.checkModule(OberonModule("test", Set(), List(), consts, vars, List(), List(), None))
}

// somente para testes

def load_userTypes_and_vars(userTypes: List[UserDefinedType], vars: List[VariableDeclaration], consts: List[ASTConstant] = List()): Unit = {
tc.checkModule(OberonModule("test", Set(), userTypes, consts, vars, List(), List(), None))
}

def reset(): Unit = {
tc = new TypeChecker()
expVisitor = new ExpressionTypeChecker(tc)
Expand Down
18 changes: 9 additions & 9 deletions src/main/scala/br/unb/cic/oberon/ir/tac/Address.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,29 @@ package br.unb.cic.oberon.ir.tac

import br.unb.cic.oberon.ir.ast.{Type}

class Address(t: Type) {}
class Address(t: Type){}

case class Name(id: String, t: Type) extends Address(t) {}
case class Name(id: String, t:Type) extends Address(t){}

case class Constant(value: String, t: Type) extends Address(t) {}
case class Constant(value: String, t: Type) extends Address(t){}

class Temporary(t: Type, num: Int = 0, manual: Boolean = false)
extends Address(t) {
// num e manual somente para testes
case class Temporary(t: Type, num: Int = 0, manual: Boolean = false) extends Address(t){
//num e manual somente para testes
import Temporary._
var number = num
if (!manual) {
number = Temporary.counter
Temporary.counter += 1
}


def canEqual(a: Any): Boolean = a.isInstanceOf[Temporary]

override def equals(that: Any): Boolean = {
that match {
case that: Temporary =>
that.canEqual(this) &&
this.number == that.number
this.number == that.number

case _ => false
}
Expand All @@ -34,5 +34,5 @@ class Temporary(t: Type, num: Int = 0, manual: Boolean = false)
object Temporary {
var counter = 0

def reset(): Unit = { counter = 0 } // somente para testes
}
def reset(): Unit = {counter = 0}//somente para testes
}
26 changes: 18 additions & 8 deletions src/main/scala/br/unb/cic/oberon/ir/tac/TAC.scala
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,12 @@ case class NegOp(s1: Address, dest: Address, label: String)
case class NotOp(s1: Address, dest: Address, label: String)
extends UniOp(s1, dest, label) {}


case class CopyOp(s1: Address, dest: Address, label: String)
extends TAC(label) {}

case class MoveOp(s1: Address, dest: Address, label: String) extends TAC(label) {}

case class NOp(label: String) extends TAC(label) {}

case class Jump(destLabel: String, label: String) extends TAC(label) {}
Expand Down Expand Up @@ -80,8 +83,7 @@ case class Call(procLabel: String, n: Int, label: String) extends TAC(label) {}

case class Return(s1: Address, label: String) extends TAC(label) {}

case class ListGet(list: Address, index: Address, dest: Address, label: String)
extends TAC(label) {}
case class New(s1: Address, label: String) extends TAC(label) {}

case class ListSet(
s1: Address,
Expand All @@ -90,14 +92,22 @@ case class ListSet(
label: String
) extends TAC(label) {}

case class SetPointer(s1: Address, destPointer: Address, label: String)
extends TAC(label) {}
case class ArrayGet(list: Address, offset: Address, dest: Address, label: String) extends TAC(label) {}

case class GetValue(sPointer: Address, dest: Address, label: String)
extends TAC(label) {}
case class ArraySet(s1: Address, offset: Address, listDest: Address, label: String) extends TAC(label) {}

case class SetValue(s1: Address, destPointer: Address, label: String)
extends TAC(label) {}

case class RecordGet(record: Address, offset: Address, dest: Address, label: String) extends TAC(label) {}

case class RecordSet(s1: Address, offset: Address, record: Address, label: String) extends TAC(label) {}



case class SetPointer(s1: Address, destPointer: Address, label: String) extends TAC(label) {}

case class GetValue(sPointer: Address, dest: Address, label: String) extends TAC(label) {}

case class SetValue(s1: Address, destPointer: Address, label: String) extends TAC(label) {}

class SysCall(label: String) extends TAC(label) {}

Expand Down
Loading

0 comments on commit e3d566b

Please sign in to comment.