Function.pm 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. package Logos::Generator::Base::Function;
  2. use strict;
  3. use Logos::Generator;
  4. use Logos::Util;
  5. sub originalFunctionName {
  6. my $self = shift;
  7. my $function = shift;
  8. return Logos::sigil("orig").$function->group->name."\$".$function->name;
  9. }
  10. sub newFunctionName {
  11. my $self = shift;
  12. my $function = shift;
  13. return Logos::sigil("function").$function->group->name."\$".$function->name;
  14. }
  15. sub originalFunctionCall {
  16. my $self = shift;
  17. my $function = shift;
  18. my $args = shift;
  19. my $return = $self->originalFunctionName($function)."(";
  20. if (!$args) {
  21. $args = [];
  22. for(@{$function->args}) {
  23. push(@$args, $self->getArgumentName($_));
  24. }
  25. $return .= join(", ", @$args);
  26. } else {
  27. $return .= $args;
  28. }
  29. $return .= ")";
  30. return $return;
  31. }
  32. sub declaration {
  33. my $self = shift;
  34. my $function = shift;
  35. my $return = "";
  36. $return .= "_disused static ".$function->retval." (*".$self->originalFunctionName($function).")(".join(", ", @{$function->args})."); ";
  37. $return .= "static ".$function->retval." ".$self->newFunctionName($function)."(".join(", ", @{$function->args}).")";
  38. return $return;
  39. }
  40. sub initializers {
  41. ::fileError(-1, "Base::Function does not implement initializers");
  42. }
  43. ##########
  44. # extras #
  45. ##########
  46. sub getArgumentName {
  47. my $self = shift;
  48. my $arg = shift;
  49. # Split the argument string by spaces
  50. my $argArray = $self->notSoSmartSplit($arg, " ");
  51. # Try to get the name of the last element of the array if it is a function pointer
  52. my $return = $self->escapeFunctionPointer(@$argArray[-1]);
  53. # Separate the name from trailing vector size
  54. $return =~ s/\[/ \[/g;
  55. # Trimm spaces or asterisks from the start
  56. while (substr($return, 0, 1) eq " " || substr($return, 0, 1) eq "*") {
  57. $return = substr($return, 1, length($return));
  58. }
  59. # Split the resulting string by spaces
  60. $argArray = $self->notSoSmartSplit($return, " ");
  61. # Get the first element
  62. my $return = @$argArray[0];
  63. return $return;
  64. }
  65. sub escapeFunctionPointer {
  66. my $self = shift;
  67. my $arg = shift;
  68. if($arg !~ /\(\s*[*^]/) {
  69. return $arg;
  70. }
  71. my $substring = $arg;
  72. my ($opening, $closing) = matchedParenthesisSet($substring, 0);
  73. my $offset = 0;
  74. while(1) {
  75. # We want to put the parameter name right before the closing ) in the deepest nested set if we found a (^ or (*.
  76. $substring = substr($substring, $opening, $closing - $opening - 1);
  77. $offset += $opening;
  78. my ($newopening, $newclosing) = matchedParenthesisSet($substring, 0);
  79. last if !defined $newopening;
  80. $opening = $newopening;
  81. $closing = $newclosing;
  82. }
  83. return substr($arg, $offset, $closing-$opening-1);
  84. }
  85. #for a lack of Logos::Util::matchedDelimiterSet()
  86. sub notSoSmartSplit {
  87. my $self = shift;
  88. my $argumentString = shift;
  89. my $delimiter = shift;
  90. # Default to commas
  91. if (!$delimiter) {
  92. $delimiter = ",";
  93. }
  94. $argumentString .= $delimiter; #uber hax
  95. # curved brackets or parens ()
  96. my $parensLevel = 0;
  97. # squared brackets or crotchets []
  98. my $crotchetsLevel = 0;
  99. # curly brackets or braces {}
  100. my $bracesLevel = 0;
  101. # angled brackets or chevrons <>
  102. my $chevronsLevel = 0;
  103. my $token = "";
  104. my $pc = "";
  105. my $args = [];
  106. foreach my $c (split //, $argumentString) {
  107. if ($c eq $delimiter) {
  108. # If at root level, end token, push to array and start again
  109. if ($parensLevel == 0 && $crotchetsLevel == 0 && $bracesLevel == 0 && $chevronsLevel == 0) {
  110. push(@$args, $token);
  111. $pc = $c;
  112. $token = "";
  113. next;
  114. }
  115. }
  116. if ($c eq "(") {
  117. $parensLevel++;
  118. }
  119. if ($c eq ")") {
  120. $parensLevel--;
  121. }
  122. if ($c eq "[") {
  123. $crotchetsLevel++;
  124. }
  125. if ($c eq "]") {
  126. $crotchetsLevel--;
  127. }
  128. if ($c eq "{") {
  129. $bracesLevel++;
  130. }
  131. if ($c eq "}") {
  132. $bracesLevel--;
  133. }
  134. if ($c eq "<") {
  135. $chevronsLevel++;
  136. }
  137. if ($c eq ">") {
  138. $chevronsLevel--;
  139. }
  140. #skip redundant empty spaces
  141. if (($pc eq $delimiter && $c eq " ") || ($pc eq " " && $c eq " ")) {
  142. next;
  143. }
  144. # Concatenate char to token
  145. $token .= $c;
  146. #save previous char
  147. $pc = $c;
  148. } # foreach
  149. return $args;
  150. }
  151. 1;